faMeshTools.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) 2012-2016 OpenFOAM Foundation
9  Copyright (C) 2015-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "faMeshTools.H"
30 #include "faBoundaryMeshEntries.H"
31 #include "areaFields.H"
32 #include "edgeFields.H"
33 #include "polyMesh.H"
34 #include "processorFaPatch.H"
35 
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
37 
39 {
40  auto& obr = const_cast<objectRegistry&>(mesh.thisDb());
41 
42  // Checkout by name (casting ambiguity)
43  obr.checkOut(faMesh::typeName);
44  obr.checkOut("faBoundaryMesh");
45  obr.checkOut("faSchemes");
46  obr.checkOut("faSolution");
47 }
48 
49 
51 {
52  (void)mesh.globalData();
53 
54  (void)mesh.Le();
55  (void)mesh.magLe();
56  (void)mesh.areaCentres();
57  (void)mesh.edgeCentres();
58 
59  (void)mesh.faceAreaNormals();
60  (void)mesh.edgeAreaNormals();
61  (void)mesh.pointAreaNormals();
62  (void)mesh.faceCurvatures();
63  (void)mesh.edgeTransformTensors();
64 }
65 
66 
68 (
69  const IOobject& io,
70  const polyMesh& pMesh,
71  const bool masterOnlyReading,
72  const bool verbose
73 )
74 {
75  // Region name
76  // ~~~~~~~~~~~
77 
78  const fileName meshSubDir
79  (
81  );
82 
83 
84  fileName facesInstance;
85 
86  // Patch types
87  // ~~~~~~~~~~~
88  // Read and scatter master patches (without reading master mesh!)
89 
90  PtrList<entry> patchEntries;
91  if (Pstream::master())
92  {
93  const bool oldParRun = Pstream::parRun(false);
94 
95  facesInstance = io.time().findInstance
96  (
97  meshSubDir,
98  "faceLabels",
100  );
101 
102  patchEntries = faBoundaryMeshEntries
103  (
104  IOobject
105  (
106  "faBoundary",
107  facesInstance,
108  meshSubDir,
109  io.db(),
113  )
114  );
115 
116  Pstream::parRun(oldParRun);
117  }
118 
119  // Broadcast information to all
121  (
123  patchEntries,
124  facesInstance
125  );
126 
127 
128  // Dummy meshes
129  // ~~~~~~~~~~~~
130 
131  // Set up to read-if-present. Note: does not search for mesh so set
132  // instance explicitly
133 
134  IOobject meshIO(io);
135  meshIO.instance() = facesInstance;
136  meshIO.readOpt(IOobject::READ_IF_PRESENT);
137 
138  // For mesh components (faceLabels, ...)
139  IOobject cmptIO(meshIO, "faceLabels", meshSubDir);
140  cmptIO.readOpt(IOobject::MUST_READ);
141  cmptIO.writeOpt(IOobject::NO_WRITE);
142  cmptIO.registerObject(false);
143 
144 
145  // Check who has a mesh
146 
147  const fileName meshDir = io.time().path()/facesInstance/meshSubDir;
148  bool haveMesh = isDir(meshDir);
149  if (masterOnlyReading && !Pstream::master())
150  {
151  haveMesh = false;
152  meshIO.readOpt(IOobject::NO_READ);
153  }
154 
155  if (!haveMesh)
156  {
157  cmptIO.readOpt(IOobject::NO_READ);
158  }
159 
160 
161  // Read mesh
162  // ~~~~~~~~~
163  // Now all processors use supplied points,faces etc
164  // Note: solution, schemes are also using the supplied IOobject so
165  // on slave will be NO_READ, on master READ_IF_PRESENT. This will
166  // conflict with e.g. timeStampMaster reading so switch off.
167 
168  const auto oldCheckType = IOobject::fileModificationChecking;
170 
171 
172  // faceLabels
173  cmptIO.rename("faceLabels");
174  labelIOList faceLabels(cmptIO);
175 
176 
178  (
179  pMesh,
180  std::move(faceLabels),
181  meshIO
182  );
183  auto& mesh = *meshPtr;
184 
185  IOobject::fileModificationChecking = oldCheckType;
186 
187 
188  // Some processors without patches? - add patches
189 
191  {
192  // Use patchEntries, which were read on master and broadcast
193 
194  faPatchList patches(patchEntries.size());
195  label nPatches = 0;
196 
197  const bool isEmptyMesh = (mesh.faceLabels().empty());
198 
199  forAll(patchEntries, patchi)
200  {
201  const entry& e = patchEntries[patchi];
202  const word type(e.dict().get<word>("type"));
203  const word& name = e.keyword();
204 
205  if
206  (
207  type == processorFaPatch::typeName
208  )
209  {
210  // Stop at the first processor patch.
211  // - logic will not work with inter-mixed proc-patches anyhow
212  break;
213  }
214  else
215  {
216  dictionary patchDict(e.dict());
217 
218  if (isEmptyMesh)
219  {
220  patchDict.set("edgeLabels", labelList());
221  }
222 
223  patches.set
224  (
225  patchi,
227  (
228  name,
229  patchDict,
230  nPatches++,
231  mesh.boundary()
232  )
233  );
234  }
235  }
236 
238  mesh.addFaPatches(patches, false); // No parallel comms
239  }
240 
241  // Recreate basic geometry, globalMeshData etc.
242  mesh.init(false);
243  (void)mesh.globalData();
244 
245  return meshPtr;
246 }
247 
248 
250 (
251  const IOobject& io,
252  const polyMesh& pMesh,
253  const bool decompose,
254  const bool verbose
255 )
256 {
257  // Region name
258  // ~~~~~~~~~~~
259 
260  const fileName meshSubDir
261  (
263  );
264 
265 
266  // Patch types
267  // ~~~~~~~~~~~
268  // Read and scatter master patches (without reading master mesh!)
269 
270  PtrList<entry> patchEntries;
271  if (Pstream::master())
272  {
273  const bool oldParRun = Pstream::parRun(false);
274 
275  patchEntries = faBoundaryMeshEntries
276  (
277  IOobject
278  (
279  "faBoundary",
280  io.instance(),
281  meshSubDir,
282  io.db(),
286  )
287  );
288 
289  Pstream::parRun(oldParRun);
290  }
291 
292  // Broadcast: send patches to all
293  Pstream::broadcast(patchEntries); // == worldComm;
294 
296 
297  // Dummy meshes
298  // ~~~~~~~~~~~~
299 
300  // Check who has or needs a mesh.
301  // For 'decompose', only need mesh on master.
302  // Otherwise check for presence of the "faceLabels" file
303 
304  bool haveMesh =
305  (
306  decompose
307  ? Pstream::master()
308  : fileHandler().isFile
309  (
310  fileHandler().filePath
311  (
312  io.time().path()/io.instance()/meshSubDir/"faceLabels"
313  )
314  )
315  );
316 
317 
318  if (!haveMesh)
319  {
320  const bool oldParRun = Pstream::parRun(false);
321 
322  // Create dummy mesh - on procs that don't already have a mesh
323  faMesh dummyMesh
324  (
325  pMesh,
326  labelList(),
328  );
329 
330  // Add patches
331  faPatchList patches(patchEntries.size());
332  label nPatches = 0;
333 
334  forAll(patchEntries, patchi)
335  {
336  const entry& e = patchEntries[patchi];
337  const word type(e.dict().get<word>("type"));
338  const word& name = e.keyword();
339 
340  if
341  (
342  type == processorFaPatch::typeName
343  )
344  {
345  // Stop at the first processor patch.
346  // - logic will not work with inter-mixed proc-patches anyhow
347  break;
348  }
349  else
350  {
351  dictionary patchDict(e.dict());
352  patchDict.set("edgeLabels", labelList());
353 
354  patches.set
355  (
356  patchi,
358  (
359  name,
360  patchDict,
361  nPatches++,
362  dummyMesh.boundary()
363  )
364  );
365  }
366  }
367 
369  dummyMesh.addFaPatches(patches, false); // No parallel comms
370 
371  // Bad hack, but the underlying polyMesh is NO_WRITE
372  // so it does not create the faMesh subDir for us...
373  Foam::mkDir(dummyMesh.boundary().path());
374 
375  //Pout<< "Writing dummy mesh to " << dummyMesh.boundary().path()
376  // << endl;
377  dummyMesh.write();
378 
379  Pstream::parRun(oldParRun); // Restore parallel state
380  }
381 
382  // Read mesh
383  // ~~~~~~~~~
384  // Now all processors have a (possibly zero size) mesh so read in
385  // parallel
386 
388  auto meshPtr = autoPtr<faMesh>::New(pMesh, false);
389  faMesh& mesh = *meshPtr;
390 
391  // Sync patches
392  // ~~~~~~~~~~~~
393 
394  if (!Pstream::master() && haveMesh)
395  {
396  // Check master names against mine
397 
398  const faBoundaryMesh& patches = mesh.boundary();
399 
400  forAll(patchEntries, patchi)
401  {
402  const entry& e = patchEntries[patchi];
403  const word type(e.dict().get<word>("type"));
404  const word& name = e.keyword();
405 
406  if
407  (
408  type == processorFaPatch::typeName
409  )
410  {
411  break;
412  }
413 
414  if (patchi >= patches.size())
415  {
417  << "Non-processor patches not synchronised."
418  << endl
419  << "Processor " << Pstream::myProcNo()
420  << " has only " << patches.size()
421  << " patches, master has "
422  << patchi
423  << exit(FatalError);
424  }
425 
426  if
427  (
428  type != patches[patchi].type()
429  || name != patches[patchi].name()
430  )
431  {
433  << "Non-processor patches not synchronised."
434  << endl
435  << "Master patch " << patchi
436  << " name:" << type
437  << " type:" << type << endl
438  << "Processor " << Pstream::myProcNo()
439  << " patch " << patchi
440  << " has name:" << patches[patchi].name()
441  << " type:" << patches[patchi].type()
442  << exit(FatalError);
443  }
444  }
445  }
446 
447 
448  // Recreate basic geometry, globalMeshData etc.
449  mesh.init(false);
450  (void)mesh.globalData();
451 
456 
457  // Do some checks.
458 
459  // Check if the boundary definition is unique
460  // and processor patches are correct
461  mesh.boundary().checkDefinition(verbose);
462  mesh.boundary().checkParallelSync(verbose);
463 
464  return meshPtr;
465 }
466 
467 
468 // ************************************************************************* //
label nPatches
Definition: readKivaGrid.H:396
PtrList< faPatch > faPatchList
Store lists of faPatch as a PtrList.
Definition: faPatch.H:59
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition: faMesh.H:88
static autoPtr< faMesh > newMesh(const IOobject &io, const polyMesh &pMesh, const bool masterOnlyReading, const bool verbose=false)
Read mesh or create dummy mesh (0 faces, >0 patches).
Definition: faMeshTools.C:61
static autoPtr< faPatch > New(const word &name, const dictionary &dict, const label index, const faBoundaryMesh &bm)
Return pointer to a new patch created on freestore from dictionary.
Definition: faPatchNew.C:28
fileName path() const
Return path.
Definition: Time.H:449
A class for handling file names.
Definition: fileName.H:71
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
word findInstance(const fileName &dir, const word &name=word::null, IOobjectOption::readOption rOpt=IOobjectOption::MUST_READ, const word &stopInstance=word::null) const
Return time instance (location) of dir that contains the file name (eg, used in reading mesh data)...
Definition: Time.C:777
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:578
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:150
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:639
autoPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler.
virtual bool init(const bool doInit)
Initialise all non-demand-driven data.
Definition: dynamicFvMesh.C:84
bool checkOut(regIOobject *io) const
Remove a regIOobject from registry and free memory if the object is ownedByRegistry. A nullptr is ignored.
Ignore writing from objectRegistry::writeObject()
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:688
static label worldComm
Default world communicator (all processors). May differ from globalComm if local worlds are in use...
Definition: UPstream.H:361
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all processes in communicator.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:813
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:752
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
dynamicFvMesh & mesh
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:567
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
Foam::autoPtr< Foam::dynamicFvMesh > meshPtr
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:99
const objectRegistry & db() const noexcept
Return the local objectRegistry.
Definition: IOobject.C:441
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1293
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: PtrList.H:163
bool empty() const noexcept
True if the hash table is empty.
Definition: HashTableI.H:52
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:313
void resize(const label newLen)
Adjust size of PtrList.
Definition: PtrList.C:95
const fileName & instance() const noexcept
Read access to instance path component.
Definition: IOobjectI.H:221
static autoPtr< faMesh > loadOrCreateMesh(const IOobject &io, const polyMesh &pMesh, const bool decompose, const bool verbose=false)
Definition: faMeshTools.C:243
static void broadcasts(const label comm, Type &arg1, Args &&... args)
Broadcast multiple items to all processes in communicator.
Read and store dictionary entries for finite-area boundary patches.
bool isFile(const fileName &name, const bool checkGzip=true, const bool followLink=true)
Does the name exist as a FILE in the file system?
Definition: POSIX.C:830
bool empty() const noexcept
True if the list is empty (ie, size() is zero)
Definition: UPtrListI.H:106
static word meshSubDir
The mesh sub-directory name (usually "faMesh")
Definition: faMesh.H:698
static void unregisterMesh(const faMesh &mesh)
Unregister the faMesh from its associated polyMesh to prevent triggering on polyMesh changes etc...
Definition: faMeshTools.C:31
const Time & time() const
Return Time associated with the objectRegistry.
Definition: IOobject.C:447
static bool master(const label communicator=worldComm)
Am I the master rank.
Definition: UPstream.H:672
const polyBoundaryMesh & patches
Nothing to be read.
Automatically write from objectRegistry::writeObject()
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:73
List< label > labelList
A List of labels.
Definition: List.H:62
Registry of regIOobjects.
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
Definition: autoPtr.H:178
bool returnReduceOr(const bool value, const label comm=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:166
static void forceDemandDriven(faMesh &mesh)
Force creation of everything that might vaguely be used by patches.
Definition: faMeshTools.C:43
static const word & regionName(const word &region)
The mesh region name or word::null if polyMesh::defaultRegion.
Definition: polyMesh.C:816
Do not request registration (bool: false)
IOList< label > labelIOList
Label container classes.
Definition: labelIOList.H:38
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:705