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-------------------------------------------------------------------------------
11License
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"
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)
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 (
105 (
106 "faBoundary",
107 facesInstance,
108 meshSubDir,
109 io.db(),
112 false
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;
137
138 // For mesh components (faceLabels, ...)
139 IOobject cmptIO(meshIO, "faceLabels", meshSubDir);
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;
153 }
154
155 if (!haveMesh)
156 {
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
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 (
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
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 (
278 (
279 "faBoundary",
280 io.instance(),
281 meshSubDir,
282 io.db(),
285 false
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
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 (
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
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
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 (
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// ************************************************************************* //
bool empty() const noexcept
True if the hash table is empty.
Definition: HashTableI.H:59
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:65
const Time & time() const
Return Time associated with the objectRegistry.
Definition: IOobject.C:506
readOption readOpt() const noexcept
The read option.
Definition: IOobjectI.H:164
const objectRegistry & db() const noexcept
Return the local objectRegistry.
Definition: IOobject.C:500
bool registerObject() const noexcept
Should object created with this IOobject be registered?
Definition: IOobjectI.H:107
const fileName & instance() const noexcept
Read access to instance path component.
Definition: IOobjectI.H:196
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:303
virtual void rename(const word &newName)
Rename the object.
Definition: IOobject.H:497
fileName path() const
The complete path.
Definition: IOobject.C:524
writeOption writeOpt() const noexcept
The write option.
Definition: IOobjectI.H:179
static void broadcast(Type &value, const label comm=UPstream::worldComm)
static void broadcasts(const label comm, Type &arg1, Args &&... args)
Broadcast multiple items to all processes in communicator.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: PtrList.H:73
const T * set(const label i) const
Definition: PtrList.H:138
void resize(const label newLen)
Adjust size of PtrList.
Definition: PtrList.C:103
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
fileName path() const
Return path.
Definition: Time.H:358
word findInstance(const fileName &dir, const word &name=word::null, const IOobject::readOption rOpt=IOobject::MUST_READ, const word &stopInstance=word::null) const
Definition: Time.C:797
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type get(const label i) const
Definition: UList.H:528
static label worldComm
Default communicator (all processors)
Definition: UPstream.H:293
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
bool empty() const noexcept
True if the list is empty (ie, size() is zero)
Definition: UPtrListI.H:113
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
entry * set(entry *entryPtr)
Assign a new entry, overwriting any existing entry.
Definition: dictionary.C:780
virtual bool init(const bool doInit)
Initialise all non-demand-driven data.
Definition: dynamicFvMesh.C:91
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:70
Read and store dictionary entries for finite-area boundary patches.
Finite area boundary mesh.
static void unregisterMesh(const faMesh &mesh)
Definition: faMeshTools.C:38
static void forceDemandDriven(faMesh &mesh)
Force creation of everything that might vaguely be used by patches.
Definition: faMeshTools.C:50
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:68
static autoPtr< faMesh > loadOrCreateMesh(const IOobject &io, const polyMesh &pMesh, const bool decompose, const bool verbose=false)
Definition: faMeshTools.C:250
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition: faMesh.H:100
const faBoundaryMesh & boundary() const noexcept
Return constant reference to boundary mesh.
Definition: faMeshI.H:38
virtual bool write(const bool valid=true) const
Write mesh.
Definition: faMesh.C:1005
void addFaPatches(faPatchList &plist, const bool validBoundary=true)
Add boundary patches. Constructor helper.
Definition: faMeshPatches.C:38
static word meshSubDir
The mesh sub-directory name (usually "faMesh")
Definition: faMesh.H:504
A class for handling file names.
Definition: fileName.H:76
virtual bool isFile(const fileName &, const bool checkGzip=true, const bool followLink=true) const =0
Does the name exist as a FILE in the file system?
virtual const objectRegistry & thisDb() const
Return the object registry - resolve conflict polyMesh/lduMesh.
Definition: fvMesh.H:302
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:712
Registry of regIOobjects.
bool checkOut(regIOobject *io) const
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
static const word & regionName(const word &region)
The mesh region name or word::null if polyMesh::defaultRegion.
Definition: polyMesh.C:829
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1310
int myProcNo() const noexcept
Return processor number.
splitCell * master() const
Definition: splitCell.H:113
A class for handling words, derived from Foam::string.
Definition: word.H:68
const polyBoundaryMesh & patches
dynamicFvMesh & mesh
Foam::autoPtr< Foam::dynamicFvMesh > meshPtr
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
const label nPatches
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
const fileOperation & fileHandler()
Get current file handler.
List< label > labelList
A List of labels.
Definition: List.H:66
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:515
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:598
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
error FatalError
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: MSwindows.C:651
volScalarField & e
Definition: createFields.H:11
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
static const char *const typeName
The type name used in ensight case files.