polyMeshIO.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) 2011-2025 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 "polyMesh.H"
27 #include "Time.H"
28 #include "cellIOList.H"
29 #include "zonesGenerator.H"
30 #include "OSspecific.H"
31 
32 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
33 
34 void Foam::polyMesh::setPointsWrite(const Foam::IOobject::writeOption wo)
35 {
36  points_.writeOpt() = wo;
37 
38  if (tetBasePtIsPtr_.valid())
39  {
40  tetBasePtIsPtr_->writeOpt() = wo;
41  }
42 }
43 
44 
45 void Foam::polyMesh::setTopologyWrite(const Foam::IOobject::writeOption wo)
46 {
47  setPointsWrite(wo);
48 
49  faces_.writeOpt() = wo;
50  owner_.writeOpt() = wo;
51  neighbour_.writeOpt() = wo;
52  boundary_.writeOpt() = wo;
53 
54  if (pointZones_.noTopoUpdate())
55  {
56  pointZones_.writeOpt() = wo;
57  }
58 
59  if (faceZones_.noTopoUpdate())
60  {
61  faceZones_.writeOpt() = wo;
62  }
63 
64  if (cellZones_.noTopoUpdate())
65  {
66  cellZones_.writeOpt() = wo;
67  }
68 }
69 
70 
72 {
73  if (debug)
74  {
75  InfoInFunction << "Resetting points instance to " << inst << endl;
76  }
77 
78  points_.instance() = inst;
79  points_.eventNo() = getEvent();
80 
81  if (tetBasePtIsPtr_.valid())
82  {
83  tetBasePtIsPtr_->instance() = inst;
84  tetBasePtIsPtr_().eventNo() = getEvent();
85  }
86 
87  setPointsWrite(IOobject::AUTO_WRITE);
88 }
89 
90 
92 {
93  if (debug)
94  {
95  InfoInFunction << "Resetting topology instance to " << inst << endl;
96  }
97 
98  setPointsInstance(inst);
99 
100  faces_.instance() = inst;
101  owner_.instance() = inst;
102  neighbour_.instance() = inst;
103  boundary_.instance() = inst;
104 
105  if (pointZones_.noTopoUpdate())
106  {
107  pointZones_.instance() = inst;
108  }
109 
110  if (faceZones_.noTopoUpdate())
111  {
112  faceZones_.instance() = inst;
113  }
114 
115  if (cellZones_.noTopoUpdate())
116  {
117  cellZones_.instance() = inst;
118  }
119 
120  setTopologyWrite(IOobject::AUTO_WRITE);
121 }
122 
123 
125 {
126  if (debug)
127  {
128  InfoInFunction << "Updating mesh based on saved data." << endl;
129  }
130 
132 
133  // Find the points and faces instance
134  const fileName pointsInst(time().findInstance(meshDir(), "points"));
135  const fileName facesInst(time().findInstance(meshDir(), "faces"));
136 
137  if (debug)
138  {
139  Info<< "Faces instance: old = " << facesInstance()
140  << " new = " << facesInst << nl
141  << "Points instance: old = " << pointsInstance()
142  << " new = " << pointsInst << endl;
143  }
144 
145  if (facesInst != facesInstance())
146  {
147  // Topological change
148  if (debug)
149  {
150  Info<< "Topological change" << endl;
151  }
152 
153  clearOut();
154 
155  points_ = pointIOField
156  (
157  IOobject
158  (
159  "points",
160  pointsInst,
161  meshSubDir,
162  *this,
165  false
166  )
167  );
168 
169  points_.instance() = pointsInst;
170 
171  faces_ = faceCompactIOList
172  (
173  IOobject
174  (
175  "faces",
176  facesInst,
177  meshSubDir,
178  *this,
181  false
182  )
183  );
184 
185  faces_.instance() = facesInst;
186 
187  owner_ = labelIOList
188  (
189  IOobject
190  (
191  "owner",
192  facesInst,
193  meshSubDir,
194  *this,
197  false
198  )
199  );
200 
201  owner_.instance() = facesInst;
202 
203  neighbour_ = labelIOList
204  (
205  IOobject
206  (
207  "neighbour",
208  facesInst,
209  meshSubDir,
210  *this,
213  false
214  )
215  );
216 
217  neighbour_.instance() = facesInst;
218 
219  // Reset the boundary patches
220  polyBoundaryMesh newBoundary
221  (
222  IOobject
223  (
224  "boundary",
225  facesInst,
226  meshSubDir,
227  *this,
230  false
231  ),
232  *this
233  );
234 
235  // Check that patch types and names are unchanged
236  bool boundaryChanged = false;
237 
238  if (newBoundary.size() != boundary_.size())
239  {
240  boundaryChanged = true;
241  }
242  else
243  {
244  wordList newTypes = newBoundary.types();
245  wordList newNames = newBoundary.names();
246 
247  wordList oldTypes = boundary_.types();
248  wordList oldNames = boundary_.names();
249 
250  forAll(oldTypes, patchi)
251  {
252  if
253  (
254  oldTypes[patchi] != newTypes[patchi]
255  || oldNames[patchi] != newNames[patchi]
256  )
257  {
258  boundaryChanged = true;
259  break;
260  }
261  }
262  }
263 
264  if (boundaryChanged)
265  {
266  boundary_.clear();
267  boundary_.setSize(newBoundary.size());
268 
269  forAll(newBoundary, patchi)
270  {
271  boundary_.set(patchi, newBoundary[patchi].clone(boundary_));
272  }
273  }
274  else
275  {
276  forAll(boundary_, patchi)
277  {
278  boundary_[patchi] = polyPatch
279  (
280  newBoundary[patchi].name(),
281  newBoundary[patchi].size(),
282  newBoundary[patchi].start(),
283  patchi,
284  boundary_,
285  newBoundary[patchi].type()
286  );
287  }
288  }
289 
290  boundary_.instance() = facesInst;
291 
292 
293  // Boundary is set so can use initMesh now (uses boundary_ to
294  // determine internal and active faces)
295 
296  if (!owner_.headerClassName().empty())
297  {
298  initMesh();
299  }
300  else
301  {
303  (
304  IOobject
305  (
306  "cells",
307  facesInst,
308  meshSubDir,
309  *this,
312  false
313  )
314  );
315 
316  // Recalculate the owner/neighbour addressing and reset the
317  // primitiveMesh
318  initMesh(cells);
319  }
320 
321 
322  // Even if number of patches stayed same still recalculate boundary
323  // data.
324 
325  // Calculate topology for the patches (processor-processor comms etc.)
326  boundary_.topoChange();
327 
328  // Calculate the geometry for the patches (transformation tensors etc.)
329  boundary_.calcGeometry();
330 
331  // Derived info
332  bounds_ = boundBox(points_);
333  geometricD_ = Zero;
334  solutionD_ = Zero;
335 
336  // Re-read tet base points
337  tetBasePtIsPtr_ = readTetBasePtIs();
338 
339  if (boundaryChanged)
340  {
342  }
343  else
344  {
345  state = polyMesh::TOPO_CHANGE;
346  }
347  }
348  else if (pointsInst != pointsInstance())
349  {
350  // Points moved
351  if (debug)
352  {
353  Info<< "Point motion" << endl;
354  }
355 
356  clearGeom();
357 
358 
359  label nOldPoints = points_.size();
360 
361  points_.clear();
362 
363  pointIOField newPoints
364  (
365  IOobject
366  (
367  "points",
368  pointsInst,
369  meshSubDir,
370  *this,
373  false
374  )
375  );
376 
377  if (nOldPoints != 0 && nOldPoints != newPoints.size())
378  {
380  << "Point motion detected but number of points "
381  << newPoints.size() << " in "
382  << newPoints.objectPath() << " does not correspond to "
383  << " current " << nOldPoints
384  << exit(FatalError);
385  }
386 
387  points_.transfer(newPoints);
388 
389  points_.instance() = pointsInst;
390 
391  // Re-read tet base points
392  autoPtr<labelIOList> newTetBasePtIsPtr = readTetBasePtIs();
393  if (newTetBasePtIsPtr.valid())
394  {
395  tetBasePtIsPtr_ = newTetBasePtIsPtr;
396  }
397 
398  // Calculate the geometry for the patches (transformation tensors etc.)
399  boundary_.calcGeometry();
400 
401  // Derived info
402  bounds_ = boundBox(points_);
403 
404  // Rotation can cause direction vector to change
405  geometricD_ = Zero;
406  solutionD_ = Zero;
407 
408  state = polyMesh::POINTS_MOVED;
409  }
410 
411  // pointZones
412  {
413  const fileName pointZonesInst
414  (
415  time().findInstance
416  (
417  meshDir(),
418  "pointZones",
420  facesInst
421  )
422  );
423 
424  if (pointZonesInst != pointZones_.instance())
425  {
426  pointZoneList newPointZones
427  (
428  IOobject
429  (
430  "pointZones",
431  pointZonesInst,
432  meshSubDir,
433  *this,
436  false
437  ),
438  *this
439  );
440 
441  pointZones_.swap(newPointZones);
442  pointZones_.instance() = pointZonesInst;
443  }
444  }
445 
446  // faceZones
447  {
448  const fileName faceZonesInst
449  (
450  time().findInstance
451  (
452  meshDir(),
453  "faceZones",
455  facesInst
456  )
457  );
458 
459  if (faceZonesInst != faceZones_.instance())
460  {
461  faceZoneList newFaceZones
462  (
463  IOobject
464  (
465  "faceZones",
466  faceZonesInst,
467  meshSubDir,
468  *this,
471  false
472  ),
473  *this
474  );
475 
476  faceZones_.swap(newFaceZones);
477  faceZones_.instance() = faceZonesInst;
478  }
479  }
480 
481  // cellZones
482  {
483  const fileName cellZonesInst
484  (
485  time().findInstance
486  (
487  meshDir(),
488  "cellZones",
490  facesInst
491  )
492  );
493 
494  if (cellZonesInst != cellZones_.instance())
495  {
496  cellZoneList newCellZones
497  (
498  IOobject
499  (
500  "cellZones",
501  cellZonesInst,
502  meshSubDir,
503  *this,
506  false
507  ),
508  *this
509  );
510 
511  cellZones_.swap(newCellZones);
512  cellZones_.instance() = cellZonesInst;
513  }
514  }
515 
516  if (debug && state == polyMesh::UNCHANGED)
517  {
518  Info<< "No change" << endl;
519  }
520 
521  return state;
522 }
523 
524 
526 (
530  const bool write
531 ) const
532 {
533  if (faces_.writeOpt() == AUTO_WRITE)
534  {
535  auto rmAddressing = [&](const word& name)
536  {
537  const IOobject faceProcAddressingIO
538  (
539  name,
540  facesInstance(),
541  meshSubDir,
542  *this
543  );
544 
545  fileHandler().rm(faceProcAddressingIO.filePath(false));
546  };
547 
548  if (!Pstream::parRun())
549  {
550  rmAddressing("cellProc");
551  }
552  else
553  {
554  rmAddressing("pointProcAddressing");
555  rmAddressing("faceProcAddressing");
556  rmAddressing("cellProcAddressing");
557  }
558  }
559 
560  const bool written = objectRegistry::writeObject(fmt, ver, cmp, write);
561 
562  const_cast<polyMesh&>(*this).setTopologyWrite(IOobject::NO_WRITE);
563 
564  return written;
565 }
566 
567 
568 // ************************************************************************* //
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:433
A List of objects of type <Type> with automated input and output using a compact storage....
A primitive field of type <Type> with automated input and output.
Definition: IOField.H:53
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
writeOption writeOpt() const
Definition: IOobject.H:367
fileName filePath(const bool global) const
Return complete path + object name if the file exists.
Definition: IOobject.C:409
writeOption
Enumeration defining the write options.
Definition: IOobject.H:126
Version number type.
Definition: IOstream.H:97
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:87
compressionType
Enumeration for the format of data in the stream.
Definition: IOstream.H:194
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
bool valid() const
Return true if the autoPtr valid (ie, the pointer is set)
Definition: autoPtrI.H:83
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:59
A class for handling file names.
Definition: fileName.H:82
virtual bool rm(const fileName &) const =0
Remove a file, returning true if successful otherwise false.
virtual bool writeObject(IOstream::streamFormat fmt, IOstream::versionNumber ver, IOstream::compressionType cmp, const bool write) const
Write the objects.
Foam::polyBoundaryMesh.
wordList types() const
Return a list of patch types.
wordList names() const
Return the list of patch names.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
readUpdateState
Enumeration defining the state of the mesh after a read update.
Definition: polyMesh.H:90
@ TOPO_PATCH_CHANGE
Definition: polyMesh.H:94
virtual bool writeObject(IOstream::streamFormat fmt, IOstream::versionNumber ver, IOstream::compressionType cmp, const bool write=true) const
Write the underlying polyMesh.
Definition: polyMeshIO.C:526
readUpdateState readUpdate()
Update the mesh based on the mesh files saved in.
Definition: polyMeshIO.C:124
void setPointsInstance(const fileName &)
Set the instance for the points files.
Definition: polyMeshIO.C:71
void setInstance(const fileName &)
Set the instance for mesh files.
Definition: polyMeshIO.C:91
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:70
fileName objectPath() const
Return complete path + object name.
Definition: regIOobject.H:158
A class for handling words, derived from string.
Definition: word.H:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
label patchi
const cellShapeList & cells
#define InfoInFunction
Report an information message using Foam::Info.
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
const fileOperation & fileHandler()
Get current file handler.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
static const zero Zero
Definition: zero.H:97
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:258
CompactIOList< face > faceCompactIOList
Definition: faceIOList.H:44
messageStream Info
vectorIOField pointIOField
pointIOField is a vectorIOField.
Definition: pointIOField.H:42
T clone(const T &t)
Definition: List.H:55
IOList< label > labelIOList
Label container classes.
Definition: labelIOList.H:42
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
error FatalError
static const char nl
Definition: Ostream.H:267
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488