polyMesh.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 "OSspecific.H"
28 #include "Time.H"
29 #include "cellIOList.H"
30 #include "wedgePolyPatch.H"
31 #include "emptyPolyPatch.H"
32 #include "globalMeshData.H"
33 #include "processorPolyPatch.H"
35 #include "meshObjects.H"
36 #include "pointMesh.H"
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
43 }
44 
45 
47 
48 
50 
51 
52 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
53 
54 Foam::fileName Foam::polyMesh::regionDir(const IOobject& io)
55 {
56  if (io.name() == defaultRegion)
57  {
58  return io.db().dbDir()/io.local();
59  }
60  else
61  {
62  return io.db().dbDir()/io.local()/io.name();
63  }
64 }
65 
66 
67 void Foam::polyMesh::calcDirections() const
68 {
69  for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
70  {
71  solutionD_[cmpt] = 1;
72  }
73 
74  // Knock out empty and wedge directions. Note:they will be present on all
75  // domains.
76 
77  label nEmptyPatches = 0;
78  label nWedgePatches = 0;
79 
80  vector emptyDirVec = Zero;
81  vector wedgeDirVec = Zero;
82 
83  forAll(boundaryMesh(), patchi)
84  {
85  if (boundaryMesh()[patchi].size())
86  {
87  if (isA<emptyPolyPatch>(boundaryMesh()[patchi]))
88  {
89  nEmptyPatches++;
90  emptyDirVec += sum(cmptMag(boundaryMesh()[patchi].faceAreas()));
91  }
92  else if (isA<wedgePolyPatch>(boundaryMesh()[patchi]))
93  {
94  const wedgePolyPatch& wpp = refCast<const wedgePolyPatch>
95  (
96  boundaryMesh()[patchi]
97  );
98 
99  nWedgePatches++;
100  wedgeDirVec += cmptMag(wpp.centreNormal());
101  }
102  }
103  }
104 
105  reduce(nEmptyPatches, maxOp<label>());
106  reduce(nWedgePatches, maxOp<label>());
107 
108  if (nEmptyPatches)
109  {
110  reduce(emptyDirVec, sumOp<vector>());
111 
112  emptyDirVec /= mag(emptyDirVec);
113 
114  for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
115  {
116  if (emptyDirVec[cmpt] > 1e-6)
117  {
118  solutionD_[cmpt] = -1;
119  }
120  else
121  {
122  solutionD_[cmpt] = 1;
123  }
124  }
125  }
126 
127 
128  // Knock out wedge directions
129 
130  geometricD_ = solutionD_;
131 
132  if (nWedgePatches)
133  {
134  reduce(wedgeDirVec, sumOp<vector>());
135 
136  wedgeDirVec /= mag(wedgeDirVec);
137 
138  for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
139  {
140  if (wedgeDirVec[cmpt] > 1e-6)
141  {
142  geometricD_[cmpt] = -1;
143  }
144  else
145  {
146  geometricD_[cmpt] = 1;
147  }
148  }
149  }
150 }
151 
152 
153 Foam::autoPtr<Foam::labelIOList> Foam::polyMesh::readTetBasePtIs() const
154 {
155  typeIOobject<labelIOList> io
156  (
157  "tetBasePtIs",
158  instance(),
159  meshSubDir,
160  *this,
163  );
164 
165  if (io.headerOk())
166  {
167  return autoPtr<labelIOList>(new labelIOList(io));
168  }
169  else
170  {
171  return autoPtr<labelIOList>(nullptr);
172  }
173 }
174 
175 
176 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
177 
179 :
180  objectRegistry(io, regionDir(io)),
181  primitiveMesh(),
182  points_
183  (
184  IOobject
185  (
186  "points",
187  time().findInstance(meshDir(), "points"),
188  meshSubDir,
189  *this,
190  IOobject::MUST_READ,
191  IOobject::NO_WRITE
192  )
193  ),
194  faces_
195  (
196  IOobject
197  (
198  "faces",
199  time().findInstance(meshDir(), "faces"),
200  meshSubDir,
201  *this,
202  IOobject::MUST_READ,
203  IOobject::NO_WRITE
204  )
205  ),
206  owner_
207  (
208  IOobject
209  (
210  "owner",
211  faces_.instance(),
212  meshSubDir,
213  *this,
214  IOobject::READ_IF_PRESENT,
215  IOobject::NO_WRITE
216  )
217  ),
218  neighbour_
219  (
220  IOobject
221  (
222  "neighbour",
223  faces_.instance(),
224  meshSubDir,
225  *this,
226  IOobject::READ_IF_PRESENT,
227  IOobject::NO_WRITE
228  )
229  ),
230  clearedPrimitives_(false),
231  boundary_
232  (
233  IOobject
234  (
235  "boundary",
236  faces_.instance(),
237  meshSubDir,
238  *this,
239  IOobject::MUST_READ,
240  IOobject::NO_WRITE
241  ),
242  *this
243  ),
244  bounds_(points_),
245  comm_(UPstream::worldComm),
246  geometricD_(Zero),
247  solutionD_(Zero),
248  tetBasePtIsPtr_(readTetBasePtIs()),
249  pointZones_
250  (
251  IOobject
252  (
253  "pointZones",
254  time().findInstance
255  (
256  meshDir(),
257  "pointZones",
258  IOobject::READ_IF_PRESENT,
259  faces_.instance()
260  ),
261  meshSubDir,
262  *this,
263  IOobject::NO_READ, // Delay reading
264  IOobject::NO_WRITE
265  ),
266  *this
267  ),
268  faceZones_
269  (
270  IOobject
271  (
272  "faceZones",
273  time().findInstance
274  (
275  meshDir(),
276  "faceZones",
277  IOobject::READ_IF_PRESENT,
278  faces_.instance()
279  ),
280  meshSubDir,
281  *this,
282  IOobject::NO_READ, // Delay reading
283  IOobject::NO_WRITE
284  ),
285  *this
286  ),
287  cellZones_
288  (
289  IOobject
290  (
291  "cellZones",
292  time().findInstance
293  (
294  meshDir(),
295  "cellZones",
296  IOobject::READ_IF_PRESENT,
297  faces_.instance()
298  ),
299  meshSubDir,
300  *this,
301  IOobject::NO_READ, // Delay reading
302  IOobject::NO_WRITE
303  ),
304  *this
305  ),
306  globalMeshDataPtr_(nullptr),
307  curMotionTimeIndex_(-1),
308  oldPointsPtr_(nullptr),
309  oldCellCentresPtr_(nullptr),
310  storeOldCellCentres_(false),
311  moving_(false),
312  topoChanged_(false)
313 {
314  if (!owner_.headerClassName().empty())
315  {
316  initMesh();
317  }
318  else
319  {
320  cellCompactIOList cLst
321  (
322  IOobject
323  (
324  "cells",
325  faces_.instance(),
326  meshSubDir,
327  *this,
330  )
331  );
332 
333  // Set the primitive mesh
334  initMesh(cLst);
335 
336  owner_.write();
337  neighbour_.write();
338  }
339 
340  // Calculate topology for the patches (processor-processor comms etc.)
341  boundary_.topoChange();
342 
343  // Calculate the geometry for the patches (transformation tensors etc.)
344  boundary_.calcGeometry();
345 
346  // Warn if global empty mesh
347  const bool complete = Pstream::parRun() || !time().processorCase();
348  if (complete && returnReduce(nPoints(), sumOp<label>()) == 0)
349  {
351  << "no points in mesh" << endl;
352  }
353  if (complete && returnReduce(nCells(), sumOp<label>()) == 0)
354  {
356  << "no cells in mesh" << endl;
357  }
358 
359  // Initialise demand-driven data
360  calcDirections();
361 
362  // Read the zones now that the mesh geometry is available to construct them
363  pointZones_.readIfPresent();
364  faceZones_.readIfPresent();
365  cellZones_.readIfPresent();
366 }
367 
368 
370 (
371  const IOobject& io,
372  pointField&& points,
373  faceList&& faces,
374  labelList&& owner,
375  labelList&& neighbour,
376  const bool syncPar
377 )
378 :
379  objectRegistry(io, regionDir(io)),
380  primitiveMesh(),
381  points_
382  (
383  IOobject
384  (
385  "points",
386  instance(),
387  meshSubDir,
388  *this,
389  io.readOpt(),
390  IOobject::AUTO_WRITE
391  ),
392  move(points)
393  ),
394  faces_
395  (
396  IOobject
397  (
398  "faces",
399  instance(),
400  meshSubDir,
401  *this,
402  io.readOpt(),
403  IOobject::AUTO_WRITE
404  ),
405  move(faces)
406  ),
407  owner_
408  (
409  IOobject
410  (
411  "owner",
412  instance(),
413  meshSubDir,
414  *this,
415  io.readOpt(),
416  IOobject::AUTO_WRITE
417  ),
418  move(owner)
419  ),
420  neighbour_
421  (
422  IOobject
423  (
424  "neighbour",
425  instance(),
426  meshSubDir,
427  *this,
428  io.readOpt(),
429  IOobject::AUTO_WRITE
430  ),
431  move(neighbour)
432  ),
433  clearedPrimitives_(false),
434  boundary_
435  (
436  IOobject
437  (
438  "boundary",
439  instance(),
440  meshSubDir,
441  *this,
442  io.readOpt(),
443  IOobject::AUTO_WRITE
444  ),
445  *this,
446  polyPatchList()
447  ),
448  bounds_(points_, syncPar),
449  comm_(UPstream::worldComm),
450  geometricD_(Zero),
451  solutionD_(Zero),
452  tetBasePtIsPtr_(readTetBasePtIs()),
453  pointZones_
454  (
455  IOobject
456  (
457  "pointZones",
458  instance(),
459  meshSubDir,
460  *this,
461  io.readOpt(),
462  IOobject::NO_WRITE
463  ),
464  *this
465  ),
466  faceZones_
467  (
468  IOobject
469  (
470  "faceZones",
471  instance(),
472  meshSubDir,
473  *this,
474  io.readOpt(),
475  IOobject::NO_WRITE
476  ),
477  *this
478  ),
479  cellZones_
480  (
481  IOobject
482  (
483  "cellZones",
484  instance(),
485  meshSubDir,
486  *this,
487  io.readOpt(),
488  IOobject::NO_WRITE
489  ),
490  *this
491  ),
492  globalMeshDataPtr_(nullptr),
493  curMotionTimeIndex_(-1),
494  oldPointsPtr_(nullptr),
495  oldCellCentresPtr_(nullptr),
496  storeOldCellCentres_(false),
497  moving_(false),
498  topoChanged_(false)
499 {
500  // Check if the faces and cells are valid
501  forAll(faces_, facei)
502  {
503  const face& curFace = faces_[facei];
504 
505  if (min(curFace) < 0 || max(curFace) > points_.size())
506  {
508  << "Face " << facei << "contains vertex labels out of range: "
509  << curFace << " Max point index = " << points_.size()
510  << abort(FatalError);
511  }
512  }
513 
514  // Set the primitive mesh
515  initMesh();
516 }
517 
518 
520 (
521  const IOobject& io,
522  pointField&& points,
523  faceList&& faces,
524  cellList&& cells,
525  const bool syncPar
526 )
527 :
528  objectRegistry(io, regionDir(io)),
529  primitiveMesh(),
530  points_
531  (
532  IOobject
533  (
534  "points",
535  instance(),
536  meshSubDir,
537  *this,
538  IOobject::NO_READ,
539  IOobject::AUTO_WRITE
540  ),
541  move(points)
542  ),
543  faces_
544  (
545  IOobject
546  (
547  "faces",
548  instance(),
549  meshSubDir,
550  *this,
551  IOobject::NO_READ,
552  IOobject::AUTO_WRITE
553  ),
554  move(faces)
555  ),
556  owner_
557  (
558  IOobject
559  (
560  "owner",
561  instance(),
562  meshSubDir,
563  *this,
564  IOobject::NO_READ,
565  IOobject::AUTO_WRITE
566  ),
567  label(0)
568  ),
569  neighbour_
570  (
571  IOobject
572  (
573  "neighbour",
574  instance(),
575  meshSubDir,
576  *this,
577  IOobject::NO_READ,
578  IOobject::AUTO_WRITE
579  ),
580  label(0)
581  ),
582  clearedPrimitives_(false),
583  boundary_
584  (
585  IOobject
586  (
587  "boundary",
588  instance(),
589  meshSubDir,
590  *this,
591  IOobject::NO_READ,
592  IOobject::AUTO_WRITE
593  ),
594  *this,
595  0
596  ),
597  bounds_(points_, syncPar),
598  comm_(UPstream::worldComm),
599  geometricD_(Zero),
600  solutionD_(Zero),
601  tetBasePtIsPtr_(readTetBasePtIs()),
602  pointZones_
603  (
604  IOobject
605  (
606  "pointZones",
607  instance(),
608  meshSubDir,
609  *this,
610  IOobject::NO_READ,
611  IOobject::NO_WRITE
612  ),
613  *this
614  ),
615  faceZones_
616  (
617  IOobject
618  (
619  "faceZones",
620  instance(),
621  meshSubDir,
622  *this,
623  IOobject::NO_READ,
624  IOobject::NO_WRITE
625  ),
626  *this
627  ),
628  cellZones_
629  (
630  IOobject
631  (
632  "cellZones",
633  instance(),
634  meshSubDir,
635  *this,
636  IOobject::NO_READ,
637  IOobject::NO_WRITE
638  ),
639  *this
640  ),
641  globalMeshDataPtr_(nullptr),
642  curMotionTimeIndex_(-1),
643  oldPointsPtr_(nullptr),
644  oldCellCentresPtr_(nullptr),
645  storeOldCellCentres_(false),
646  moving_(false),
647  topoChanged_(false)
648 {
649  // Check if faces are valid
650  forAll(faces_, facei)
651  {
652  const face& curFace = faces_[facei];
653 
654  if (min(curFace) < 0 || max(curFace) > points_.size())
655  {
657  << "Face " << facei << "contains vertex labels out of range: "
658  << curFace << " Max point index = " << points_.size()
659  << abort(FatalError);
660  }
661  }
662 
663  // transfer in cell list
664  cellList cLst(move(cells));
665 
666  // Check if cells are valid
667  forAll(cLst, celli)
668  {
669  const cell& curCell = cLst[celli];
670 
671  if (min(curCell) < 0 || max(curCell) > faces_.size())
672  {
674  << "Cell " << celli << "contains face labels out of range: "
675  << curCell << " Max face index = " << faces_.size()
676  << abort(FatalError);
677  }
678  }
679 
680  // Set the primitive mesh
681  initMesh(cLst);
682 }
683 
684 
686 :
687  objectRegistry(move(mesh)),
688  primitiveMesh(move(mesh)),
689  points_(move(mesh.points_)),
690  faces_(move(mesh.faces_)),
691  owner_(move(mesh.owner_)),
692  neighbour_(move(mesh.neighbour_)),
693  clearedPrimitives_(mesh.clearedPrimitives_),
694  boundary_(move(mesh.boundary_)),
695  bounds_(move(mesh.bounds_)),
696  comm_(mesh.comm_),
697  geometricD_(mesh.geometricD_),
698  solutionD_(mesh.solutionD_),
699  tetBasePtIsPtr_(move(mesh.tetBasePtIsPtr_)),
700  pointZones_(move(mesh.pointZones_)),
701  faceZones_(move(mesh.faceZones_)),
702  cellZones_(move(mesh.cellZones_)),
703  globalMeshDataPtr_(move(mesh.globalMeshDataPtr_)),
704  curMotionTimeIndex_(mesh.curMotionTimeIndex_),
705  oldPointsPtr_(move(mesh.oldPointsPtr_)),
706  oldCellCentresPtr_(move(mesh.oldCellCentresPtr_)),
707  storeOldCellCentres_(mesh.storeOldCellCentres_),
708  moving_(mesh.moving_),
709  topoChanged_(mesh.topoChanged_)
710 {}
711 
712 
714 (
715  pointField&& points,
716  faceList&& faces,
717  labelList&& owner,
718  labelList&& neighbour,
719  const labelList& patchSizes,
720  const labelList& patchStarts,
721  const bool validBoundary
722 )
723 {
724  // Clear addressing. Keep geometric props and updateable props for mapping.
725  clearAddressing(true);
726 
727  // Take over new primitive data.
728  // Optimised to avoid overwriting data at all
729  if (notNull(points))
730  {
731  points_ = move(points);
732  bounds_ = boundBox(points_, validBoundary);
733  }
734 
735  if (notNull(faces))
736  {
737  faces_ = move(faces);
738  }
739 
740  if (notNull(owner))
741  {
742  owner_ = move(owner);
743  }
744 
745  if (notNull(neighbour))
746  {
747  neighbour_ = move(neighbour);
748  }
749 
750 
751  // Reset patch sizes and starts
752  forAll(boundary_, patchi)
753  {
754  boundary_[patchi] = polyPatch
755  (
756  boundary_[patchi],
757  boundary_,
758  patchi,
759  patchSizes[patchi],
760  patchStarts[patchi]
761  );
762  }
763 
764 
765  // Flags the mesh files as being changed
766  setInstance(time().name());
767 
768  // Check if the faces and cells are valid
769  forAll(faces_, facei)
770  {
771  const face& curFace = faces_[facei];
772 
773  if (min(curFace) < 0 || max(curFace) > points_.size())
774  {
776  << "Face " << facei << " contains vertex labels out of range: "
777  << curFace << " Max point index = " << points_.size()
778  << abort(FatalError);
779  }
780  }
781 
782 
783  // Set the primitive mesh from the owner_, neighbour_.
784  // Works out from patch end where the active faces stop.
785  initMesh();
786 
787 
788  if (validBoundary)
789  {
790  // Note that we assume that all the patches stay the same and are
791  // correct etc. so we can already use the patches to do
792  // processor-processor comms.
793 
794  // Calculate topology for the patches (processor-processor comms etc.)
795  boundary_.topoChange();
796 
797  // Calculate the geometry for the patches (transformation tensors etc.)
798  boundary_.calcGeometry();
799 
800  // Warn if global empty mesh
801  if
802  (
803  (returnReduce(nPoints(), sumOp<label>()) == 0)
804  || (returnReduce(nCells(), sumOp<label>()) == 0)
805  )
806  {
808  << "no points or no cells in mesh"
809  << exit(FatalError);
810  }
811  }
812 }
813 
814 
816 {
817  // Clear addressing. Keep geometric and updatable properties for mapping.
818  clearAddressing(true);
819  otherMesh.clearAddressing(true);
820 
821  // Swap the primitives
822  points_.swap(otherMesh.points_);
823  bounds_ = boundBox(points_, true);
824  faces_.swap(otherMesh.faces_);
825  owner_.swap(otherMesh.owner_);
826  neighbour_.swap(otherMesh.neighbour_);
827 
828  // Clear the boundary data
829  boundary_.clearGeom();
830  boundary_.clearAddressing();
831  otherMesh.boundary_.clearGeom();
832  otherMesh.boundary_.clearAddressing();
833 
834  // Swap the boundaries
835  auto updatePatches = []
836  (
837  const polyPatchList& otherPatches,
838  polyBoundaryMesh& boundaryMesh
839  )
840  {
841  boundaryMesh.resize(otherPatches.size());
842 
843  forAll(otherPatches, otherPatchi)
844  {
845  // Clone processor patches, as the decomposition may be different
846  // in the other mesh. Just change the size and start of other
847  // patches.
848 
849  if (isA<processorPolyPatch>(otherPatches[otherPatchi]))
850  {
851  boundaryMesh.set
852  (
853  otherPatchi,
854  otherPatches[otherPatchi].clone(boundaryMesh)
855  );
856  }
857  else
858  {
859  boundaryMesh[otherPatchi] = polyPatch
860  (
861  boundaryMesh[otherPatchi],
862  boundaryMesh,
863  otherPatchi,
864  otherPatches[otherPatchi].size(),
865  otherPatches[otherPatchi].start()
866  );
867  }
868  }
869  };
870 
871  {
872  const polyPatchList patches
873  (
874  boundary_,
875  otherMesh.boundary_
876  );
877  const polyPatchList otherPatches
878  (
879  otherMesh.boundary_,
880  boundary_
881  );
882 
883  updatePatches(otherPatches, boundary_);
884  updatePatches(patches, otherMesh.boundary_);
885  }
886 
887  // Parallel data depends on the patch ordering so force recalculation
888  globalMeshDataPtr_.clear();
889  otherMesh.globalMeshDataPtr_.clear();
890 
891  // Flags the mesh files as being changed
892  setInstance(time().name());
893  otherMesh.setInstance(time().name());
894 
895  // Check if the faces and cells are valid
896  auto checkFaces = [](const polyMesh& mesh)
897  {
898  forAll(mesh.faces_, facei)
899  {
900  const face& curFace = mesh.faces_[facei];
901 
902  if (min(curFace) < 0 || max(curFace) > mesh.points_.size())
903  {
905  << "Face " << facei << " contains vertex labels out of "
906  << "range: " << curFace << " Max point index = "
907  << mesh.points_.size() << abort(FatalError);
908  }
909  }
910  };
911 
912  checkFaces(*this);
913  checkFaces(otherMesh);
914 
915  // Set the primitive mesh from the owner_, neighbour_.
916  // Works out from patch end where the active faces stop.
917  initMesh();
918  otherMesh.initMesh();
919 
920  // Calculate topology for the patches (processor-processor comms etc.)
921  boundary_.topoChange();
922  otherMesh.boundary_.topoChange();
923 
924  // Calculate the geometry for the patches (transformation tensors etc.)
925  boundary_.calcGeometry();
926  otherMesh.boundary_.calcGeometry();
927 
928  // Update the optional pointMesh with respect to the updated polyMesh
929  if (foundObject<pointMesh>(pointMesh::typeName))
930  {
931  pointMesh::New(*this).reset();
932  }
933 
934  if (otherMesh.foundObject<pointMesh>(pointMesh::typeName))
935  {
936  pointMesh::New(*this).reset();
937  }
938 
939  // Swap zones
940  pointZones_.swap(otherMesh.pointZones_);
941  faceZones_.swap(otherMesh.faceZones_);
942  cellZones_.swap(otherMesh.cellZones_);
943 }
944 
945 
946 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
947 
949 {
950  clearOut();
951  resetMotion();
952 }
953 
954 
955 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
956 
958 {
959  // Create an IO object for the current-time polyMesh directory
960  const IOobject curDirIo
961  (
962  word::null,
963  io.time().name(),
965  ? fileName(io.local()/meshSubDir)
966  : fileName(io.local()/io.name()/meshSubDir),
967  io.time(),
969  );
970 
971  // Search back to find the latest-time polyMesh directory
972  const IOobject latestDirIo =
973  fileHandler().findInstance(curDirIo, io.time().value(), word::null);
974 
975  // Return whether or not this latest-time polyMesh directory exists
976  return fileHandler().isDir(fileHandler().objectPath(latestDirIo));
977 }
978 
979 
981 {
982  return dbDir()/meshSubDir;
983 }
984 
985 
987 {
988  return points_.instance();
989 }
990 
991 
993 {
994  return faces_.instance();
995 }
996 
997 
999 {
1000  return points_.writeOpt();
1001 }
1002 
1003 
1005 {
1006  return faces_.writeOpt();
1007 }
1008 
1009 
1011 {
1012  if (geometricD_.x() == 0)
1013  {
1014  calcDirections();
1015  }
1016 
1017  return geometricD_;
1018 }
1019 
1020 
1022 {
1023  return cmptSum(geometricD() + Vector<label>::one)/2;
1024 }
1025 
1026 
1028 {
1029  if (solutionD_.x() == 0)
1030  {
1031  calcDirections();
1032  }
1033 
1034  return solutionD_;
1035 }
1036 
1037 
1039 {
1040  return cmptSum(solutionD() + Vector<label>::one)/2;
1041 }
1042 
1043 
1045 {
1046  if (tetBasePtIsPtr_.empty())
1047  {
1048  if (debug)
1049  {
1051  << "Forcing storage of base points."
1052  << endl;
1053  }
1054 
1055  tetBasePtIsPtr_.reset
1056  (
1057  new labelIOList
1058  (
1059  IOobject
1060  (
1061  "tetBasePtIs",
1062  instance(),
1063  meshSubDir,
1064  *this,
1067  ),
1069  )
1070  );
1071  }
1072 
1073  return tetBasePtIsPtr_();
1074 }
1075 
1076 
1078 (
1079  const List<polyPatch*>& p,
1080  const bool validBoundary
1081 )
1082 {
1083  if (boundaryMesh().size())
1084  {
1086  << "boundary already exists"
1087  << abort(FatalError);
1088  }
1089 
1090  // Reset valid directions
1091  geometricD_ = Zero;
1092  solutionD_ = Zero;
1093 
1094  boundary_.setSize(p.size());
1095 
1096  // Copy the patch pointers
1097  forAll(p, pI)
1098  {
1099  boundary_.set(pI, p[pI]);
1100  }
1101 
1102  // parallelData depends on the processorPatch ordering so force
1103  // recalculation. Problem: should really be done in removeBoundary but
1104  // there is some info in parallelData which might be interesting in between
1105  // removeBoundary and addPatches.
1106  globalMeshDataPtr_.clear();
1107 
1108  if (validBoundary)
1109  {
1110  addedPatches();
1111  }
1112 }
1113 
1114 
1116 (
1117  const List<pointZone*>& pz,
1118  const List<faceZone*>& fz,
1119  const List<cellZone*>& cz
1120 )
1121 {
1122  if (pointZones().size() || faceZones().size() || cellZones().size())
1123  {
1125  << "point, face or cell zone already exists"
1126  << abort(FatalError);
1127  }
1128 
1129  // Point zones
1130  if (pz.size())
1131  {
1132  pointZones_.setSize(pz.size());
1133 
1134  // Copy the zone pointers
1135  forAll(pz, pI)
1136  {
1137  pointZones_.set(pI, pz[pI]->name(), pz[pI]);
1138  }
1139 
1140  pointZones_.writeOpt() = IOobject::AUTO_WRITE;
1141  }
1142 
1143  // Face zones
1144  if (fz.size())
1145  {
1146  faceZones_.setSize(fz.size());
1147 
1148  // Copy the zone pointers
1149  forAll(fz, fI)
1150  {
1151  faceZones_.set(fI, fz[fI]->name(), fz[fI]);
1152  }
1153 
1154  faceZones_.writeOpt() = IOobject::AUTO_WRITE;
1155  }
1156 
1157  // Cell zones
1158  if (cz.size())
1159  {
1160  cellZones_.setSize(cz.size());
1161 
1162  // Copy the zone pointers
1163  forAll(cz, cI)
1164  {
1165  cellZones_.set(cI, cz[cI]->name(), cz[cI]);
1166  }
1167 
1168  cellZones_.writeOpt() = IOobject::AUTO_WRITE;
1169  }
1170 }
1171 
1172 
1174 (
1175  const labelUList& newToOld,
1176  const bool validBoundary
1177 )
1178 {
1179  // Clear local fields and e.g. polyMesh parallelInfo
1180  boundary_.clearGeom();
1181  clearAddressing(true);
1182 
1183  // Clear all but RepatchableMeshObjects
1185  <
1186  polyMesh,
1189  >
1190  (
1191  *this
1192  );
1194  <
1195  pointMesh,
1198  >
1199  (
1200  *this
1201  );
1202 
1203  // Update time instance for the mesh
1204  // so that it writes the mesh with the changed boundary
1205  // into a new time directory
1206  setInstance(time().name());
1207 
1208  boundary_.reorderPatches(newToOld, validBoundary);
1209 
1210  // Warn mesh objects
1211  meshObjects::reorderPatches<polyMesh>(*this, newToOld, validBoundary);
1212  meshObjects::reorderPatches<pointMesh>(*this, newToOld, validBoundary);
1213 }
1214 
1215 
1217 (
1218  const label insertPatchi,
1219  const polyPatch& patch
1220 )
1221 {
1222  const label sz = boundary_.size();
1223 
1224  label startFacei = nFaces();
1225  if (insertPatchi < sz)
1226  {
1227  startFacei = boundary_[insertPatchi].start();
1228  }
1229 
1230  // Create reordering list
1231  // patches before insert position stay as is
1232  // patches after insert position move one up
1233  labelList newToOld(boundary_.size()+1);
1234  for (label i = 0; i < insertPatchi; i++)
1235  {
1236  newToOld[i] = i;
1237  }
1238  for (label i = insertPatchi; i < sz; i++)
1239  {
1240  newToOld[i+1] = i;
1241  }
1242  newToOld[insertPatchi] = -1;
1243 
1244  // Reorder
1245  reorderPatches(newToOld, false);
1246 
1247  // Clear local fields and e.g. polyMesh parallelInfo
1248  boundary_.clearGeom();
1249  clearAddressing(true);
1250 
1251  // Clear all but RepatchableMeshObjects
1253  <
1254  polyMesh,
1257  >
1258  (
1259  *this
1260  );
1262  <
1263  pointMesh,
1266  >
1267  (
1268  *this
1269  );
1270 
1271  // Insert polyPatch
1272  boundary_.set
1273  (
1274  insertPatchi,
1275  patch.clone
1276  (
1277  boundary_,
1278  insertPatchi, // index
1279  0, // size
1280  startFacei // start
1281  )
1282  );
1283 
1284  // Warn mesh objects
1285  meshObjects::addPatch<polyMesh>(*this, insertPatchi);
1286  meshObjects::addPatch<pointMesh>(*this, insertPatchi);
1287 }
1288 
1289 
1291 {
1292  // Calculate topology for the patches (processor-processor comms etc.)
1293  boundary_.topoChange();
1294 
1295  // Calculate the geometry for the patches (transformation tensors etc.)
1296  boundary_.calcGeometry();
1297 
1298  boundary_.checkDefinition();
1299 }
1300 
1301 
1303 {
1304  if (clearedPrimitives_)
1305  {
1307  << "points deallocated"
1308  << abort(FatalError);
1309  }
1310 
1311  return points_;
1312 }
1313 
1314 
1316 {
1317  if (clearedPrimitives_)
1318  {
1320  << "faces deallocated"
1321  << abort(FatalError);
1322  }
1323 
1324  return faces_;
1325 }
1326 
1327 
1329 {
1330  return owner_;
1331 }
1332 
1333 
1335 {
1336  return neighbour_;
1337 }
1338 
1339 
1341 {
1342  if (!moving_)
1343  {
1344  return points_;
1345  }
1346 
1347  if (oldPointsPtr_.empty())
1348  {
1350  << "Old points have not been stored"
1351  << exit(FatalError);
1352  }
1353 
1354  return oldPointsPtr_();
1355 }
1356 
1357 
1359 {
1360  storeOldCellCentres_ = true;
1361 
1362  if (!moving_)
1363  {
1364  return cellCentres();
1365  }
1366 
1367  if (oldCellCentresPtr_.empty())
1368  {
1370  << "Old cell centres have not been stored"
1371  << exit(FatalError);
1372  }
1373 
1374  return oldCellCentresPtr_();
1375 }
1376 
1377 
1379 {
1380  if (debug)
1381  {
1383  << "Set points for time " << time().value()
1384  << " index " << time().timeIndex() << endl;
1385  }
1386 
1388 
1389  points_ = newPoints;
1390 
1391  setPointsInstance(time().name());
1392 
1393  // Adjust parallel shared points
1394  if (globalMeshDataPtr_.valid())
1395  {
1396  globalMeshDataPtr_().movePoints(points_);
1397  }
1398 
1399  // Force recalculation of all geometric data with new points
1400 
1401  bounds_ = boundBox(points_);
1402  boundary_.movePoints(points_);
1403 
1404  pointZones_.movePoints(points_);
1405  faceZones_.movePoints(points_);
1406  cellZones_.movePoints(points_);
1407 
1408  // Reset valid directions (could change with rotation)
1409  geometricD_ = Zero;
1410  solutionD_ = Zero;
1411 
1412  meshObjects::movePoints<polyMesh>(*this);
1413  meshObjects::movePoints<pointMesh>(*this);
1414 }
1415 
1416 
1418 (
1419  const pointField& newPoints
1420 )
1421 {
1422  if (debug)
1423  {
1425  << "Moving points for time " << time().value()
1426  << " index " << time().timeIndex() << endl;
1427  }
1428 
1429  // Pick up old points and cell centres
1430  if (curMotionTimeIndex_ != time().timeIndex())
1431  {
1432  oldPointsPtr_.clear();
1433  oldPointsPtr_.reset(new pointField(points_));
1434  if (storeOldCellCentres_)
1435  {
1436  oldCellCentresPtr_.clear();
1437  oldCellCentresPtr_.reset(new pointField(cellCentres()));
1438  }
1439  curMotionTimeIndex_ = time().timeIndex();
1440  }
1441 
1442  points_ = newPoints;
1443 
1444  setPointsInstance(time().name());
1445 
1447  (
1448  points_,
1449  oldPoints()
1450  );
1451 
1452  // Adjust parallel shared points
1453  if (globalMeshDataPtr_.valid())
1454  {
1455  globalMeshDataPtr_().movePoints(points_);
1456  }
1457 
1458  // Force recalculation of all geometric data with new points
1459 
1460  bounds_ = boundBox(points_);
1461  boundary_.movePoints(points_);
1462 
1463  pointZones_.movePoints(points_);
1464  faceZones_.movePoints(points_);
1465  cellZones_.movePoints(points_);
1466 
1467  // Reset valid directions (could change with rotation)
1468  geometricD_ = Zero;
1469  solutionD_ = Zero;
1470 
1471  meshObjects::movePoints<polyMesh>(*this);
1472  meshObjects::movePoints<pointMesh>(*this);
1473 
1474  return sweptVols;
1475 }
1476 
1477 
1479 {
1480  curMotionTimeIndex_ = -1;
1481  oldPointsPtr_.clear();
1482  oldCellCentresPtr_.clear();
1483 }
1484 
1485 
1487 {
1488  if (globalMeshDataPtr_.empty())
1489  {
1490  if (debug)
1491  {
1492  Pout<< "polyMesh::globalData() const : "
1493  << "Constructing parallelData from processor topology"
1494  << endl;
1495  }
1496  // Construct globalMeshData using processorPatch information only.
1497  globalMeshDataPtr_.reset(new globalMeshData(*this));
1498  }
1499 
1500  return globalMeshDataPtr_();
1501 }
1502 
1503 
1505 {
1506  return comm_;
1507 }
1508 
1509 
1511 {
1512  return comm_;
1513 }
1514 
1515 
1516 void Foam::polyMesh::removeFiles(const fileName& instanceDir) const
1517 {
1518  fileName meshFilesPath = thisDb().time().path()/instanceDir/meshDir();
1519 
1520  rm(meshFilesPath/"points");
1521  rm(meshFilesPath/"faces");
1522  rm(meshFilesPath/"owner");
1523  rm(meshFilesPath/"neighbour");
1524  rm(meshFilesPath/"cells");
1525  rm(meshFilesPath/"boundary");
1526  rm(meshFilesPath/"pointZones");
1527  rm(meshFilesPath/"faceZones");
1528  rm(meshFilesPath/"cellZones");
1529  rm(meshFilesPath/"meshModifiers");
1530  rm(meshFilesPath/"parallelData");
1531 
1532  // remove subdirectories
1533  if (isDir(meshFilesPath/"sets"))
1534  {
1535  rmDir(meshFilesPath/"sets");
1536  }
1537 }
1538 
1539 
1541 {
1542  removeFiles(instance());
1543 }
1544 
1545 
1546 // ************************************************************************* //
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....
MeshObject types:
Definition: MeshObjects.H:67
static pointMesh & New(const word &name, const polyMesh &mesh)
Construct and return the named DemandDrivenMeshObject.
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
const fileName & local() const
Definition: IOobject.H:400
const Time & time() const
Return time.
Definition: IOobject.C:315
fileName & instance() const
Return the instance directory, constant, system, <time> etc.
Definition: IOobject.C:352
const word & headerClassName() const
Return name of the class name read from header.
Definition: IOobject.H:313
const word & name() const
Return name.
Definition: IOobject.H:307
writeOption
Enumeration defining the write options.
Definition: IOobject.H:126
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: PtrList.H:75
bool processorCase() const
Return true if this is a processor case.
Definition: TimePaths.H:88
Inter-processor communications stream.
Definition: UPstream.H:59
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
static const direction nComponents
Number of components in this vector space.
Definition: VectorSpace.H:105
Templated 3D Vector derived from VectorSpace adding construction from 3 components,...
Definition: Vector.H:60
bool readIfPresent()
Read zones if the zones file is present.
Definition: ZoneList.C:560
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:59
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:60
const Type & value() const
Return const reference to value.
const word & name() const
Return const reference to name.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
A class for handling file names.
Definition: fileName.H:82
word name() const
Return file name (part beyond last /)
Definition: fileName.C:195
fileName path() const
Return directory path name (part before last /)
Definition: fileName.C:284
virtual IOobject findInstance(const IOobject &io, const scalar startValue, const word &stopInstance) const
Find instance where IOobject is. Fails if cannot be found.
virtual bool isDir(const fileName &, const bool followLink=true) const =0
Does the name exist as a directory in the file system?
Various mesh related information for a parallel run. Upon construction, constructs all info using par...
static void clearUpto(objectRegistry &)
Clear all meshObjects derived from FromType up to (but not including)
Registry of regIOobjects.
const Time & time() const
Return time.
bool foundObject(const word &name) const
Is the named Type in registry.
Mesh representing a set of points created from polyMesh.
Definition: pointMesh.H:53
void reset()
Reset pointMesh with respect to the updated polyMesh.
Definition: pointMesh.C:183
Foam::polyBoundaryMesh.
void topoChange()
Correct polyBoundaryMesh after topology update.
void clearGeom()
Clear geometry at this level and at patches.
void clearAddressing()
Clear addressing at this level and at patches.
static labelList findFaceBasePts(const polyMesh &mesh, scalar tol=minTetQuality, bool report=false)
Find a suitable base point for each face for decomposition.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:78
virtual ~polyMesh()
Destructor.
Definition: polyMesh.C:948
const fileName & facesInstance() const
Return the current instance directory for faces.
Definition: polyMesh.C:992
label nGeometricD() const
Return the number of valid geometric dimensions in the mesh.
Definition: polyMesh.C:1021
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:251
fileName meshDir() const
Return the local mesh directory (dbDir()/meshSubDir)
Definition: polyMesh.C:980
virtual tmp< scalarField > movePoints(const pointField &)
Move points, returns volumes swept by faces in motion.
Definition: polyMesh.C:1418
IOobject::writeOption facesWriteOpt() const
Return the points write option.
Definition: polyMesh.C:1004
static bool found(const IOobject &io)
Return whether the given IOobject relates to a mesh on disk.
Definition: polyMesh.C:957
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1315
void addedPatches()
Complete addition of single patches.
Definition: polyMesh.C:1290
void resetPrimitives(pointField &&points, faceList &&faces, labelList &&owner, labelList &&neighbour, const labelList &patchSizes, const labelList &patchStarts, const bool validBoundary=true)
Reset mesh primitive data. Assumes all patch info correct.
Definition: polyMesh.C:714
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1328
const labelIOList & tetBasePtIs() const
Return the tetBasePtIs.
Definition: polyMesh.C:1044
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1486
label nSolutionD() const
Return the number of valid solved-for dimensions in the mesh.
Definition: polyMesh.C:1038
virtual const pointField & oldPoints() const
Return old points for mesh motion.
Definition: polyMesh.C:1340
void swap(polyMesh &)
Swap mesh.
Definition: polyMesh.C:815
const fileName & pointsInstance() const
Return the current instance directory for points.
Definition: polyMesh.C:986
label comm() const
Return communicator used for parallel communication.
Definition: polyMesh.C:1504
polyMesh(const IOobject &io)
Construct from IOobject.
Definition: polyMesh.C:178
void clearAddressing(const bool isMeshUpdate=false)
Clear addressing.
Definition: polyMeshClear.C:85
void resetMotion() const
Reset motion.
Definition: polyMesh.C:1478
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1334
void addPatches(const List< polyPatch * > &, const bool validBoundary=true)
Add boundary patches.
Definition: polyMesh.C:1078
void addZones(const List< pointZone * > &pz, const List< faceZone * > &fz, const List< cellZone * > &cz)
Add mesh zones.
Definition: polyMesh.C:1116
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1302
IOobject::writeOption pointsWriteOpt() const
Return the points write option.
Definition: polyMesh.C:998
void removeFiles() const
Remove all files from mesh instance()
Definition: polyMesh.C:1540
virtual const pointField & oldCellCentres() const
Return old cell centres for mesh motion.
Definition: polyMesh.C:1358
virtual void reorderPatches(const labelUList &newToOld, const bool validBoundary)
Reorder and trim existing patches. If validBoundary the new.
Definition: polyMesh.C:1174
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:254
void setInstance(const fileName &)
Set the instance for mesh files.
Definition: polyMeshIO.C:91
virtual void addPatch(const label insertPatchi, const polyPatch &patch)
Add/insert single patch.
Definition: polyMesh.C:1217
virtual void setPoints(const pointField &)
Reset the points.
Definition: polyMesh.C:1378
const Vector< label > & solutionD() const
Return the vector of solved-for directions in mesh.
Definition: polyMesh.C:1027
const Vector< label > & geometricD() const
Return the vector of geometric directions in mesh.
Definition: polyMesh.C:1010
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:70
virtual autoPtr< polyPatch > clone(const polyBoundaryMesh &bm) const
Construct and return a clone, resetting the boundary mesh.
Definition: polyPatch.H:215
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:75
void clearGeom()
Clear geometry.
label nCells() const
label nPoints() const
tmp< scalarField > movePoints(const pointField &p, const pointField &oldP)
Move points, returns volumes swept by faces in motion.
const cellList & cells() const
virtual bool write(const bool write=true) const
Write using setting from DB.
A class for managing temporary objects.
Definition: tmp.H:55
A class for handling words, derived from string.
Definition: word.H:62
static const word null
An empty word.
Definition: word.H:77
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
label patchi
const pointField & points
label nPoints
const cellShapeList & cells
const fvPatchList & patches
#define WarningInFunction
Report a warning using Foam::Warning.
#define InfoInFunction
Report an information message using Foam::Info.
Namespace for OpenFOAM.
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
const doubleScalar e
Definition: doubleScalar.H:106
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
bool rm(const fileName &)
Remove a file, returning true if successful otherwise false.
Definition: POSIX.C:1017
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:258
errorManip< error > abort(error &err)
Definition: errorManip.H:131
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
void mag(LagrangianPatchField< scalar > &f, const LagrangianPatchField< Type > &f1)
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
bool notNull(const T &t)
Return true if t is not a reference to the nullObject of type T.
Definition: nullObjectI.H:64
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
bool rmDir(const fileName &)
Remove a directory and its contents.
Definition: POSIX.C:1047
defineTypeNameAndDebug(combustionModel, 0)
T clone(const T &t)
Definition: List.H:55
bool isDir(const fileName &, const bool followLink=true)
Does the name exist as a directory in the file system?
Definition: POSIX.C:539
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
IOList< label > labelIOList
Label container classes.
Definition: labelIOList.H:42
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
error FatalError
Cmpt cmptSum(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
Definition: VectorSpaceI.H:507
void cmptMag(LagrangianPatchField< Type > &f, const LagrangianPatchField< Type > &f1)
uint8_t direction
Definition: direction.H:45
label timeIndex
Definition: getTimeIndex.H:4
volScalarField & p