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