loadOrCreateMesh.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-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2019 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 "loadOrCreateMesh.H"
30 #include "processorPolyPatch.H"
32 #include "Time.H"
33 //#include "IOPtrList.H"
35 #include "IOobjectList.H"
36 #include "pointSet.H"
37 #include "faceSet.H"
38 #include "cellSet.H"
39 
40 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
41 
42 //namespace Foam
43 //{
44 // defineTemplateTypeNameAndDebug(IOPtrList<entry>, 0);
45 //}
46 
47 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
48 
49 // Read mesh if available. Otherwise create empty mesh with same non-proc
50 // patches as proc0 mesh. Requires all processors to have all patches
51 // (and in same order).
53 (
54  const IOobject& io
55 )
56 {
57  // Region name
58  // ~~~~~~~~~~~
59 
60  fileName meshSubDir;
61 
62  if (io.name() == polyMesh::defaultRegion)
63  {
64  meshSubDir = polyMesh::meshSubDir;
65  }
66  else
67  {
68  meshSubDir = io.name()/polyMesh::meshSubDir;
69  }
70 
71 
72  // Patch types
73  // ~~~~~~~~~~~
74  // Read and scatter master patches (without reading master mesh!)
75 
76  PtrList<entry> patchEntries;
77  if (Pstream::master())
78  {
80  //const word oldTypeName = IOPtrList<entry>::typeName;
81  //const_cast<word&>(IOPtrList<entry>::typeName) = word::null;
82  //IOPtrList<entry> dictList
83  //(
84  // IOobject
85  // (
86  // "boundary",
87  // io.time().findInstance
88  // (
89  // meshSubDir,
90  // "boundary",
91  // IOobject::MUST_READ
92  // ),
93  // meshSubDir,
94  // io.db(),
95  // IOobject::MUST_READ,
96  // IOobject::NO_WRITE,
97  // false
98  // )
99  //);
100  //const_cast<word&>(IOPtrList<entry>::typeName) = oldTypeName;
102  //const_cast<word&>(dictList.type()) = dictList.headerClassName();
103  //
104  //patchEntries.transfer(dictList);
105  const fileName facesInstance = io.time().findInstance
106  (
107  meshSubDir,
108  "faces",
109  IOobject::MUST_READ
110  );
111 
112  patchEntries = polyBoundaryMeshEntries
113  (
114  IOobject
115  (
116  "boundary",
117  facesInstance,
118  meshSubDir,
119  io.db(),
120  IOobject::MUST_READ,
121  IOobject::NO_WRITE,
122  false
123  )
124  );
125 
126  // Send patches
127  for
128  (
129  int slave=Pstream::firstSlave();
130  slave<=Pstream::lastSlave();
131  slave++
132  )
133  {
134  OPstream toSlave(Pstream::commsTypes::scheduled, slave);
135  toSlave << patchEntries;
136  }
137  }
138  else
139  {
140  // Receive patches
141  IPstream fromMaster
142  (
143  Pstream::commsTypes::scheduled,
144  Pstream::masterNo()
145  );
146  fromMaster >> patchEntries;
147  }
148 
149 
150 
151  // Dummy meshes
152  // ~~~~~~~~~~~~
153 
154  // Check who has a mesh
155  const bool haveMesh = fileHandler().isFile
156  (
157  fileHandler().filePath
158  (
159  io.time().path()/io.instance()/meshSubDir/"faces"
160  )
161  );
162 
163  if (!haveMesh)
164  {
165  const bool oldParRun = Pstream::parRun();
166  Pstream::parRun() = false;
167 
168 
169  // Create dummy mesh. Only used on procs that don't have mesh.
170  IOobject noReadIO(io);
171  noReadIO.readOpt() = IOobject::NO_READ;
172  noReadIO.writeOpt() = IOobject::AUTO_WRITE;
173  fvMesh dummyMesh(noReadIO, Zero, false);
174 
175  // Add patches
176  List<polyPatch*> patches(patchEntries.size());
177  label nPatches = 0;
178 
179  forAll(patchEntries, patchi)
180  {
181  const entry& e = patchEntries[patchi];
182  const word type(e.dict().get<word>("type"));
183  const word& name = e.keyword();
184 
185  if
186  (
187  type != processorPolyPatch::typeName
188  && type != processorCyclicPolyPatch::typeName
189  )
190  {
191  dictionary patchDict(e.dict());
192  patchDict.set("nFaces", 0);
193  patchDict.set("startFace", 0);
194 
195  patches[patchi] = polyPatch::New
196  (
197  name,
198  patchDict,
199  nPatches++,
200  dummyMesh.boundaryMesh()
201  ).ptr();
202  }
203  }
204  patches.setSize(nPatches);
205  dummyMesh.addFvPatches(patches, false); // no parallel comms
206 
207 
208  // Add some dummy zones so upon reading it does not read them
209  // from the undecomposed case. Should be done as extra argument to
210  // regIOobject::readStream?
211  List<pointZone*> pz
212  (
213  1,
214  new pointZone
215  (
216  "dummyPointZone",
217  0,
218  dummyMesh.pointZones()
219  )
220  );
221  List<faceZone*> fz
222  (
223  1,
224  new faceZone
225  (
226  "dummyFaceZone",
227  0,
228  dummyMesh.faceZones()
229  )
230  );
231  List<cellZone*> cz
232  (
233  1,
234  new cellZone
235  (
236  "dummyCellZone",
237  0,
238  dummyMesh.cellZones()
239  )
240  );
241  dummyMesh.addZones(pz, fz, cz);
242  dummyMesh.pointZones().clear();
243  dummyMesh.faceZones().clear();
244  dummyMesh.cellZones().clear();
245  //Pout<< "Writing dummy mesh to " << dummyMesh.polyMesh::objectPath()
246  // << endl;
247  dummyMesh.write();
248 
249  Pstream::parRun() = oldParRun;
250  }
251 
252 
253 
254  // Read mesh
255  // ~~~~~~~~~
256  // Now all processors have a (possibly zero size) mesh so read in
257  // parallel
258 
259  //Pout<< "Reading mesh from " << io.objectPath() << endl;
260  auto meshPtr = autoPtr<fvMesh>::New(io);
261  fvMesh& mesh = *meshPtr;
262 
263 
264 
265  // Sync patches
266  // ~~~~~~~~~~~~
267 
268  if (!Pstream::master() && haveMesh)
269  {
270  // Check master names against mine
271 
272  const polyBoundaryMesh& patches = mesh.boundaryMesh();
273 
274  forAll(patchEntries, patchi)
275  {
276  const entry& e = patchEntries[patchi];
277  const word type(e.dict().get<word>("type"));
278  const word& name = e.keyword();
279 
280  if (type == processorPolyPatch::typeName)
281  {
282  break;
283  }
284 
285  if (patchi >= patches.size())
286  {
288  << "Non-processor patches not synchronised."
289  << endl
290  << "Processor " << Pstream::myProcNo()
291  << " has only " << patches.size()
292  << " patches, master has "
293  << patchi
294  << exit(FatalError);
295  }
296 
297  if
298  (
299  type != patches[patchi].type()
300  || name != patches[patchi].name()
301  )
302  {
304  << "Non-processor patches not synchronised."
305  << endl
306  << "Master patch " << patchi
307  << " name:" << type
308  << " type:" << type << endl
309  << "Processor " << Pstream::myProcNo()
310  << " patch " << patchi
311  << " has name:" << patches[patchi].name()
312  << " type:" << patches[patchi].type()
313  << exit(FatalError);
314  }
315  }
316  }
317 
318 
319  // Determine zones
320  // ~~~~~~~~~~~~~~~
321 
322  wordList pointZoneNames(mesh.pointZones().names());
323  Pstream::scatter(pointZoneNames);
324  wordList faceZoneNames(mesh.faceZones().names());
325  Pstream::scatter(faceZoneNames);
326  wordList cellZoneNames(mesh.cellZones().names());
327  Pstream::scatter(cellZoneNames);
328 
329  if (!haveMesh)
330  {
331  // Add the zones. Make sure to remove the old dummy ones first
332  mesh.pointZones().clear();
333  mesh.faceZones().clear();
334  mesh.cellZones().clear();
335 
336  List<pointZone*> pz(pointZoneNames.size());
337  forAll(pointZoneNames, i)
338  {
339  pz[i] = new pointZone
340  (
341  pointZoneNames[i],
342  i,
343  mesh.pointZones()
344  );
345  }
346  List<faceZone*> fz(faceZoneNames.size());
347  forAll(faceZoneNames, i)
348  {
349  fz[i] = new faceZone
350  (
351  faceZoneNames[i],
352  i,
353  mesh.faceZones()
354  );
355  }
356  List<cellZone*> cz(cellZoneNames.size());
357  forAll(cellZoneNames, i)
358  {
359  cz[i] = new cellZone
360  (
361  cellZoneNames[i],
362  i,
363  mesh.cellZones()
364  );
365  }
366  mesh.addZones(pz, fz, cz);
367  }
368 
369 
370  // Determine sets
371  // ~~~~~~~~~~~~~~
372 
373  wordList pointSetNames;
374  wordList faceSetNames;
375  wordList cellSetNames;
376  if (Pstream::master())
377  {
378  // Read sets
379  IOobjectList objects(mesh, mesh.facesInstance(), "polyMesh/sets");
380  pointSetNames = objects.sortedNames(pointSet::typeName);
381  faceSetNames = objects.sortedNames(faceSet::typeName);
382  cellSetNames = objects.sortedNames(cellSet::typeName);
383  }
384  Pstream::scatter(pointSetNames);
385  Pstream::scatter(faceSetNames);
386  Pstream::scatter(cellSetNames);
387 
388  if (!haveMesh)
389  {
390  for (const word& setName : pointSetNames)
391  {
392  pointSet(mesh, setName, 0).write();
393  }
394  for (const word& setName : faceSetNames)
395  {
396  faceSet(mesh, setName, 0).write();
397  }
398  for (const word& setName : cellSetNames)
399  {
400  cellSet(mesh, setName, 0).write();
401  }
402  }
403 
404 
405 // if (!haveMesh)
406 // {
407 // // We created a dummy mesh file above. Delete it.
408 // const fileName meshFiles = io.time().path()/io.instance()/meshSubDir;
409 // //Pout<< "Removing dummy mesh " << meshFiles << endl;
410 // mesh.removeFiles();
411 // rmDir(meshFiles);
412 // }
413 //
414  // Force recreation of globalMeshData.
415 // mesh.clearOut();
416  mesh.globalData();
417 
418 
419  // Do some checks.
420 
421  // Check if the boundary definition is unique
422  mesh.boundaryMesh().checkDefinition(true);
423  // Check if the boundary processor patches are correct
424  mesh.boundaryMesh().checkParallelSync(true);
425  // Check names of zones are equal
426  mesh.cellZones().checkDefinition(true);
427  mesh.cellZones().checkParallelSync(true);
428  mesh.faceZones().checkDefinition(true);
429  mesh.faceZones().checkParallelSync(true);
430  mesh.pointZones().checkDefinition(true);
431  mesh.pointZones().checkParallelSync(true);
432 
433  return meshPtr;
434 }
435 
436 
437 // ************************************************************************* //
meshPtr
Foam::autoPtr< Foam::fvMesh > meshPtr(nullptr)
nPatches
label nPatches
Definition: readKivaGrid.H:396
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::fileHandler
const fileOperation & fileHandler()
Get current file handler.
Definition: fileOperation.C:1170
IOobjectList.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
polyBoundaryMeshEntries.H
processorCyclicPolyPatch.H
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::wordList
List< word > wordList
A List of words.
Definition: fileName.H:59
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
faceSet.H
Foam::FatalError
error FatalError
processorPolyPatch.H
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
Time.H
Foam::autoPtr< Foam::fvMesh >
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:372
Foam::fileOperation::isFile
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?
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::roots::type
type
Types of root.
Definition: Roots.H:54
cellSet.H
Foam::loadOrCreateMesh
autoPtr< fvMesh > loadOrCreateMesh(const IOobject &io)
Load (if it exists) or create zero cell mesh given an IOobject:
loadOrCreateMesh.H
Load or create (0 size) a mesh. Used in distributing meshes to a larger number of processors.
pointSet.H