abaqusMeshSet.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2023 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "abaqusMeshSet.H"
29 #include "stringOps.H"
30 #include "Fstream.H"
31 #include "SpanStream.H"
32 #include "meshSearch.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39  defineTypeNameAndDebug(abaqusMeshSet, 0);
40  addToRunTimeSelectionTable(sampledSet, abaqusMeshSet, word);
41 }
42 
43 
44 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
45 
46 bool Foam::abaqusMeshSet::readCoord(ISstream& is, vector& coord) const
47 {
48  string buffer;
49 
50  do
51  {
52  //buffer.clear();
53 
54  is.getLine(buffer);
55 
56  const auto elems = buffer.find("*ELEMENT");
57 
58  if (elems != std::string::npos)
59  {
60  buffer.clear();
61  break;
62  }
63 
64  // Trim out any '*' comments
65  const auto pos = buffer.find('*');
66  if (pos != std::string::npos)
67  {
68  buffer.erase(pos);
69  }
71  }
72  while (buffer.empty() && is.good());
73 
74  if (buffer.empty())
75  {
76  return false;
77  }
78 
79  const auto strings = stringOps::split(buffer, ',');
80 
81  if (strings.size() != 4)
82  {
84  << "Read error: expected format int, float, float, float"
85  << " but read buffer " << buffer
86  << exit(FatalError);
87  }
88 
89  for (int i = 0; i <= 2; ++i)
90  {
91  // Swallow i=0 for node label
92  const auto& s = strings[i+1].str();
93  ISpanStream buf(s.data(), s.length());
94  buf >> coord[i];
95  }
96 
97  coord *= scale_;
98 
99  return true;
100 }
101 
102 
103 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
104 
105 void Foam::abaqusMeshSet::calcSamples
106 (
107  DynamicList<point>& samplingPts,
108  DynamicList<label>& samplingCells,
109  DynamicList<label>& samplingFaces,
110  DynamicList<label>& samplingSegments,
111  DynamicList<scalar>& samplingCurveDist
112 ) const
113 {
114  DebugInfo
115  << "abaqusMeshSet : sampling " << sampleCoords_.size() << " points"
116  << endl;
117 
118  List<bool> found(sampleCoords_.size(), false);
119 
120  forAll(sampleCoords_, samplei)
121  {
122  const vector& pt = sampleCoords_[samplei];
123 
124  label celli = searchEngine().findCell(pt);
125  if (celli != -1)
126  {
127  found[samplei] = true;
128 
129  samplingPts.append(pt);
130  samplingCells.append(celli);
131  samplingFaces.append(-1);
132  samplingSegments.append(0);
133  samplingCurveDist.append(1.0*samplei);
134  }
135  }
136 
137  Pstream::listCombineAllGather(found, orEqOp<bool>());
138 
139  DynamicList<label> lost;
140  forAll(found, samplei)
141  {
142  if (!found[samplei]) lost.append(samplei);
143  }
144 
145  const label nFound = sampleCoords_.size() - lost.size();
146  label nOutOfBounds = 0;
147 
148  if (Pstream::parRun())
149  {
150  typedef Tuple2<label, Tuple2<label, scalar>> procCellDist;
151  List<procCellDist> pcd(lost.size(), procCellDist(-1, {-1, GREAT}));
152  forAll(pcd, i)
153  {
154  const label samplei = lost[i];
155  const vector& pt0 = sampleCoords_[samplei];
156  const label celli = searchEngine().findNearestCell(pt0);
157  const vector& pt1 = mesh().cellCentres()[celli];
158  const scalar distSqr = magSqr(pt1 - pt0);
159  pcd[i] = procCellDist(Pstream::myProcNo(), {celli, distSqr});
160  }
161 
163  (
164  pcd,
165  [](procCellDist& x, const procCellDist& y)
166  {
167  // Select item with smallest distance
168  if (y.second().second() < x.second().second())
169  {
170  x = y;
171  }
172  }
173  );
174 
175  forAll(pcd, i)
176  {
177  const label samplei = lost[i];
178 
179  if (pcd[i].second().second() < maxDistSqr_)
180  {
181  if (pcd[i].first() == Pstream::myProcNo())
182  {
183  const label celli = pcd[i].second().first();
184  const vector& pt1 = mesh().cellCentres()[celli];
185 
186  samplingPts.append(pt1);
187  samplingCells.append(celli);
188  samplingFaces.append(-1);
189  samplingSegments.append(0);
190  samplingCurveDist.append(1.0*samplei);
191  }
192  }
193  else
194  {
195  // Insert points that have not been found as null points
196  if (Pstream::master())
197  {
198  samplingPts.append(sampleCoords_[samplei]);
199  samplingCells.append(-1);
200  samplingFaces.append(-1);
201  samplingSegments.append(0);
202  samplingCurveDist.append(1.0*samplei);
203  ++nOutOfBounds;
204  }
205  }
206  }
207  }
208  else
209  {
210  // Serial running
211 
212  forAll(lost, i)
213  {
214  const label samplei = lost[i];
215  const vector& pt0 = sampleCoords_[samplei];
216  const label celli = searchEngine().findNearestCell(pt0);
217  const vector& pt1 = mesh().cellCentres()[celli];
218  const scalar distSqr = magSqr(pt1 - pt0);
219 
220  if (distSqr < maxDistSqr_)
221  {
222  samplingPts.append(pt1);
223  samplingCells.append(celli);
224  samplingFaces.append(-1);
225  samplingSegments.append(0);
226  samplingCurveDist.append(1.0*samplei);
227  }
228  else
229  {
230  // Insert points that have not been found as null points
231  samplingPts.append(sampleCoords_[samplei]);
232  samplingCells.append(-1);
233  samplingFaces.append(-1);
234  samplingSegments.append(0);
235  samplingCurveDist.append(1.0*samplei);
236  ++nOutOfBounds;
237  }
238  }
239  }
240 
242  << "Sample size : " << sampleCoords_.size() << nl
243  << "Lost samples : " << nOutOfBounds << nl
244  << "Recovered samples : "
245  << (sampleCoords_.size() - nOutOfBounds - nFound) << nl
246  << endl;
247 
248 
249  if (nOutOfBounds)
250  {
252  << "Identified " << nOutOfBounds << " out-of-bounds points"
253  << endl;
254  }
255 }
256 
257 
258 void Foam::abaqusMeshSet::genSamples()
259 {
260  // Storage for sample points
261  DynamicList<point> samplingPts;
262  DynamicList<label> samplingCells;
263  DynamicList<label> samplingFaces;
264  DynamicList<label> samplingSegments;
265  DynamicList<scalar> samplingCurveDist;
266 
267  calcSamples
268  (
269  samplingPts,
270  samplingCells,
271  samplingFaces,
272  samplingSegments,
273  samplingCurveDist
274  );
275 
276  samplingPts.shrink();
277  samplingCells.shrink();
278  samplingFaces.shrink();
279  samplingSegments.shrink();
280  samplingCurveDist.shrink();
281 
282  setSamples
283  (
284  std::move(samplingPts),
285  std::move(samplingCells),
286  std::move(samplingFaces),
287  std::move(samplingSegments),
288  std::move(samplingCurveDist)
289  );
290 
291  if (debug > 1)
292  {
293  write(Info);
294  }
295 }
296 
297 
298 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
299 
301 (
302  const word& name,
303  const polyMesh& mesh,
304  const meshSearch& searchEngine,
305  const dictionary& dict
306 )
307 :
308  sampledSet(name, mesh, searchEngine, dict),
309  scale_(dict.getOrDefault<scalar>("scale", 1)),
310  sampleCoords_(),
311  maxDistSqr_(sqr(dict.getOrDefault<scalar>("maxDist", 0)))
312 {
313  if (Pstream::master())
314  {
315  const fileName inputFile(dict.get<fileName>("file").expand());
316  IFstream pointsFile(inputFile);
317 
318  if (!pointsFile.good())
319  {
321  << "Unable to find file " << pointsFile.name()
322  << abort(FatalIOError);
323  }
324 
325  // Read the points file
326  DynamicList<point> coords;
327  vector c;
328  while (readCoord(pointsFile, c))
329  {
330  coords.append(c);
331  }
332 
333  sampleCoords_.transfer(coords);
334  }
335 
336  Pstream::broadcast(sampleCoords_);
337 
338  DebugInfo
339  << "Number of sample points: " << sampleCoords_.size() << nl
340  << "Sample points bounds: " << boundBox(sampleCoords_) << endl;
341 
342  genSamples();
343 }
344 
345 
346 // ************************************************************************* //
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
Input/output streams with (internal or external) character storage.
Foam::SubStrings< StringType > split(const StringType &str, const char delim, const bool keepEmpty=false)
Split string into sub-strings at the delimiter character.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
label findNearestCell(const point &location, const label seedCelli=-1, const bool useTreeSearch=true) const
Find nearest cell in terms of cell centre.
Definition: meshSearch.C:713
void transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition: List.C:326
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:517
dimensionedSymmTensor sqr(const dimensionedVector &dv)
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1049
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1074
Macros for easy insertion into run-time selection tables.
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
dimensionedScalar pos(const dimensionedScalar &ds)
scalar y
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
void inplaceTrimRight(std::string &s)
Trim trailing whitespace inplace.
Definition: stringOps.C:979
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
label findCell(const point &location, const label seedCelli=-1, const bool useTreeSearch=true) const
Find cell containing location.
Definition: meshSearch.C:759
#define DebugInFunction
Report an information message using Foam::Info.
abaqusMeshSet(const word &name, const polyMesh &mesh, const meshSearch &searchEngine, const dictionary &dict)
Construct from dictionary.
Vector< scalar > vector
Definition: vector.H:57
static void listCombineAllGather(List< T > &values, const CombineOp &cop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Same as Pstream::listCombineReduce.
Definition: Pstream.H:304
const vectorField & cellCentres() const
errorManip< error > abort(error &err)
Definition: errorManip.H:139
#define DebugInfo
Report an information message using Foam::Info.
int debug
Static debugging option.
defineTypeNameAndDebug(combustionModel, 0)
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
const dimensionedScalar c
Speed of light in a vacuum.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
messageStream Info
Information stream (stdout output on master, null elsewhere)
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
bool found
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
Namespace for OpenFOAM.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...