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-2026 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 // * * * * * * * * * * * * * Private 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 
71 // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
72 
74 {
75  scalar time0 = NaN;
76 
77  return readScalar(instance().c_str(), time0) && time0 < time().value();
78 }
79 
80 
81 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
82 
84 {
85  DebugInFunction << "Resetting points instance to " << inst << endl;
86 
87  instance() = inst;
88 
89  points_.instance() = inst;
90  points_.eventNo() = getEvent();
91 
92  if (tetBasePtIsPtr_.valid())
93  {
94  tetBasePtIsPtr_->instance() = inst;
95  tetBasePtIsPtr_().eventNo() = getEvent();
96  }
97 
98  setPointsWrite(IOobject::AUTO_WRITE);
99 }
100 
101 
103 {
104  DebugInFunction << "Resetting topology instance to " << inst << endl;
105 
106  setPointsInstance(inst);
107 
108  faces_.instance() = inst;
109  owner_.instance() = inst;
110  neighbour_.instance() = inst;
111  boundary_.instance() = inst;
112 
113  if (pointZones_.noTopoUpdate())
114  {
115  pointZones_.instance() = inst;
116  }
117 
118  if (faceZones_.noTopoUpdate())
119  {
120  faceZones_.instance() = inst;
121  }
122 
123  if (cellZones_.noTopoUpdate())
124  {
125  cellZones_.instance() = inst;
126  }
127 
128  setTopologyWrite(IOobject::AUTO_WRITE);
129 }
130 
131 
133 {
134  // Determine if this update moves forward in time. If so, searching back in
135  // time for data files will only go back as far as the previous instance.
136  const fileName instance0 = instance();
137  const bool forward = readUpdateIsForward();
138 
139  // Update the mesh instance
140  instance() = time().name();
141 
142  DebugInFunction << "Updating the polyMesh:" << endl;
143 
145 
146  // Find the points and faces instance
147  const fileName pointsInst
148  (
149  time().findInstance
150  (
151  meshDir(),
152  "points",
154  forward ? word(instance0) : word::null
155  )
156  );
157  const fileName facesInst
158  (
159  time().findInstance
160  (
161  meshDir(),
162  "faces",
164  forward ? word(instance0) : word::null
165  )
166  );
167 
168  DebugInfo
169  << " Faces instance: old = " << facesInstance()
170  << ", new = " << facesInst << nl
171  << " Points instance: old = " << pointsInstance()
172  << ", new = " << pointsInst << endl;
173 
174  if (facesInst != (forward ? instance0 : facesInstance()))
175  {
176  // Topological change
177  DebugInfo << " Topological change" << endl;
178 
179  clearOut();
180 
181  // Clear all DeletableMeshObjects
182  meshObjects::clearAll<polyMesh, DeletableMeshObject>(*this);
183 
184  points_ = pointIOField
185  (
186  IOobject
187  (
188  "points",
189  pointsInst,
190  meshSubDir,
191  *this,
194  false
195  )
196  );
197 
198  points_.instance() = pointsInst;
199 
200  faces_ = faceCompactIOList
201  (
202  IOobject
203  (
204  "faces",
205  facesInst,
206  meshSubDir,
207  *this,
210  false
211  )
212  );
213 
214  faces_.instance() = facesInst;
215 
216  owner_ = labelIOList
217  (
218  IOobject
219  (
220  "owner",
221  facesInst,
222  meshSubDir,
223  *this,
226  false
227  )
228  );
229 
230  owner_.instance() = facesInst;
231 
232  neighbour_ = labelIOList
233  (
234  IOobject
235  (
236  "neighbour",
237  facesInst,
238  meshSubDir,
239  *this,
242  false
243  )
244  );
245 
246  neighbour_.instance() = facesInst;
247 
248  // Reset the boundary patches
249  polyBoundaryMesh newBoundary
250  (
251  IOobject
252  (
253  "boundary",
254  facesInst,
255  meshSubDir,
256  *this,
259  false
260  ),
261  *this
262  );
263 
264  // Check that patch types and names are unchanged
265  bool boundaryChanged = false;
266 
267  if (newBoundary.size() != boundary_.size())
268  {
269  boundaryChanged = true;
270  }
271  else
272  {
273  wordList newTypes = newBoundary.types();
274  wordList newNames = newBoundary.names();
275 
276  wordList oldTypes = boundary_.types();
277  wordList oldNames = boundary_.names();
278 
279  forAll(oldTypes, patchi)
280  {
281  if
282  (
283  oldTypes[patchi] != newTypes[patchi]
284  || oldNames[patchi] != newNames[patchi]
285  )
286  {
287  boundaryChanged = true;
288  break;
289  }
290  }
291  }
292 
293  if (boundaryChanged)
294  {
295  boundary_.clear();
296  boundary_.setSize(newBoundary.size());
297 
298  forAll(newBoundary, patchi)
299  {
300  boundary_.set(patchi, newBoundary[patchi].clone(boundary_));
301  }
302  }
303  else
304  {
305  forAll(boundary_, patchi)
306  {
307  // boundary_[patchi] = polyPatch
308  // (
309  // newBoundary[patchi].name(),
310  // newBoundary[patchi].size(),
311  // newBoundary[patchi].start(),
312  // patchi,
313  // boundary_
314  // );
315 
316  boundary_[patchi].reset
317  (
318  newBoundary[patchi].size(),
319  newBoundary[patchi].start()
320  );
321  }
322  }
323 
324  boundary_.instance() = facesInst;
325 
326 
327  // Boundary is set so can use initMesh now (uses boundary_ to
328  // determine internal and active faces)
329 
330  if (!owner_.headerClassName().empty())
331  {
332  initMesh();
333  }
334  else
335  {
337  (
338  IOobject
339  (
340  "cells",
341  facesInst,
342  meshSubDir,
343  *this,
346  false
347  )
348  );
349 
350  // Recalculate the owner/neighbour addressing and reset the
351  // primitiveMesh
352  initMesh(cells);
353  }
354 
355 
356  // Even if number of patches stayed same still recalculate boundary
357  // data.
358 
359  // Calculate topology for the patches (processor-processor comms etc.)
360  boundary_.topoChange();
361 
362  // Calculate the geometry for the patches (transformation tensors etc.)
363  boundary_.calcGeometry();
364 
365  // Derived info
366  bounds_ = boundBox(points_);
367  geometricD_ = Zero;
368  solutionD_ = Zero;
369 
370  // Re-read tet base points
371  tetBasePtIsPtr_ = readTetBasePtIs();
372 
373  if (boundaryChanged)
374  {
376  }
377  else
378  {
379  state = polyMesh::TOPO_CHANGE;
380  }
381  }
382  else if (pointsInst != (forward ? instance0 : pointsInstance()))
383  {
384  // Points moved
385  DebugInfo << " Point motion" << endl;
386 
387  clearGeom();
388 
389  label nOldPoints = points_.size();
390 
391  points_.clear();
392 
393  pointIOField newPoints
394  (
395  IOobject
396  (
397  "points",
398  pointsInst,
399  meshSubDir,
400  *this,
403  false
404  )
405  );
406 
407  if (nOldPoints != 0 && nOldPoints != newPoints.size())
408  {
410  << "Point motion detected but number of points "
411  << newPoints.size() << " in "
412  << newPoints.objectPath() << " does not correspond to "
413  << " current " << nOldPoints
414  << exit(FatalError);
415  }
416 
417  points_.transfer(newPoints);
418 
419  points_.instance() = pointsInst;
420 
421  // Re-read tet base points
422  autoPtr<labelIOList> newTetBasePtIsPtr = readTetBasePtIs();
423  if (newTetBasePtIsPtr.valid())
424  {
425  tetBasePtIsPtr_ = newTetBasePtIsPtr;
426  }
427 
428  // Calculate the geometry for the patches (transformation tensors etc.)
429  boundary_.calcGeometry();
430 
431  // Derived info
432  bounds_ = boundBox(points_);
433 
434  // Rotation can cause direction vector to change
435  geometricD_ = Zero;
436  solutionD_ = Zero;
437 
438  state = polyMesh::POINTS_MOVED;
439  }
440 
441  // pointZones
442  {
443  const fileName pointZonesInst
444  (
445  time().findInstance
446  (
447  meshDir(),
448  "pointZones",
450  facesInst
451  )
452  );
453 
454  if (pointZonesInst != pointZones_.instance())
455  {
456  pointZoneList newPointZones
457  (
458  IOobject
459  (
460  "pointZones",
461  pointZonesInst,
462  meshSubDir,
463  *this,
466  false
467  ),
468  *this
469  );
470 
471  pointZones_.swap(newPointZones);
472  pointZones_.instance() = pointZonesInst;
473  }
474  }
475 
476  // faceZones
477  {
478  const fileName faceZonesInst
479  (
480  time().findInstance
481  (
482  meshDir(),
483  "faceZones",
485  facesInst
486  )
487  );
488 
489  if (faceZonesInst != faceZones_.instance())
490  {
491  faceZoneList newFaceZones
492  (
493  IOobject
494  (
495  "faceZones",
496  faceZonesInst,
497  meshSubDir,
498  *this,
501  false
502  ),
503  *this
504  );
505 
506  faceZones_.swap(newFaceZones);
507  faceZones_.instance() = faceZonesInst;
508  }
509  }
510 
511  // cellZones
512  {
513  const fileName cellZonesInst
514  (
515  time().findInstance
516  (
517  meshDir(),
518  "cellZones",
520  facesInst
521  )
522  );
523 
524  if (cellZonesInst != cellZones_.instance())
525  {
526  cellZoneList newCellZones
527  (
528  IOobject
529  (
530  "cellZones",
531  cellZonesInst,
532  meshSubDir,
533  *this,
536  false
537  ),
538  *this
539  );
540 
541  cellZones_.swap(newCellZones);
542  cellZones_.instance() = cellZonesInst;
543  }
544  }
545 
546  if (state == polyMesh::UNCHANGED)
547  {
548  DebugInfo << " No change" << endl;
549  }
550 
551  return state;
552 }
553 
554 
556 (
560  const bool write
561 ) const
562 {
563  if (faces_.writeOpt() == AUTO_WRITE)
564  {
565  auto rmAddressing = [&](const word& name)
566  {
567  const IOobject faceProcAddressingIO
568  (
569  name,
570  facesInstance(),
571  meshSubDir,
572  *this
573  );
574 
575  fileHandler().rm(faceProcAddressingIO.filePath(false));
576  };
577 
578  if (!Pstream::parRun())
579  {
580  rmAddressing("cellProc");
581  }
582  else
583  {
584  rmAddressing("pointProcAddressing");
585  rmAddressing("faceProcAddressing");
586  rmAddressing("cellProcAddressing");
587  }
588  }
589 
590  // Write the points out at a higher precision
591  if (points_.writeOpt() == IOobject::AUTO_WRITE)
592  {
593  unsigned int precision0 =
595 
596  points_.write();
597 
598  IOstream::defaultPrecision(precision0);
599  }
600 
601  const_cast<polyMesh&>(*this).points_.writeOpt() = IOobject::NO_WRITE;
602 
603  const bool written = objectRegistry::writeObject(fmt, ver, cmp, write);
604 
605  const_cast<polyMesh&>(*this).setTopologyWrite(IOobject::NO_WRITE);
606 
607  return written;
608 }
609 
610 
612 {
613  bool ok = true;
614 
615  // Write the points out at a higher precision
616  if (points_.writeOpt() == IOobject::AUTO_WRITE)
617  {
618  unsigned int precision0 =
620 
621  ok = ok && points_.write();
622 
623  IOstream::defaultPrecision(precision0);
624  }
625 
626  if (faces_.writeOpt() == IOobject::AUTO_WRITE)
627  {
628  ok = ok && faces_.write();
629  }
630 
631  if (owner_.writeOpt() == IOobject::AUTO_WRITE)
632  {
633  ok = ok && owner_.write();
634  }
635 
636  if (neighbour_.writeOpt() == IOobject::AUTO_WRITE)
637  {
638  ok = ok && neighbour_.write();
639  }
640 
641  if (pointZones_.writeOpt() == IOobject::AUTO_WRITE)
642  {
643  ok = ok && pointZones_.write();
644  }
645 
646  if (faceZones_.writeOpt() == IOobject::AUTO_WRITE)
647  {
648  ok = ok && faceZones_.write();
649  }
650 
651  if (cellZones_.writeOpt() == IOobject::AUTO_WRITE)
652  {
653  ok = ok && cellZones_.write();
654  }
655 
656  const_cast<polyMesh&>(*this).setTopologyWrite(IOobject::NO_WRITE);
657 
658  return ok;
659 }
660 
661 
662 // ************************************************************************* //
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:449
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
static unsigned int fullPrecision()
Return a full precision for writing data that is *very*.
Definition: IOstream.C:98
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:87
static unsigned int defaultPrecision()
Return the default precision.
Definition: IOstream.H:473
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:60
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:78
bool readUpdateIsForward() const
Does a read update move the mesh forward in time?
Definition: polyMeshIO.C:73
readUpdateState
Enumeration defining the state of the mesh after a read update.
Definition: polyMesh.H:88
@ TOPO_PATCH_CHANGE
Definition: polyMesh.H:92
virtual bool writeObject(IOstream::streamFormat fmt, IOstream::versionNumber ver, IOstream::compressionType cmp, const bool write=true) const
Write the mesh data and all objects in the registry.
Definition: polyMeshIO.C:556
readUpdateState readUpdate()
Update the mesh based on the mesh files saved in.
Definition: polyMeshIO.C:132
void setPointsInstance(const fileName &)
Set the instance for the points files.
Definition: polyMeshIO.C:83
void setInstance(const fileName &)
Set the instance for mesh files.
Definition: polyMeshIO.C:102
virtual bool writeMesh() const
Write the mesh data only.
Definition: polyMeshIO.C:611
fileName objectPath() const
Return complete path + object name.
Definition: regIOobject.H:155
A class for handling words, derived from string.
Definition: word.H:63
static const word null
An empty word.
Definition: word.H:78
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
label patchi
const cellShapeList & cells
#define DebugInfo
Report an information message using Foam::Info.
#define DebugInFunction
Report an information message using Foam::Info.
const dimensionSet time
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:288
CompactIOList< face > faceCompactIOList
Definition: faceIOList.H:44
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if successful.
Definition: doubleScalar.H:75
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:297