loadOrCreateMesh.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2012-2024 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "loadOrCreateMesh.H"
27 #include "processorPolyPatch.H"
29 #include "IOPtrList.H"
30 #include "OSspecific.H"
31 
32 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36  defineTemplateTypeNameAndDebug(IOPtrList<entry>, 0);
37 }
38 
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40 
41 // Read mesh if available. Otherwise create empty mesh with same non-proc
42 // patches as proc0 mesh. Requires all processors to have all patches
43 // (and in same order).
45 (
46  const IOobject& io
47 )
48 {
49  fileName meshSubDir;
50 
51  if (io.name() == polyMesh::defaultRegion)
52  {
53  meshSubDir = polyMesh::meshSubDir;
54  }
55  else
56  {
57  meshSubDir = io.name()/polyMesh::meshSubDir;
58  }
59 
60 
61  // Scatter master patches
62  PtrList<entry> patchEntries;
63  if (Pstream::master())
64  {
65  // Read PtrList of dictionary as dictionary.
66  const word oldTypeName = IOPtrList<entry>::typeName;
67  const_cast<word&>(IOPtrList<entry>::typeName) = word::null;
68  IOPtrList<entry> dictList
69  (
70  IOobject
71  (
72  "boundary",
73  io.time().findInstance
74  (
75  meshSubDir,
76  "boundary",
77  IOobject::MUST_READ
78  ),
79  meshSubDir,
80  io.db(),
81  IOobject::MUST_READ,
82  IOobject::NO_WRITE,
83  false
84  )
85  );
86  const_cast<word&>(IOPtrList<entry>::typeName) = oldTypeName;
87  // Fake type back to what was in field
88  const_cast<word&>(dictList.type()) = dictList.headerClassName();
89 
90  patchEntries.transfer(dictList);
91 
92  // Send patches
93  for
94  (
95  int slave=Pstream::firstSlave();
96  slave<=Pstream::lastSlave();
97  slave++
98  )
99  {
100  OPstream toSlave(Pstream::commsTypes::scheduled, slave);
101  toSlave << patchEntries;
102  }
103  }
104  else
105  {
106  // Receive patches
107  IPstream fromMaster
108  (
109  Pstream::commsTypes::scheduled,
110  Pstream::masterNo()
111  );
112  fromMaster >> patchEntries;
113  }
114 
115 
116 
117  // Check who has a mesh
118  const bool haveMesh = fileHandler().isDir
119  (
120  fileHandler().filePath(io.time().path()/io.instance()/meshSubDir)
121  );
122 
123  if (!haveMesh)
124  {
125  bool oldParRun = Pstream::parRun();
126  Pstream::parRun() = false;
127 
128 
129  // Create dummy mesh. Only used on procs that don't have mesh.
130  IOobject noReadIO(io);
131  noReadIO.readOpt() = IOobject::NO_READ;
132  fvMesh dummyMesh
133  (
134  noReadIO,
135  pointField(),
136  faceList(),
137  labelList(),
138  labelList(),
139  false
140  );
141 
142  // Add patches
143  List<polyPatch*> patches(patchEntries.size());
144  label nPatches = 0;
145 
146  forAll(patchEntries, patchi)
147  {
148  const entry& e = patchEntries[patchi];
149  const word type(e.dict().lookup("type"));
150  const word& name = e.keyword();
151 
152  if
153  (
154  type != processorPolyPatch::typeName
155  && type != processorCyclicPolyPatch::typeName
156  )
157  {
158  dictionary patchDict(e.dict());
159  patchDict.set("nFaces", 0);
160  patchDict.set("startFace", 0);
161 
163  (
164  name,
165  patchDict,
166  nPatches++,
167  dummyMesh.boundaryMesh()
168  ).ptr();
169  }
170  }
171  patches.setSize(nPatches);
172  dummyMesh.addFvPatches(patches, false); // no parallel comms
173 
174  // Add some dummy zones so upon reading it does not read them
175  // from the undecomposed case. Should be done as extra argument to
176  // regIOobject::readStream?
177  List<pointZone*> pz
178  (
179  1,
180  new pointZone
181  (
182  "dummyPointZone",
183  labelList(0),
184  dummyMesh.pointZones()
185  )
186  );
187  List<faceZone*> fz
188  (
189  1,
190  new faceZone
191  (
192  "dummyFaceZone",
193  labelList(0),
194  boolList(0),
195  dummyMesh.faceZones()
196  )
197  );
198  List<cellZone*> cz
199  (
200  1,
201  new cellZone
202  (
203  "dummyCellZone",
204  labelList(0),
205  dummyMesh.cellZones()
206  )
207  );
208  dummyMesh.addZones(pz, fz, cz);
209  dummyMesh.write();
210 
211  Pstream::parRun() = oldParRun;
212  }
213 
214  autoPtr<fvMesh> meshPtr(new fvMesh(io, false));
215  fvMesh& mesh = meshPtr();
216 
217 
218  // Sync patches
219  // ~~~~~~~~~~~~
220 
221  if (!Pstream::master() && haveMesh)
222  {
223  // Check master names against mine
224 
225  const polyBoundaryMesh& patches = mesh.boundaryMesh();
226 
227  forAll(patchEntries, patchi)
228  {
229  const entry& e = patchEntries[patchi];
230  const word type(e.dict().lookup("type"));
231  const word& name = e.keyword();
232 
233  if (type == processorPolyPatch::typeName)
234  {
235  break;
236  }
237 
238  if (patchi >= patches.size())
239  {
241  << "Non-processor patches not synchronised."
242  << endl
243  << "Processor " << Pstream::myProcNo()
244  << " has only " << patches.size()
245  << " patches, master has "
246  << patchi
247  << exit(FatalError);
248  }
249 
250  if
251  (
252  type != patches[patchi].type()
253  || name != patches[patchi].name()
254  )
255  {
257  << "Non-processor patches not synchronised."
258  << endl
259  << "Master patch " << patchi
260  << " name:" << type
261  << " type:" << type << endl
262  << "Processor " << Pstream::myProcNo()
263  << " patch " << patchi
264  << " has name:" << patches[patchi].name()
265  << " type:" << patches[patchi].type()
266  << exit(FatalError);
267  }
268  }
269  }
270 
271 
272  // Determine zones
273  // ~~~~~~~~~~~~~~~
274 
275  wordList pointZoneNames(mesh.pointZones().toc());
276  Pstream::scatter(pointZoneNames);
277  wordList faceZoneNames(mesh.faceZones().toc());
278  Pstream::scatter(faceZoneNames);
279  wordList cellZoneNames(mesh.cellZones().toc());
280  Pstream::scatter(cellZoneNames);
281 
282  if (!haveMesh)
283  {
284  // Add the zones. Make sure to remove the old dummy ones first
285  mesh.pointZones().clear();
286  mesh.faceZones().clear();
287  mesh.cellZones().clear();
288 
289  List<pointZone*> pz(pointZoneNames.size());
290  forAll(pointZoneNames, i)
291  {
292  pz[i] = new pointZone
293  (
294  pointZoneNames[i],
295  labelList(0),
296  mesh.pointZones()
297  );
298  }
299  List<faceZone*> fz(faceZoneNames.size());
300  forAll(faceZoneNames, i)
301  {
302  fz[i] = new faceZone
303  (
304  faceZoneNames[i],
305  labelList(0),
306  boolList(0),
307  mesh.faceZones()
308  );
309  }
310  List<cellZone*> cz(cellZoneNames.size());
311  forAll(cellZoneNames, i)
312  {
313  cz[i] = new cellZone
314  (
315  cellZoneNames[i],
316  labelList(0),
317  mesh.cellZones()
318  );
319  }
320  mesh.addZones(pz, fz, cz);
321  }
322 
323 
324  if (!haveMesh)
325  {
326  // We created a dummy mesh file above. Delete it.
327  const fileName meshFiles = io.time().path()/io.instance()/meshSubDir;
328  // Pout<< "Removing dummy mesh " << meshFiles << endl;
329  mesh.removeFiles();
330  rmDir(meshFiles);
331  }
332 
333  // Force recreation of globalMeshData.
334  mesh.clearOut();
335  mesh.globalData();
336 
337 
338  // Do some checks.
339 
340  // Check if the boundary definition is unique
341  mesh.boundaryMesh().checkDefinition(true);
342  // Check if the boundary processor patches are correct
343  mesh.boundaryMesh().checkParallelSync(true);
344  // Check names of zones are equal
345  mesh.cellZones().checkDefinition(true);
346  mesh.cellZones().checkParallelSync(true);
347  mesh.faceZones().checkDefinition(true);
348  mesh.faceZones().checkParallelSync(true);
349  mesh.pointZones().checkDefinition(true);
350  mesh.pointZones().checkParallelSync(true);
351 
352  return meshPtr;
353 }
354 
355 
356 // ************************************************************************* //
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
virtual bool isDir(const fileName &, const bool followLink=true) const =0
Does the name exist as a directory in the file system?
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
label patchi
static fvMesh * meshPtr
Definition: globalFoam.H:52
const fvPatchList & patches
Load or create (0 size) a mesh. Used in distributing meshes to a larger number of processors.
autoPtr< CompressibleMomentumTransportModel > New(const volScalarField &rho, const volVectorField &U, const surfaceScalarField &phi, const viscosity &viscosity)
const dimensionedScalar e
Elementary charge.
Namespace for OpenFOAM.
const fileOperation & fileHandler()
Get current file handler.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
List< word > wordList
A List of words.
Definition: fileName.H:54
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:257
word name(const bool)
Return a word representation of a bool.
Definition: boolIO.C:39
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
defineTemplateTypeNameAndDebug(prghPressure, 0)
bool rmDir(const fileName &)
Remove a directory and its contents.
Definition: POSIX.C:1047
error FatalError
List< face > faceList
Definition: faceListFwd.H:41
autoPtr< fvMesh > loadOrCreateMesh(const IOobject &io)
Load (if it exists) or create zero cell mesh given an IOobject:
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
label nPatches
Definition: readKivaGrid.H:396