redistributePar.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Application
28  redistributePar
29 
30 Group
31  grpParallelUtilities
32 
33 Description
34  Redistributes existing decomposed mesh and fields according to the current
35  settings in the decomposeParDict file.
36 
37  Must be run on maximum number of source and destination processors.
38  Balances mesh and writes new mesh to new time directory.
39 
40  Can optionally run in decompose/reconstruct mode to decompose/reconstruct
41  mesh and fields.
42 
43 Usage
44  \b redistributePar [OPTION]
45 
46  Options:
47  - \par -decompose
48  Remove any existing \a processor subdirectories and decomposes the
49  mesh. Equivalent to running without processor subdirectories.
50 
51  - \par -reconstruct
52  Reconstruct mesh and fields (like reconstructParMesh+reconstructPar).
53 
54  - \par -newTimes
55  (in combination with -reconstruct) reconstruct only new times.
56 
57  - \par -dry-run
58  (not in combination with -reconstruct) Test without actually
59  decomposing.
60 
61  - \par -cellDist
62  not in combination with -reconstruct) Write the cell distribution
63  as a labelList, for use with 'manual'
64  decomposition method and as a volScalarField for visualization.
65 
66  - \par -region <regionName>
67  Distribute named region.
68 
69  - \par -allRegions
70  Distribute all regions in regionProperties. Does not check for
71  existence of processor*.
72 
73 \*---------------------------------------------------------------------------*/
74 
75 #include "argList.H"
76 #include "sigFpe.H"
77 #include "Time.H"
78 #include "fvMesh.H"
79 #include "fvMeshTools.H"
80 #include "fvMeshDistribute.H"
81 #include "decompositionMethod.H"
82 #include "decompositionModel.H"
83 #include "timeSelector.H"
84 #include "PstreamReduceOps.H"
85 #include "volFields.H"
86 #include "surfaceFields.H"
88 #include "IOobjectList.H"
89 #include "globalIndex.H"
90 #include "loadOrCreateMesh.H"
91 #include "processorFvPatchField.H"
93 #include "topoSet.H"
94 #include "regionProperties.H"
95 
99 #include "hexRef8Data.H"
100 #include "meshRefinement.H"
101 #include "pointFields.H"
102 
103 #include "cyclicACMIFvPatch.H"
104 
105 using namespace Foam;
106 
107 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
108 
109 // Tolerance (as fraction of the bounding box). Needs to be fairly lax since
110 // usually meshes get written with limited precision (6 digits)
111 static const scalar defaultMergeTol = 1e-6;
112 
113 
114 // Get merging distance when matching face centres
115 scalar getMergeDistance
116 (
117  const argList& args,
118  const Time& runTime,
119  const boundBox& bb
120 )
121 {
122  const scalar mergeTol =
123  args.getOrDefault<scalar>("mergeTol", defaultMergeTol);
124 
125  const scalar writeTol =
126  Foam::pow(scalar(10), -scalar(IOstream::defaultPrecision()));
127 
128  Info<< "Merge tolerance : " << mergeTol << nl
129  << "Write tolerance : " << writeTol << endl;
130 
131  if (runTime.writeFormat() == IOstream::ASCII && mergeTol < writeTol)
132  {
134  << "Your current settings specify ASCII writing with "
135  << IOstream::defaultPrecision() << " digits precision." << nl
136  << "Your merging tolerance (" << mergeTol << ") is finer than this."
137  << nl
138  << "Please change your writeFormat to binary"
139  << " or increase the writePrecision" << endl
140  << "or adjust the merge tolerance (-mergeTol)."
141  << exit(FatalError);
142  }
143 
144  const scalar mergeDist = mergeTol * bb.mag();
145 
146  Info<< "Overall meshes bounding box : " << bb << nl
147  << "Relative tolerance : " << mergeTol << nl
148  << "Absolute matching distance : " << mergeDist << nl
149  << endl;
150 
151  return mergeDist;
152 }
153 
154 
155 void printMeshData(const polyMesh& mesh)
156 {
157  // Collect all data on master
158 
159  globalIndex globalCells(mesh.nCells());
160  labelListList patchNeiProcNo(Pstream::nProcs());
161  labelListList patchSize(Pstream::nProcs());
162  const labelList& pPatches = mesh.globalData().processorPatches();
163  patchNeiProcNo[Pstream::myProcNo()].setSize(pPatches.size());
164  patchSize[Pstream::myProcNo()].setSize(pPatches.size());
165  forAll(pPatches, i)
166  {
167  const processorPolyPatch& ppp = refCast<const processorPolyPatch>
168  (
169  mesh.boundaryMesh()[pPatches[i]]
170  );
171  patchNeiProcNo[Pstream::myProcNo()][i] = ppp.neighbProcNo();
172  patchSize[Pstream::myProcNo()][i] = ppp.size();
173  }
174  Pstream::gatherList(patchNeiProcNo);
175  Pstream::gatherList(patchSize);
176 
177 
178  // Print stats
179 
180  globalIndex globalBoundaryFaces(mesh.nBoundaryFaces());
181 
182  label maxProcCells = 0;
183  label totProcFaces = 0;
184  label maxProcPatches = 0;
185  label totProcPatches = 0;
186  label maxProcFaces = 0;
187 
188  for (label procI = 0; procI < Pstream::nProcs(); ++procI)
189  {
190  Info<< nl
191  << "Processor " << procI << nl
192  << " Number of cells = " << globalCells.localSize(procI)
193  << endl;
194 
195  label nProcFaces = 0;
196 
197  const labelList& nei = patchNeiProcNo[procI];
198 
199  forAll(patchNeiProcNo[procI], i)
200  {
201  Info<< " Number of faces shared with processor "
202  << patchNeiProcNo[procI][i] << " = " << patchSize[procI][i]
203  << endl;
204 
205  nProcFaces += patchSize[procI][i];
206  }
207 
208  Info<< " Number of processor patches = " << nei.size() << nl
209  << " Number of processor faces = " << nProcFaces << nl
210  << " Number of boundary faces = "
211  << globalBoundaryFaces.localSize(procI)-nProcFaces << endl;
212 
213  maxProcCells = max(maxProcCells, globalCells.localSize(procI));
214  totProcFaces += nProcFaces;
215  totProcPatches += nei.size();
216  maxProcPatches = max(maxProcPatches, nei.size());
217  maxProcFaces = max(maxProcFaces, nProcFaces);
218  }
219 
220  // Stats
221 
222  scalar avgProcCells = scalar(globalCells.size())/Pstream::nProcs();
223  scalar avgProcPatches = scalar(totProcPatches)/Pstream::nProcs();
224  scalar avgProcFaces = scalar(totProcFaces)/Pstream::nProcs();
225 
226  // In case of all faces on one processor. Just to avoid division by 0.
227  if (totProcPatches == 0)
228  {
229  avgProcPatches = 1;
230  }
231  if (totProcFaces == 0)
232  {
233  avgProcFaces = 1;
234  }
235 
236  Info<< nl
237  << "Number of processor faces = " << totProcFaces/2 << nl
238  << "Max number of cells = " << maxProcCells
239  << " (" << 100.0*(maxProcCells-avgProcCells)/avgProcCells
240  << "% above average " << avgProcCells << ")" << nl
241  << "Max number of processor patches = " << maxProcPatches
242  << " (" << 100.0*(maxProcPatches-avgProcPatches)/avgProcPatches
243  << "% above average " << avgProcPatches << ")" << nl
244  << "Max number of faces between processors = " << maxProcFaces
245  << " (" << 100.0*(maxProcFaces-avgProcFaces)/avgProcFaces
246  << "% above average " << avgProcFaces << ")" << nl
247  << endl;
248 }
249 
250 
251 // Debugging: write volScalarField with decomposition for post processing.
252 void writeDecomposition
253 (
254  const word& name,
255  const fvMesh& mesh,
256  const labelUList& decomp
257 )
258 {
259  // Write the decomposition as labelList for use with 'manual'
260  // decomposition method.
261  labelIOList cellDecomposition
262  (
263  IOobject
264  (
265  "cellDecomposition",
266  mesh.facesInstance(), // mesh read from facesInstance
267  mesh,
270  false
271  ),
272  decomp
273  );
274  cellDecomposition.write();
275 
276  Info<< "Writing wanted cell distribution to volScalarField " << name
277  << " for postprocessing purposes." << nl << endl;
278 
279  volScalarField procCells
280  (
281  IOobject
282  (
283  name,
284  mesh.time().timeName(),
285  mesh,
288  false // do not register
289  ),
290  mesh,
292  zeroGradientFvPatchScalarField::typeName
293  );
294 
295  forAll(procCells, cI)
296  {
297  procCells[cI] = decomp[cI];
298  }
299 
300  procCells.correctBoundaryConditions();
301  procCells.write();
302 }
303 
304 
305 void determineDecomposition
306 (
307  const Time& baseRunTime,
308  const fileName& decompDictFile, // optional location for decomposeParDict
309  const bool decompose, // decompose, i.e. read from undecomposed case
310  const fileName& proc0CaseName,
311  const fvMesh& mesh,
312  const bool writeCellDist,
313 
314  label& nDestProcs,
315  labelList& decomp
316 )
317 {
318  // Read decomposeParDict (on all processors)
320  (
321  mesh,
322  decompDictFile
323  );
324 
325  decompositionMethod& decomposer = method.decomposer();
326 
327  if (!decomposer.parallelAware())
328  {
330  << "You have selected decomposition method "
331  << decomposer.typeName
332  << " which does" << nl
333  << "not synchronise the decomposition across"
334  << " processor patches." << nl
335  << " You might want to select a decomposition method"
336  << " which is aware of this. Continuing."
337  << endl;
338  }
339 
340  if (Pstream::master() && decompose)
341  {
342  Info<< "Setting caseName to " << baseRunTime.caseName()
343  << " to read decomposeParDict" << endl;
344  const_cast<Time&>(mesh.time()).caseName() = baseRunTime.caseName();
345  }
346 
347  scalarField cellWeights;
348  if (method.found("weightField"))
349  {
350  word weightName = method.get<word>("weightField");
351 
352  volScalarField weights
353  (
354  IOobject
355  (
356  weightName,
357  mesh.time().timeName(),
358  mesh,
361  ),
362  mesh
363  );
364  cellWeights = weights.internalField();
365  }
366 
367  nDestProcs = decomposer.nDomains();
368  decomp = decomposer.decompose(mesh, cellWeights);
369 
370  if (Pstream::master() && decompose)
371  {
372  Info<< "Restoring caseName to " << proc0CaseName << endl;
373  const_cast<Time&>(mesh.time()).caseName() = proc0CaseName;
374  }
375 
376  // Dump decomposition to volScalarField
377  if (writeCellDist)
378  {
379  // Note: on master make sure to write to processor0
380  if (decompose)
381  {
382  if (Pstream::master())
383  {
384  Info<< "Setting caseName to " << baseRunTime.caseName()
385  << " to write undecomposed cellDist" << endl;
386 
387  Time& tm = const_cast<Time&>(mesh.time());
388 
389  tm.caseName() = baseRunTime.caseName();
390  writeDecomposition("cellDist", mesh, decomp);
391  Info<< "Restoring caseName to " << proc0CaseName << endl;
392  tm.caseName() = proc0CaseName;
393  }
394  }
395  else
396  {
397  writeDecomposition("cellDist", mesh, decomp);
398  }
399  }
400 }
401 
402 
403 // Write addressing if decomposing (1 to many) or reconstructing (many to 1)
404 void writeProcAddressing
405 (
406  const fvMesh& mesh,
407  const mapDistributePolyMesh& map,
408  const bool decompose
409 )
410 {
411  Info<< "Writing procAddressing files to " << mesh.facesInstance()
412  << endl;
413 
414  labelIOList cellMap
415  (
416  IOobject
417  (
418  "cellProcAddressing",
421  mesh,
423  ),
424  0
425  );
426 
428  (
429  IOobject
430  (
431  "faceProcAddressing",
434  mesh,
436  ),
437  0
438  );
439 
440  labelIOList pointMap
441  (
442  IOobject
443  (
444  "pointProcAddressing",
447  mesh,
449  ),
450  0
451  );
452 
453  labelIOList patchMap
454  (
455  IOobject
456  (
457  "boundaryProcAddressing",
460  mesh,
462  ),
463  0
464  );
465 
466  // Decomposing: see how cells moved from undecomposed case
467  if (decompose)
468  {
469  cellMap = identity(map.nOldCells());
470  map.distributeCellData(cellMap);
471 
472  faceMap = identity(map.nOldFaces());
473  {
474  const mapDistribute& faceDistMap = map.faceMap();
475 
476  if (faceDistMap.subHasFlip() || faceDistMap.constructHasFlip())
477  {
478  // Offset by 1
479  faceMap = faceMap + 1;
480  }
481  // Apply face flips
483  (
485  List<labelPair>(),
486  faceDistMap.constructSize(),
487  faceDistMap.subMap(),
488  faceDistMap.subHasFlip(),
489  faceDistMap.constructMap(),
490  faceDistMap.constructHasFlip(),
491  faceMap,
492  flipLabelOp()
493  );
494  }
495 
496  pointMap = identity(map.nOldPoints());
497  map.distributePointData(pointMap);
498 
499  patchMap = identity(map.oldPatchSizes().size());
500  const mapDistribute& patchDistMap = map.patchMap();
501  // Use explicit distribute since we need to provide a null value
502  // (for new patches) and this is the only call that allow us to
503  // provide one ...
505  (
507  List<labelPair>(),
508  patchDistMap.constructSize(),
509  patchDistMap.subMap(),
510  patchDistMap.subHasFlip(),
511  patchDistMap.constructMap(),
512  patchDistMap.constructHasFlip(),
513  patchMap,
514  eqOp<label>(),
515  flipOp(),
516  label(-1),
518  );
519  }
520  else // reconstruct
521  {
522  cellMap = identity(mesh.nCells());
523  map.cellMap().reverseDistribute(map.nOldCells(), cellMap);
524 
526  {
527  const mapDistribute& faceDistMap = map.faceMap();
528 
529  if (faceDistMap.subHasFlip() || faceDistMap.constructHasFlip())
530  {
531  // Offset by 1
532  faceMap = faceMap + 1;
533  }
534 
536  (
538  List<labelPair>(),
539  map.nOldFaces(),
540  faceDistMap.constructMap(),
541  faceDistMap.constructHasFlip(),
542  faceDistMap.subMap(),
543  faceDistMap.subHasFlip(),
544  faceMap,
545  flipLabelOp()
546  );
547  }
548 
549  pointMap = identity(mesh.nPoints());
550  map.pointMap().reverseDistribute(map.nOldPoints(), pointMap);
551 
552  const mapDistribute& patchDistMap = map.patchMap();
553  patchMap = identity(mesh.boundaryMesh().size());
554  patchDistMap.reverseDistribute
555  (
556  map.oldPatchSizes().size(),
557  label(-1),
558  patchMap
559  );
560  }
561 
562  const bool cellOk = cellMap.write();
563  const bool faceOk = faceMap.write();
564  const bool pointOk = pointMap.write();
565  const bool patchOk = patchMap.write();
566 
567  if (!cellOk || !faceOk || !pointOk || !patchOk)
568  {
570  << "Failed to write " << cellMap.objectPath()
571  << ", " << faceMap.objectPath()
572  << ", " << pointMap.objectPath()
573  << ", " << patchMap.objectPath()
574  << endl;
575  }
576 }
577 
578 
579 // Remove addressing
580 void removeProcAddressing(const polyMesh& mesh)
581 {
582  for (const auto prefix : {"boundary", "cell", "face", "point"})
583  {
584  IOobject io
585  (
586  prefix + word("ProcAddressing"),
589  mesh
590  );
591 
592  const fileName procFile(io.objectPath());
593  rm(procFile);
594  }
595 }
596 
597 
598 // Generic mesh-based field reading
599 template<class GeoField>
600 void readField
601 (
602  const IOobject& io,
603  const fvMesh& mesh,
604  const label i,
606 )
607 {
608  fields.set(i, new GeoField(io, mesh));
609 }
610 
611 
612 // Definition of readField for GeometricFields only
613 template<class Type, template<class> class PatchField, class GeoMesh>
614 void readField
615 (
616  const IOobject& io,
617  const fvMesh& mesh,
618  const label i,
620 )
621 {
622  fields.set
623  (
624  i,
626  );
627 }
628 
629 
630 // Read vol or surface fields
631 template<class GeoField>
632 void readFields
633 (
634  const boolList& haveMesh,
635  const fvMesh& mesh,
636  const autoPtr<fvMeshSubset>& subsetterPtr,
637  IOobjectList& allObjects,
639 )
640 {
641  // Get my objects of type
642  IOobjectList objects(allObjects.lookupClass(GeoField::typeName));
643 
644  // Check that we all have all objects
645  wordList objectNames = objects.sortedNames();
646 
647  // Get master names
648  wordList masterNames(objectNames);
649  Pstream::scatter(masterNames);
650 
651  if (haveMesh[Pstream::myProcNo()] && objectNames != masterNames)
652  {
654  << "Objects not synchronised across processors." << nl
655  << "Master has " << flatOutput(masterNames) << nl
656  << "Processor " << Pstream::myProcNo()
657  << " has " << flatOutput(objectNames)
658  << exit(FatalError);
659  }
660 
661  fields.setSize(masterNames.size());
662 
663  // Have master send all fields to processors that don't have a mesh
664  if (Pstream::master())
665  {
666  forAll(masterNames, i)
667  {
668  const word& name = masterNames[i];
669  IOobject& io = *objects[name];
671 
672  // Load field (but not oldTime)
673  readField(io, mesh, i, fields);
674  // Create zero sized field and send
675  if (subsetterPtr.valid())
676  {
677  tmp<GeoField> tsubfld = subsetterPtr().interpolate(fields[i]);
678 
679  // Send to all processors that don't have a mesh
680  for (label procI = 1; procI < Pstream::nProcs(); ++procI)
681  {
682  if (!haveMesh[procI])
683  {
685  toProc<< tsubfld();
686  }
687  }
688  }
689  }
690  }
691  else if (!haveMesh[Pstream::myProcNo()])
692  {
693  // Don't have mesh (nor fields). Receive empty field from master.
694 
695  forAll(masterNames, i)
696  {
697  const word& name = masterNames[i];
698 
699  // Receive field
700  IPstream fromMaster
701  (
704  );
705  dictionary fieldDict(fromMaster);
706 
707  fields.set
708  (
709  i,
710  new GeoField
711  (
712  IOobject
713  (
714  name,
715  mesh.time().timeName(),
716  mesh,
719  ),
720  mesh,
721  fieldDict
722  )
723  );
724 
726  //fields[i].write();
727  }
728  }
729  else
730  {
731  // Have mesh so just try to load
732  forAll(masterNames, i)
733  {
734  const word& name = masterNames[i];
735  IOobject& io = *objects[name];
737 
738  // Load field (but not oldtime)
739  readField(io, mesh, i, fields);
740  }
741  }
742 }
743 
744 
745 // Variant of GeometricField::correctBoundaryConditions that only
746 // evaluates selected patch fields
747 template<class GeoField, class CoupledPatchType>
748 void correctCoupledBoundaryConditions(fvMesh& mesh)
749 {
751  (
752  mesh.objectRegistry::lookupClass<GeoField>()
753  );
754 
755  forAllIters(flds, iter)
756  {
757  GeoField& fld = *iter();
758 
759  typename GeoField::Boundary& bfld = fld.boundaryFieldRef();
760  if
761  (
764  )
765  {
766  const label nReq = Pstream::nRequests();
767 
768  forAll(bfld, patchi)
769  {
770  auto& pfld = bfld[patchi];
771  const auto& fvp = mesh.boundary()[patchi];
772 
773  if (fvp.coupled() && !isA<cyclicACMIFvPatch>(fvp))
774  {
775  pfld.initEvaluate(Pstream::defaultCommsType);
776  }
777  }
778 
779  // Block for any outstanding requests
780  if
781  (
784  )
785  {
786  Pstream::waitRequests(nReq);
787  }
788 
789  for (auto& pfld : bfld)
790  {
791  if (pfld.patch().coupled())
792  {
793  pfld.evaluate(Pstream::defaultCommsType);
794  }
795  }
796  }
798  {
799  const lduSchedule& patchSchedule =
800  fld.mesh().globalData().patchSchedule();
801 
802  forAll(patchSchedule, patchEvali)
803  {
804  const label patchi = patchSchedule[patchEvali].patch;
805  const auto& fvp = mesh.boundary()[patchi];
806  auto& pfld = bfld[patchi];
807 
808  if (fvp.coupled() && !isA<cyclicACMIFvPatch>(fvp))
809  {
810  if (patchSchedule[patchEvali].init)
811  {
812  pfld.initEvaluate(Pstream::commsTypes::scheduled);
813  }
814  else
815  {
816  pfld.evaluate(Pstream::commsTypes::scheduled);
817  }
818  }
819  }
820  }
821  else
822  {
824  << "Unsupported communications type "
826  << exit(FatalError);
827  }
828  }
829 }
830 
831 
832 // Inplace redistribute mesh and any fields
833 autoPtr<mapDistributePolyMesh> redistributeAndWrite
834 (
835  const Time& baseRunTime,
836  const scalar tolDim,
837  const boolList& haveMesh,
838  const fileName& meshSubDir,
839  const bool doReadFields,
840  const bool decompose, // decompose, i.e. read from undecomposed case
841  const bool reconstruct,
842  const bool overwrite,
843  const fileName& proc0CaseName,
844  const label nDestProcs,
845  const labelList& decomp,
846  const fileName& masterInstDir,
847  fvMesh& mesh
848 )
849 {
850  Time& runTime = const_cast<Time&>(mesh.time());
851 
853  //Info<< "Before distribution:" << endl;
854  //printMeshData(mesh);
855 
856 
857  PtrList<volScalarField> volScalarFields;
858  PtrList<volVectorField> volVectorFields;
859  PtrList<volSphericalTensorField> volSphereTensorFields;
860  PtrList<volSymmTensorField> volSymmTensorFields;
861  PtrList<volTensorField> volTensorFields;
862 
863  PtrList<surfaceScalarField> surfScalarFields;
864  PtrList<surfaceVectorField> surfVectorFields;
865  PtrList<surfaceSphericalTensorField> surfSphereTensorFields;
866  PtrList<surfaceSymmTensorField> surfSymmTensorFields;
867  PtrList<surfaceTensorField> surfTensorFields;
868 
874 
875  DynamicList<word> pointFieldNames;
876 
877 
878  if (doReadFields)
879  {
880  // Create 0 sized mesh to do all the generation of zero sized
881  // fields on processors that have zero sized meshes. Note that this is
882  // only necessary on master but since polyMesh construction with
883  // Pstream::parRun does parallel comms we have to do it on all
884  // processors
885  autoPtr<fvMeshSubset> subsetterPtr;
886 
887  const bool allHaveMesh = !haveMesh.found(false);
888  if (!allHaveMesh)
889  {
890  // Find last non-processor patch.
892 
893  const label nonProcI = (patches.nNonProcessor() - 1);
894 
895  if (nonProcI < 0)
896  {
898  << "Cannot find non-processor patch on processor "
899  << Pstream::myProcNo() << nl
900  << " Current patches:" << patches.names()
901  << abort(FatalError);
902  }
903 
904  // Subset 0 cells, no parallel comms.
905  // This is used to create zero-sized fields.
906  subsetterPtr.reset
907  (
908  new fvMeshSubset(mesh, bitSet(), nonProcI, false)
909  );
910  }
911 
912 
913  // Get original objects (before incrementing time!)
914  if (Pstream::master() && decompose)
915  {
916  runTime.caseName() = baseRunTime.caseName();
917  }
918  IOobjectList objects(mesh, runTime.timeName());
919  if (Pstream::master() && decompose)
920  {
921  runTime.caseName() = proc0CaseName;
922  }
923 
924  Info<< "From time " << runTime.timeName()
925  << " have objects:" << objects.names() << endl;
926 
927  // We don't want to map the decomposition (mapping already tested when
928  // mapping the cell centre field)
929  auto iter = objects.find("cellDist");
930  if (iter.found())
931  {
932  objects.erase(iter);
933  }
934 
935 
936  // volFields
937 
938  if (Pstream::master() && decompose)
939  {
940  runTime.caseName() = baseRunTime.caseName();
941  }
942  readFields
943  (
944  haveMesh,
945  mesh,
946  subsetterPtr,
947  objects,
948  volScalarFields
949  );
950 
951  readFields
952  (
953  haveMesh,
954  mesh,
955  subsetterPtr,
956  objects,
957  volVectorFields
958  );
959 
960  readFields
961  (
962  haveMesh,
963  mesh,
964  subsetterPtr,
965  objects,
966  volSphereTensorFields
967  );
968 
969  readFields
970  (
971  haveMesh,
972  mesh,
973  subsetterPtr,
974  objects,
975  volSymmTensorFields
976  );
977 
978  readFields
979  (
980  haveMesh,
981  mesh,
982  subsetterPtr,
983  objects,
984  volTensorFields
985  );
986 
987 
988  // surfaceFields
989 
990  readFields
991  (
992  haveMesh,
993  mesh,
994  subsetterPtr,
995  objects,
996  surfScalarFields
997  );
998 
999  readFields
1000  (
1001  haveMesh,
1002  mesh,
1003  subsetterPtr,
1004  objects,
1005  surfVectorFields
1006  );
1007 
1008  readFields
1009  (
1010  haveMesh,
1011  mesh,
1012  subsetterPtr,
1013  objects,
1014  surfSphereTensorFields
1015  );
1016 
1017  readFields
1018  (
1019  haveMesh,
1020  mesh,
1021  subsetterPtr,
1022  objects,
1023  surfSymmTensorFields
1024  );
1025 
1026  readFields
1027  (
1028  haveMesh,
1029  mesh,
1030  subsetterPtr,
1031  objects,
1032  surfTensorFields
1033  );
1034 
1035 
1036  // Dimensioned internal fields
1037  readFields
1038  (
1039  haveMesh,
1040  mesh,
1041  subsetterPtr,
1042  objects,
1043  dimScalarFields
1044  );
1045 
1046  readFields
1047  (
1048  haveMesh,
1049  mesh,
1050  subsetterPtr,
1051  objects,
1052  dimVectorFields
1053  );
1054 
1055  readFields
1056  (
1057  haveMesh,
1058  mesh,
1059  subsetterPtr,
1060  objects,
1061  dimSphereTensorFields
1062  );
1063 
1064  readFields
1065  (
1066  haveMesh,
1067  mesh,
1068  subsetterPtr,
1069  objects,
1070  dimSymmTensorFields
1071  );
1072 
1073  readFields
1074  (
1075  haveMesh,
1076  mesh,
1077  subsetterPtr,
1078  objects,
1079  dimTensorFields
1080  );
1081 
1082 
1083  // pointFields currently not supported. Read their names so we
1084  // can delete them.
1085  {
1086  // Get my objects of type
1087  pointFieldNames.append
1088  (
1089  objects.lookupClass(pointScalarField::typeName).sortedNames()
1090  );
1091  pointFieldNames.append
1092  (
1093  objects.lookupClass(pointVectorField::typeName).sortedNames()
1094  );
1095  pointFieldNames.append
1096  (
1097  objects.lookupClass
1098  (
1099  pointSphericalTensorField::typeName
1100  ).sortedNames()
1101  );
1102  pointFieldNames.append
1103  (
1104  objects.lookupClass
1105  (
1106  pointSymmTensorField::typeName
1107  ).sortedNames()
1108  );
1109  pointFieldNames.append
1110  (
1111  objects.lookupClass(pointTensorField::typeName).sortedNames()
1112  );
1113 
1114  // Make sure all processors have the same set
1115  Pstream::scatter(pointFieldNames);
1116  }
1117 
1118  if (Pstream::master() && decompose)
1119  {
1120  runTime.caseName() = proc0CaseName;
1121  }
1122  }
1123 
1124 
1125  // Mesh distribution engine
1126  fvMeshDistribute distributor(mesh, tolDim);
1127 
1128  // Do all the distribution of mesh and fields
1129  autoPtr<mapDistributePolyMesh> rawMap = distributor.distribute(decomp);
1130 
1131  // Print some statistics
1132  Info<< "After distribution:" << endl;
1133  printMeshData(mesh);
1134 
1135  // Get other side of processor boundaries
1136  correctCoupledBoundaryConditions
1137  <
1140  >(mesh);
1141  correctCoupledBoundaryConditions
1142  <
1145  >(mesh);
1146  correctCoupledBoundaryConditions
1147  <
1150  >(mesh);
1151  correctCoupledBoundaryConditions
1152  <
1155  >(mesh);
1156  correctCoupledBoundaryConditions
1157  <
1160  >(mesh);
1161  // No update surface fields
1162 
1163 
1164  // Set the minimum write precision
1166 
1167 
1168  if (!overwrite)
1169  {
1170  ++runTime;
1172  }
1173  else
1174  {
1175  mesh.setInstance(masterInstDir);
1176  }
1177 
1178 
1180  (
1181  IOobject
1182  (
1183  "procAddressing",
1184  mesh.facesInstance(),
1186  mesh,
1189  )
1190  );
1191  map.transfer(rawMap());
1192 
1193 
1194  if (reconstruct)
1195  {
1196  if (Pstream::master())
1197  {
1198  Info<< "Setting caseName to " << baseRunTime.caseName()
1199  << " to write reconstructed mesh and fields." << endl;
1200  runTime.caseName() = baseRunTime.caseName();
1201 
1202  mesh.write();
1204  for (const word& fieldName : pointFieldNames)
1205  {
1206  IOobject io
1207  (
1208  fieldName,
1209  runTime.timeName(),
1210  mesh
1211  );
1212 
1213  const fileName fieldFile(io.objectPath());
1214  if (topoSet::debug) DebugVar(fieldFile);
1215  rm(fieldFile);
1216  }
1217 
1218  // Now we've written all. Reset caseName on master
1219  Info<< "Restoring caseName to " << proc0CaseName << endl;
1220  runTime.caseName() = proc0CaseName;
1221  }
1222  }
1223  else
1224  {
1225  mesh.write();
1227  for (const word& fieldName : pointFieldNames)
1228  {
1229  IOobject io
1230  (
1231  fieldName,
1232  runTime.timeName(),
1233  mesh
1234  );
1235 
1236  const fileName fieldFile(io.objectPath());
1237  if (topoSet::debug) DebugVar(fieldFile);
1238  rm(fieldFile);
1239  }
1240  }
1241  Info<< "Written redistributed mesh to " << mesh.facesInstance() << nl
1242  << endl;
1243 
1244 
1245  if (decompose || reconstruct)
1246  {
1247  // Decompose (1 -> N) or reconstruct (N -> 1)
1248  // so {boundary,cell,face,point}ProcAddressing have meaning
1249  writeProcAddressing(mesh, map, decompose);
1250  }
1251  else
1252  {
1253  // Redistribute (N -> M)
1254  // {boundary,cell,face,point}ProcAddressing would be incorrect
1255  // - can either remove or redistribute previous
1256  removeProcAddressing(mesh);
1257  }
1258 
1259 
1260  // Refinement data
1261  {
1262 
1263  // Read refinement data
1264  if (Pstream::master() && decompose)
1265  {
1266  runTime.caseName() = baseRunTime.caseName();
1267  }
1268  IOobject io
1269  (
1270  "dummy",
1271  mesh.facesInstance(),
1273  mesh,
1276  false
1277  );
1278 
1279  hexRef8Data refData(io);
1280  if (Pstream::master() && decompose)
1281  {
1282  runTime.caseName() = proc0CaseName;
1283  }
1284 
1285  // Make sure all processors have valid data (since only some will
1286  // read)
1287  refData.sync(io);
1288 
1289  // Distribute
1290  refData.distribute(map);
1291 
1292 
1293  // Now we've read refinement data we can remove it
1295 
1296  if (reconstruct)
1297  {
1298  if (Pstream::master())
1299  {
1300  Info<< "Setting caseName to " << baseRunTime.caseName()
1301  << " to write reconstructed refinement data." << endl;
1302  runTime.caseName() = baseRunTime.caseName();
1303 
1304  refData.write();
1305 
1306  // Now we've written all. Reset caseName on master
1307  Info<< "Restoring caseName to " << proc0CaseName << endl;
1308  runTime.caseName() = proc0CaseName;
1309  }
1310  }
1311  else
1312  {
1313  refData.write();
1314  }
1315  }
1316 
1318  //{
1319  // // Read sets
1320  // if (Pstream::master() && decompose)
1321  // {
1322  // runTime.caseName() = baseRunTime.caseName();
1323  // }
1324  // IOobjectList objects(mesh, mesh.facesInstance(), "polyMesh/sets");
1325  //
1326  // PtrList<cellSet> cellSets;
1327  // ReadFields(objects, cellSets);
1328  //
1329  // if (Pstream::master() && decompose)
1330  // {
1331  // runTime.caseName() = proc0CaseName;
1332  // }
1333  //
1334  // forAll(cellSets, i)
1335  // {
1336  // cellSets[i].distribute(map);
1337  // }
1338  //
1339  // if (reconstruct)
1340  // {
1341  // if (Pstream::master())
1342  // {
1343  // Info<< "Setting caseName to " << baseRunTime.caseName()
1344  // << " to write reconstructed refinement data." << endl;
1345  // runTime.caseName() = baseRunTime.caseName();
1346  //
1347  // forAll(cellSets, i)
1348  // {
1349  // cellSets[i].distribute(map);
1350  // }
1351  //
1352  // // Now we've written all. Reset caseName on master
1353  // Info<< "Restoring caseName to " << proc0CaseName << endl;
1354  // runTime.caseName() = proc0CaseName;
1355  // }
1356  // }
1357  // else
1358  // {
1359  // forAll(cellSets, i)
1360  // {
1361  // cellSets[i].distribute(map);
1362  // }
1363  // }
1364  //}
1365 
1366 
1367  return autoPtr<mapDistributePolyMesh>::New(std::move(map));
1368 }
1369 
1370 
1371 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1372 //
1373 // Field Mapping
1374 //
1375 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1376 
1377 autoPtr<mapDistributePolyMesh> createReconstructMap
1378 (
1379  const autoPtr<fvMesh>& baseMeshPtr,
1380  const fvMesh& mesh,
1381  const labelList& cellProcAddressing,
1383  const labelList& pointProcAddressing,
1384  const labelList& boundaryProcAddressing
1385 )
1386 {
1387  // Send addressing to master
1388  labelListList cellAddressing(Pstream::nProcs());
1389  cellAddressing[Pstream::myProcNo()] = cellProcAddressing;
1390  Pstream::gatherList(cellAddressing);
1391 
1392  labelListList faceAddressing(Pstream::nProcs());
1393  faceAddressing[Pstream::myProcNo()] = faceProcAddressing;
1394  Pstream::gatherList(faceAddressing);
1395 
1396  labelListList pointAddressing(Pstream::nProcs());
1397  pointAddressing[Pstream::myProcNo()] = pointProcAddressing;
1398  Pstream::gatherList(pointAddressing);
1399 
1400  labelListList boundaryAddressing(Pstream::nProcs());
1401  {
1402  // Remove -1 entries
1403  DynamicList<label> patchProcAddressing(boundaryProcAddressing.size());
1404  forAll(boundaryProcAddressing, i)
1405  {
1406  if (boundaryProcAddressing[i] != -1)
1407  {
1408  patchProcAddressing.append(boundaryProcAddressing[i]);
1409  }
1410  }
1411  boundaryAddressing[Pstream::myProcNo()] = patchProcAddressing;
1412  Pstream::gatherList(boundaryAddressing);
1413  }
1414 
1415 
1417 
1418  if (baseMeshPtr.valid() && baseMeshPtr().nCells())
1419  {
1420  const fvMesh& baseMesh = baseMeshPtr();
1421 
1422  labelListList cellSubMap(Pstream::nProcs());
1423  cellSubMap[Pstream::masterNo()] = identity(mesh.nCells());
1424 
1425  mapDistribute cellMap
1426  (
1427  baseMesh.nCells(),
1428  std::move(cellSubMap),
1429  std::move(cellAddressing)
1430  );
1431 
1432  labelListList faceSubMap(Pstream::nProcs());
1433  faceSubMap[Pstream::masterNo()] = identity(mesh.nFaces());
1434 
1436  (
1437  baseMesh.nFaces(),
1438  std::move(faceSubMap),
1439  std::move(faceAddressing),
1440  false, //subHasFlip
1441  true //constructHasFlip
1442  );
1443 
1444  labelListList pointSubMap(Pstream::nProcs());
1445  pointSubMap[Pstream::masterNo()] = identity(mesh.nPoints());
1446 
1447  mapDistribute pointMap
1448  (
1449  baseMesh.nPoints(),
1450  std::move(pointSubMap),
1451  std::move(pointAddressing)
1452  );
1453 
1454  labelListList patchSubMap(Pstream::nProcs());
1455  // Send (filtered) patches to master
1456  patchSubMap[Pstream::masterNo()] =
1457  boundaryAddressing[Pstream::myProcNo()];
1458 
1459  mapDistribute patchMap
1460  (
1461  baseMesh.boundaryMesh().size(),
1462  std::move(patchSubMap),
1463  std::move(boundaryAddressing)
1464  );
1465 
1466  const label nOldPoints = mesh.nPoints();
1467  const label nOldFaces = mesh.nFaces();
1468  const label nOldCells = mesh.nCells();
1469 
1470  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
1471  labelList oldPatchStarts(pbm.size());
1472  labelList oldPatchNMeshPoints(pbm.size());
1473  forAll(pbm, patchI)
1474  {
1475  oldPatchStarts[patchI] = pbm[patchI].start();
1476  oldPatchNMeshPoints[patchI] = pbm[patchI].nPoints();
1477  }
1478 
1479  mapPtr.reset
1480  (
1482  (
1483  nOldPoints,
1484  nOldFaces,
1485  nOldCells,
1486  std::move(oldPatchStarts),
1487  std::move(oldPatchNMeshPoints),
1488  std::move(pointMap),
1489  std::move(faceMap),
1490  std::move(cellMap),
1491  std::move(patchMap)
1492  )
1493  );
1494  }
1495  else
1496  {
1497  labelListList cellSubMap(Pstream::nProcs());
1498  cellSubMap[Pstream::masterNo()] = identity(mesh.nCells());
1499  labelListList cellConstructMap(Pstream::nProcs());
1500 
1501  mapDistribute cellMap
1502  (
1503  0,
1504  std::move(cellSubMap),
1505  std::move(cellConstructMap)
1506  );
1507 
1508  labelListList faceSubMap(Pstream::nProcs());
1509  faceSubMap[Pstream::masterNo()] = identity(mesh.nFaces());
1510  labelListList faceConstructMap(Pstream::nProcs());
1511 
1513  (
1514  0,
1515  std::move(faceSubMap),
1516  std::move(faceConstructMap),
1517  false, //subHasFlip
1518  true //constructHasFlip
1519  );
1520 
1521  labelListList pointSubMap(Pstream::nProcs());
1522  pointSubMap[Pstream::masterNo()] = identity(mesh.nPoints());
1523  labelListList pointConstructMap(Pstream::nProcs());
1524 
1525  mapDistribute pointMap
1526  (
1527  0,
1528  std::move(pointSubMap),
1529  std::move(pointConstructMap)
1530  );
1531 
1532  labelListList patchSubMap(Pstream::nProcs());
1533  // Send (filtered) patches to master
1534  patchSubMap[Pstream::masterNo()] =
1535  boundaryAddressing[Pstream::myProcNo()];
1536  labelListList patchConstructMap(Pstream::nProcs());
1537 
1538  mapDistribute patchMap
1539  (
1540  0,
1541  std::move(patchSubMap),
1542  std::move(patchConstructMap)
1543  );
1544 
1545  const label nOldPoints = mesh.nPoints();
1546  const label nOldFaces = mesh.nFaces();
1547  const label nOldCells = mesh.nCells();
1548 
1549  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
1550  labelList oldPatchStarts(pbm.size());
1551  labelList oldPatchNMeshPoints(pbm.size());
1552  forAll(pbm, patchI)
1553  {
1554  oldPatchStarts[patchI] = pbm[patchI].start();
1555  oldPatchNMeshPoints[patchI] = pbm[patchI].nPoints();
1556  }
1557 
1558  mapPtr.reset
1559  (
1561  (
1562  nOldPoints,
1563  nOldFaces,
1564  nOldCells,
1565  std::move(oldPatchStarts),
1566  std::move(oldPatchNMeshPoints),
1567  std::move(pointMap),
1568  std::move(faceMap),
1569  std::move(cellMap),
1570  std::move(patchMap)
1571  )
1572  );
1573  }
1574 
1575  return mapPtr;
1576 }
1577 
1578 
1579 void readProcAddressing
1580 (
1581  const fvMesh& mesh,
1582  const autoPtr<fvMesh>& baseMeshPtr,
1584 )
1585 {
1586  //IOobject io
1587  //(
1588  // "procAddressing",
1589  // mesh.facesInstance(),
1590  // polyMesh::meshSubDir,
1591  // mesh,
1592  // IOobject::MUST_READ
1593  //);
1594  //if (io.typeHeaderOk<labelIOList>(true))
1595  //{
1596  // Pout<< "Reading addressing from " << io.name() << " at "
1597  // << mesh.facesInstance() << nl << endl;
1598  // distMap.reset(new IOmapDistributePolyMesh(io));
1599  //}
1600  //else
1601  {
1602  Info<< "Reading addressing from procXXXAddressing at "
1603  << mesh.facesInstance() << nl << endl;
1604  labelIOList cellProcAddressing
1605  (
1606  IOobject
1607  (
1608  "cellProcAddressing",
1609  mesh.facesInstance(),
1611  mesh,
1613  ),
1614  labelList()
1615  );
1617  (
1618  IOobject
1619  (
1620  "faceProcAddressing",
1621  mesh.facesInstance(),
1623  mesh,
1625  ),
1626  labelList()
1627  );
1628  labelIOList pointProcAddressing
1629  (
1630  IOobject
1631  (
1632  "pointProcAddressing",
1633  mesh.facesInstance(),
1635  mesh,
1637  ),
1638  labelList()
1639  );
1640  labelIOList boundaryProcAddressing
1641  (
1642  IOobject
1643  (
1644  "boundaryProcAddressing",
1645  mesh.facesInstance(),
1647  mesh,
1649  ),
1650  labelList()
1651  );
1652 
1653 
1654  if
1655  (
1656  mesh.nCells() != cellProcAddressing.size()
1657  || mesh.nPoints() != pointProcAddressing.size()
1658  || mesh.nFaces() != faceProcAddressing.size()
1659  || mesh.boundaryMesh().size() != boundaryProcAddressing.size()
1660  )
1661  {
1663  << "Read addressing inconsistent with mesh sizes" << nl
1664  << "cells:" << mesh.nCells()
1665  << " addressing:" << cellProcAddressing.objectPath()
1666  << " size:" << cellProcAddressing.size() << nl
1667  << "faces:" << mesh.nFaces()
1668  << " addressing:" << faceProcAddressing.objectPath()
1669  << " size:" << faceProcAddressing.size() << nl
1670  << "points:" << mesh.nPoints()
1671  << " addressing:" << pointProcAddressing.objectPath()
1672  << " size:" << pointProcAddressing.size()
1673  << "patches:" << mesh.boundaryMesh().size()
1674  << " addressing:" << boundaryProcAddressing.objectPath()
1675  << " size:" << boundaryProcAddressing.size()
1676  << exit(FatalError);
1677  }
1678 
1679  distMap.clear();
1680  distMap = createReconstructMap
1681  (
1682  baseMeshPtr,
1683  mesh,
1684  cellProcAddressing,
1686  pointProcAddressing,
1687  boundaryProcAddressing
1688  );
1689  }
1690 }
1691 
1692 
1693 void reconstructMeshFields
1694 (
1695  const parFvFieldReconstructor& fvReconstructor,
1696  const IOobjectList& objects,
1697  const wordRes& selectedFields
1698 )
1699 {
1700  // Dimensioned fields
1701 
1702  fvReconstructor.reconstructFvVolumeInternalFields<scalar>
1703  (
1704  objects,
1705  selectedFields
1706  );
1707  fvReconstructor.reconstructFvVolumeInternalFields<vector>
1708  (
1709  objects,
1710  selectedFields
1711  );
1713  (
1714  objects,
1715  selectedFields
1716  );
1718  (
1719  objects,
1720  selectedFields
1721  );
1722  fvReconstructor.reconstructFvVolumeInternalFields<tensor>
1723  (
1724  objects,
1725  selectedFields
1726  );
1727 
1728 
1729  // volFields
1730 
1731  fvReconstructor.reconstructFvVolumeFields<scalar>
1732  (
1733  objects,
1734  selectedFields
1735  );
1736  fvReconstructor.reconstructFvVolumeFields<vector>
1737  (
1738  objects,
1739  selectedFields
1740  );
1742  (
1743  objects,
1744  selectedFields
1745  );
1746  fvReconstructor.reconstructFvVolumeFields<symmTensor>
1747  (
1748  objects,
1749  selectedFields
1750  );
1751  fvReconstructor.reconstructFvVolumeFields<tensor>
1752  (
1753  objects,
1754  selectedFields
1755  );
1756 
1757 
1758  // surfaceFields
1759 
1760  fvReconstructor.reconstructFvSurfaceFields<scalar>
1761  (
1762  objects,
1763  selectedFields
1764  );
1765  fvReconstructor.reconstructFvSurfaceFields<vector>
1766  (
1767  objects,
1768  selectedFields
1769  );
1771  (
1772  objects,
1773  selectedFields
1774  );
1775  fvReconstructor.reconstructFvSurfaceFields<symmTensor>
1776  (
1777  objects,
1778  selectedFields
1779  );
1780  fvReconstructor.reconstructFvSurfaceFields<tensor>
1781  (
1782  objects,
1783  selectedFields
1784  );
1785 }
1786 
1787 
1788 void reconstructLagrangian
1789 (
1790  autoPtr<parLagrangianRedistributor>& lagrangianReconstructorPtr,
1791  const fvMesh& baseMesh,
1792  const fvMesh& mesh,
1793  const mapDistributePolyMesh& distMap,
1794  const wordRes& selectedLagrangianFields
1795 )
1796 {
1797  // Clouds (note: might not be present on all processors)
1798 
1800  List<wordList> fieldNames;
1801  // Find all cloudNames on all processors
1803 
1804  if (cloudNames.size())
1805  {
1806  if (!lagrangianReconstructorPtr.valid())
1807  {
1808  lagrangianReconstructorPtr.reset
1809  (
1811  (
1812  mesh,
1813  baseMesh,
1814  mesh.nCells(), // range of cell indices in clouds
1815  distMap
1816  )
1817  );
1818  }
1820  *lagrangianReconstructorPtr;
1821 
1822  for (const word& cloudName : cloudNames)
1823  {
1824  Info<< "Reconstructing lagrangian fields for cloud "
1825  << cloudName << nl << endl;
1826 
1827  autoPtr<mapDistributeBase> lagrangianMapPtr =
1828  lagrangianReconstructor.redistributeLagrangianPositions
1829  (
1830  cloudName
1831  );
1832 
1833  const mapDistributeBase& lagrangianMap = *lagrangianMapPtr;
1834 
1835  IOobjectList cloudObjs
1836  (
1837  mesh,
1838  mesh.time().timeName(),
1840  );
1841 
1842  lagrangianReconstructor.redistributeFields<label>
1843  (
1844  lagrangianMap,
1845  cloudName,
1846  cloudObjs,
1847  selectedLagrangianFields
1848  );
1849  lagrangianReconstructor.redistributeFieldFields<label>
1850  (
1851  lagrangianMap,
1852  cloudName,
1853  cloudObjs,
1854  selectedLagrangianFields
1855  );
1856  lagrangianReconstructor.redistributeFields<scalar>
1857  (
1858  lagrangianMap,
1859  cloudName,
1860  cloudObjs,
1861  selectedLagrangianFields
1862  );
1863  lagrangianReconstructor.redistributeFieldFields<scalar>
1864  (
1865  lagrangianMap,
1866  cloudName,
1867  cloudObjs,
1868  selectedLagrangianFields
1869  );
1870  lagrangianReconstructor.redistributeFields<vector>
1871  (
1872  lagrangianMap,
1873  cloudName,
1874  cloudObjs,
1875  selectedLagrangianFields
1876  );
1877  lagrangianReconstructor.redistributeFieldFields<vector>
1878  (
1879  lagrangianMap,
1880  cloudName,
1881  cloudObjs,
1882  selectedLagrangianFields
1883  );
1884  lagrangianReconstructor.redistributeFields
1885  <sphericalTensor>
1886  (
1887  lagrangianMap,
1888  cloudName,
1889  cloudObjs,
1890  selectedLagrangianFields
1891  );
1892  lagrangianReconstructor.redistributeFieldFields
1893  <sphericalTensor>
1894  (
1895  lagrangianMap,
1896  cloudName,
1897  cloudObjs,
1898  selectedLagrangianFields
1899  );
1900  lagrangianReconstructor.redistributeFields<symmTensor>
1901  (
1902  lagrangianMap,
1903  cloudName,
1904  cloudObjs,
1905  selectedLagrangianFields
1906  );
1907  lagrangianReconstructor.redistributeFieldFields
1908  <symmTensor>
1909  (
1910  lagrangianMap,
1911  cloudName,
1912  cloudObjs,
1913  selectedLagrangianFields
1914  );
1915  lagrangianReconstructor.redistributeFields<tensor>
1916  (
1917  lagrangianMap,
1918  cloudName,
1919  cloudObjs,
1920  selectedLagrangianFields
1921  );
1922  lagrangianReconstructor.redistributeFieldFields<tensor>
1923  (
1924  lagrangianMap,
1925  cloudName,
1926  cloudObjs,
1927  selectedLagrangianFields
1928  );
1929  }
1930  }
1931 }
1932 
1933 
1934 // Read clouds (note: might not be present on all processors)
1935 void readLagrangian
1936 (
1937  const fvMesh& mesh,
1938  const wordList& cloudNames,
1939  const wordRes& selectedLagrangianFields,
1941 )
1942 {
1943  (void)mesh.tetBasePtIs();
1944 
1945  forAll(cloudNames, i)
1946  {
1947  //Pout<< "Loading cloud " << cloudNames[i] << endl;
1948  clouds.set
1949  (
1950  i,
1952  );
1953 
1954 
1955  //for (passivePositionParticle& p : clouds[i]))
1956  //{
1957  // Pout<< "Particle position:" << p.position()
1958  // << " cell:" << p.cell()
1959  // << " with cc:" << mesh.cellCentres()[p.cell()]
1960  // << endl;
1961  //}
1962 
1963 
1964  IOobjectList cloudObjs(clouds[i], clouds[i].time().timeName());
1965 
1966  //Pout<< "Found clould objects:" << cloudObjs.names() << endl;
1967 
1969  <IOField<label>>
1970  (
1971  clouds[i],
1972  cloudObjs,
1973  selectedLagrangianFields
1974  );
1977  (
1978  clouds[i],
1979  cloudObjs,
1980  selectedLagrangianFields
1981  );
1983  <CompactIOField<Field<label>, label>>
1984  (
1985  clouds[i],
1986  cloudObjs,
1987  selectedLagrangianFields
1988  );
1989 
1990 
1992  <IOField<scalar>>
1993  (
1994  clouds[i],
1995  cloudObjs,
1996  selectedLagrangianFields
1997  );
2000  (
2001  clouds[i],
2002  cloudObjs,
2003  selectedLagrangianFields
2004  );
2006  <CompactIOField<Field<scalar>, scalar>>
2007  (
2008  clouds[i],
2009  cloudObjs,
2010  selectedLagrangianFields
2011  );
2012 
2013 
2015  <IOField<vector>>
2016  (
2017  clouds[i],
2018  cloudObjs,
2019  selectedLagrangianFields
2020  );
2023  (
2024  clouds[i],
2025  cloudObjs,
2026  selectedLagrangianFields
2027  );
2030  (
2031  clouds[i],
2032  cloudObjs,
2033  selectedLagrangianFields
2034  );
2035 
2036 
2039  (
2040  clouds[i],
2041  cloudObjs,
2042  selectedLagrangianFields
2043  );
2046  (
2047  clouds[i],
2048  cloudObjs,
2049  selectedLagrangianFields
2050  );
2053  (
2054  clouds[i],
2055  cloudObjs,
2056  selectedLagrangianFields
2057  );
2058 
2059 
2062  (
2063  clouds[i],
2064  cloudObjs,
2065  selectedLagrangianFields
2066  );
2069  (
2070  clouds[i],
2071  cloudObjs,
2072  selectedLagrangianFields
2073  );
2076  (
2077  clouds[i],
2078  cloudObjs,
2079  selectedLagrangianFields
2080  );
2081 
2082 
2084  <IOField<tensor>>
2085  (
2086  clouds[i],
2087  cloudObjs,
2088  selectedLagrangianFields
2089  );
2092  (
2093  clouds[i],
2094  cloudObjs,
2095  selectedLagrangianFields
2096  );
2099  (
2100  clouds[i],
2101  cloudObjs,
2102  selectedLagrangianFields
2103  );
2104  }
2105 }
2106 
2107 
2108 void redistributeLagrangian
2109 (
2110  autoPtr<parLagrangianRedistributor>& lagrangianReconstructorPtr,
2111  const fvMesh& mesh,
2112  const label nOldCells,
2113  const mapDistributePolyMesh& distMap,
2115 )
2116 {
2117  if (clouds.size())
2118  {
2119  if (!lagrangianReconstructorPtr.valid())
2120  {
2121  lagrangianReconstructorPtr.reset
2122  (
2124  (
2125  mesh,
2126  mesh,
2127  nOldCells, // range of cell indices in clouds
2128  distMap
2129  )
2130  );
2131  }
2132  const parLagrangianRedistributor& distributor =
2133  lagrangianReconstructorPtr();
2134 
2135  forAll(clouds, i)
2136  {
2137  autoPtr<mapDistributeBase> lagrangianMapPtr =
2138  distributor.redistributeLagrangianPositions(clouds[i]);
2139  const mapDistributeBase& lagrangianMap = *lagrangianMapPtr;
2140 
2141  distributor.redistributeStoredFields
2142  <IOField<label>>
2143  (
2144  lagrangianMap,
2145  clouds[i]
2146  );
2147  distributor.redistributeStoredFields
2149  (
2150  lagrangianMap,
2151  clouds[i]
2152  );
2153  distributor.redistributeStoredFields
2154  <CompactIOField<Field<label>, label>>
2155  (
2156  lagrangianMap,
2157  clouds[i]
2158  );
2159 
2160 
2161  distributor.redistributeStoredFields
2162  <IOField<scalar>>
2163  (
2164  lagrangianMap,
2165  clouds[i]
2166  );
2167  distributor.redistributeStoredFields
2169  (
2170  lagrangianMap,
2171  clouds[i]
2172  );
2173  distributor.redistributeStoredFields
2174  <CompactIOField<Field<scalar>, scalar>>
2175  (
2176  lagrangianMap,
2177  clouds[i]
2178  );
2179 
2180 
2181  distributor.redistributeStoredFields
2182  <IOField<vector>>
2183  (
2184  lagrangianMap,
2185  clouds[i]
2186  );
2187  distributor.redistributeStoredFields
2189  (
2190  lagrangianMap,
2191  clouds[i]
2192  );
2193  distributor.redistributeStoredFields
2195  (
2196  lagrangianMap,
2197  clouds[i]
2198  );
2199 
2200 
2201  distributor.redistributeStoredFields
2203  (
2204  lagrangianMap,
2205  clouds[i]
2206  );
2207  distributor.redistributeStoredFields
2209  (
2210  lagrangianMap,
2211  clouds[i]
2212  );
2213  distributor.redistributeStoredFields
2215  (
2216  lagrangianMap,
2217  clouds[i]
2218  );
2219 
2220 
2221  distributor.redistributeStoredFields
2223  (
2224  lagrangianMap,
2225  clouds[i]
2226  );
2227  distributor.redistributeStoredFields
2229  (
2230  lagrangianMap,
2231  clouds[i]
2232  );
2233  distributor.redistributeStoredFields
2235  (
2236  lagrangianMap,
2237  clouds[i]
2238  );
2239 
2240 
2241  distributor.redistributeStoredFields
2242  <IOField<tensor>>
2243  (
2244  lagrangianMap,
2245  clouds[i]
2246  );
2247  distributor.redistributeStoredFields
2249  (
2250  lagrangianMap,
2251  clouds[i]
2252  );
2253  distributor.redistributeStoredFields
2255  (
2256  lagrangianMap,
2257  clouds[i]
2258  );
2259  }
2260  }
2261 }
2262 
2263 
2264 int main(int argc, char *argv[])
2265 {
2267  (
2268  "Redistribute decomposed mesh and fields according"
2269  " to the decomposeParDict settings.\n"
2270  "Optionally run in decompose/reconstruct mode"
2271  );
2272 
2273  argList::noFunctionObjects(); // Never use function objects
2274 
2275  // enable -constant ... if someone really wants it
2276  // enable -zeroTime to prevent accidentally trashing the initial fields
2277  timeSelector::addOptions(true, true);
2278  #include "addRegionOption.H"
2280  (
2281  "allRegions",
2282  "operate on all regions in regionProperties"
2283  );
2284  #include "addOverwriteOption.H"
2285  argList::addBoolOption("decompose", "Decompose case");
2286  argList::addBoolOption("reconstruct", "Reconstruct case");
2288  (
2289  "dry-run",
2290  "Test without writing the decomposition. "
2291  "Changes -cellDist to only write volScalarField."
2292  );
2294  (
2295  "mergeTol",
2296  "scalar",
2297  "The merge distance relative to the bounding box size (default 1e-6)"
2298  );
2300  (
2301  "cellDist",
2302  "Write cell distribution as a labelList - for use with 'manual' "
2303  "decomposition method or as a volScalarField for post-processing."
2304  );
2306  (
2307  "newTimes",
2308  "Only reconstruct new times (i.e. that do not exist already)"
2309  );
2310 
2311 
2312  // Handle arguments
2313  // ~~~~~~~~~~~~~~~~
2314  // (replacement for setRootCase that does not abort)
2315 
2316  argList args(argc, argv);
2317  #include "foamDlOpenLibs.H"
2318 
2319  const bool reconstruct = args.found("reconstruct");
2320  const bool writeCellDist = args.found("cellDist");
2321  const bool dryrun = args.found("dry-run");
2322  const bool newTimes = args.found("newTimes");
2323 
2324  bool decompose = args.found("decompose");
2325  bool overwrite = args.found("overwrite");
2326 
2328  {
2330  << "Detected floating point exception trapping (FOAM_SIGFPE)."
2331  << " This might give" << nl
2332  << " problems when mapping fields. Switch it off in case"
2333  << " of problems." << endl;
2334  }
2335 
2336 
2337  const wordRes selectedFields;
2338  const wordRes selectedLagrangianFields;
2339 
2340 
2341  if (decompose)
2342  {
2343  Info<< "Decomposing case (like decomposePar)" << nl << endl;
2344  if (reconstruct)
2345  {
2347  << "Cannot specify both -decompose and -reconstruct"
2348  << exit(FatalError);
2349  }
2350  }
2351  else if (reconstruct)
2352  {
2353  Info<< "Reconstructing case (like reconstructParMesh)" << nl << endl;
2354  }
2355 
2356 
2357  if (decompose || reconstruct)
2358  {
2359  if (!overwrite)
2360  {
2362  << "Working in decompose or reconstruction mode automatically"
2363  << " implies -overwrite" << nl << endl;
2364  overwrite = true;
2365  }
2366  }
2367 
2368 
2369  if (!Pstream::parRun())
2370  {
2372  << ": This utility can only be run parallel"
2373  << exit(FatalError);
2374  }
2375 
2376 
2377  if (!isDir(args.rootPath()))
2378  {
2380  << ": cannot open root directory " << args.rootPath()
2381  << exit(FatalError);
2382  }
2383 
2384  // Detect if running data-distributed (multiple roots)
2385  bool nfs = true;
2386  {
2387  List<fileName> roots(1, args.rootPath());
2389  nfs = (roots.size() == 1);
2390  }
2391 
2392  if (!nfs)
2393  {
2394  Info<< "Detected multiple roots i.e. non-nfs running"
2395  << nl << endl;
2396  }
2397 
2398  if (isDir(args.path()))
2399  {
2400  if (decompose)
2401  {
2402  Info<< "Removing existing processor directories" << endl;
2403  rmDir(args.path());
2404  }
2405  }
2406  else
2407  {
2408  // Directory does not exist. If this happens on master -> decompose mode
2409  decompose = true;
2410  Info<< "No processor directories; switching on decompose mode"
2411  << nl << endl;
2412  }
2413  // If master changed to decompose mode make sure all nodes know about it
2414  Pstream::scatter(decompose);
2415 
2416 
2417  // If running distributed we have problem of new processors not finding
2418  // a system/controlDict. However if we switch on the master-only reading
2419  // the problem becomes that the time directories are differing sizes and
2420  // e.g. latestTime will pick up a different time (which causes createTime.H
2421  // to abort). So for now make sure to have master times on all
2422  // processors
2423  {
2424  Info<< "Creating time directories on all processors" << nl << endl;
2425  instantList timeDirs;
2426  if (Pstream::master())
2427  {
2428  const bool oldParRun = Pstream::parRun();
2429  Pstream::parRun() = false;
2430  timeDirs = Time::findTimes(args.path(), "constant");
2431  Pstream::parRun() = oldParRun;
2432  }
2433  Pstream::scatter(timeDirs);
2434  for (const instant& t : timeDirs)
2435  {
2436  mkDir(args.path()/t.name());
2437  }
2438  }
2439 
2440 
2441  // Construct time
2442  // ~~~~~~~~~~~~~~
2443 
2444  #include "createTime.H"
2445  runTime.functionObjects().off(); // Extra safety?
2446 
2447 
2448  // Save local processor0 casename
2449  const fileName proc0CaseName = runTime.caseName();
2450 
2451 
2452  // Construct undecomposed Time
2453  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
2454  // This will read the same controlDict but might have a different
2455  // set of times so enforce same times
2456 
2457  if (!nfs)
2458  {
2459  Info<< "Creating time directories for undecomposed Time"
2460  << " on all processors" << nl << endl;
2461  instantList timeDirs;
2462 
2463  const fileName basePath(args.globalPath());
2464 
2465  if (Pstream::master())
2466  {
2467  const bool oldParRun = Pstream::parRun();
2468  Pstream::parRun() = false;
2469  timeDirs = Time::findTimes(basePath, "constant");
2470  Pstream::parRun() = oldParRun;
2471  }
2472  Pstream::scatter(timeDirs);
2473  for (const instant& t : timeDirs)
2474  {
2475  mkDir(basePath/t.name());
2476  }
2477  }
2478 
2479 
2480  Info<< "Create undecomposed database"<< nl << endl;
2481  Time baseRunTime
2482  (
2483  runTime.controlDict(),
2484  runTime.rootPath(),
2486  runTime.system(),
2487  runTime.constant(),
2488  false // enableFunctionObjects
2489  );
2490 
2491 
2492  wordHashSet masterTimeDirSet;
2493  if (newTimes)
2494  {
2495  instantList baseTimeDirs(baseRunTime.times());
2496  for (const instant& t : baseTimeDirs)
2497  {
2498  masterTimeDirSet.insert(t.name());
2499  }
2500  }
2501 
2502 
2503  // Allow override of decomposeParDict location
2504  const fileName decompDictFile =
2505  args.getOrDefault<fileName>("decomposeParDict", "");
2506 
2507  // Get all region names
2508  wordList regionNames;
2509  if (args.found("allRegions"))
2510  {
2511  regionNames = regionProperties(runTime).names();
2512 
2513  Info<< "Decomposing all regions in regionProperties" << nl
2514  << " " << flatOutput(regionNames) << nl << endl;
2515  }
2516  else
2517  {
2518  regionNames.resize(1);
2519  regionNames.first() =
2521  }
2522 
2523 
2524  // Demand driven lagrangian mapper
2525  autoPtr<parLagrangianRedistributor> lagrangianReconstructorPtr;
2526 
2527 
2528  if (reconstruct)
2529  {
2530  // use the times list from the master processor
2531  // and select a subset based on the command-line options
2533  Pstream::scatter(timeDirs);
2534 
2535  if (timeDirs.empty())
2536  {
2538  << "No times selected"
2539  << exit(FatalError);
2540  }
2541 
2542 
2543  // Pass1 : reconstruct mesh and addressing
2544  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2545 
2546 
2547  Info<< nl
2548  << "Pass1 : reconstructing mesh and addressing" << nl << endl;
2549 
2550 
2551  forAll(regionNames, regioni)
2552  {
2553  const word& regionName = regionNames[regioni];
2554  const fileName meshSubDir
2555  (
2558  : regionNames[regioni]/polyMesh::meshSubDir
2559  );
2560 
2561  Info<< "\n\nReconstructing mesh " << regionName << nl << endl;
2562 
2563  // Loop over all times
2564  forAll(timeDirs, timeI)
2565  {
2566  // Set time for global database
2567  runTime.setTime(timeDirs[timeI], timeI);
2568  baseRunTime.setTime(timeDirs[timeI], timeI);
2569 
2570  Info<< "Time = " << runTime.timeName() << endl << endl;
2571 
2572 
2573  // See where the mesh is
2574  fileName facesInstance = runTime.findInstance
2575  (
2576  meshSubDir,
2577  "faces",
2579  );
2580  //Pout<< "facesInstance:" << facesInstance << endl;
2581 
2582  Pstream::scatter(facesInstance);
2583 
2584  // Check who has a mesh
2585  const fileName meshPath =
2586  runTime.path()/facesInstance/meshSubDir/"faces";
2587 
2588  Info<< "Checking for mesh in " << meshPath << nl << endl;
2589 
2590  boolList haveMesh(Pstream::nProcs(), false);
2591  haveMesh[Pstream::myProcNo()] = isFile(meshPath);
2592  Pstream::gatherList(haveMesh);
2593  Pstream::scatterList(haveMesh);
2594  Info<< "Per processor mesh availability:" << nl
2595  << " " << flatOutput(haveMesh) << nl << endl;
2596 
2597 
2598  // Addressing back to reconstructed mesh as xxxProcAddressing.
2599  // - all processors have consistent faceProcAddressing
2600  // - processors with no mesh don't need faceProcAddressing
2601 
2602 
2603  // Note: filePath searches up on processors that don't have
2604  // processor if instance = constant so explicitly check
2605  // found filename.
2606  bool haveAddressing = false;
2607  if (haveMesh[Pstream::myProcNo()])
2608  {
2609  // Read faces (just to know their size)
2610  faceCompactIOList faces
2611  (
2612  IOobject
2613  (
2614  "faces",
2615  facesInstance,
2616  meshSubDir,
2617  runTime,
2619  )
2620  );
2621 
2622  // Check faceProcAddressing
2624  (
2625  IOobject
2626  (
2627  "faceProcAddressing",
2628  facesInstance,
2629  meshSubDir,
2630  runTime,
2632  ),
2633  labelList()
2634  );
2635  if
2636  (
2637  faceProcAddressing.headerOk()
2638  && faceProcAddressing.size() == faces.size()
2639  )
2640  {
2641  haveAddressing = true;
2642  }
2643  }
2644  else
2645  {
2646  // Have no mesh. Don't need addressing
2647  haveAddressing = true;
2648  }
2649 
2650  if (!returnReduce(haveAddressing, andOp<bool>()))
2651  {
2652  Info<< "loading mesh from " << facesInstance << endl;
2654  (
2655  IOobject
2656  (
2657  regionName,
2658  facesInstance,
2659  runTime,
2661  )
2662  );
2663  fvMesh& mesh = meshPtr();
2664 
2665  // Global matching tolerance
2666  const scalar tolDim = getMergeDistance
2667  (
2668  args,
2669  runTime,
2670  mesh.bounds()
2671  );
2672 
2673 
2674  // Determine decomposition
2675  // ~~~~~~~~~~~~~~~~~~~~~~~
2676 
2677  Info<< "Reconstructing mesh for time " << facesInstance
2678  << endl;
2679 
2680  label nDestProcs = 1;
2681  labelList finalDecomp = labelList(mesh.nCells(), Zero);
2682 
2683  redistributeAndWrite
2684  (
2685  baseRunTime,
2686  tolDim,
2687  haveMesh,
2688  meshSubDir,
2689  false, // do not read fields
2690  false, // do not read undecomposed case on proc0
2691  true, // write redistributed files to proc0
2692  overwrite,
2693  proc0CaseName,
2694  nDestProcs,
2695  finalDecomp,
2696  facesInstance,
2697  mesh
2698  );
2699  }
2700  }
2701 
2702 
2703  // Pass2 : read mesh and addressing and reconstruct fields
2704  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2705 
2706  Info<< nl
2707  << "Pass2 : reconstructing fields" << nl << endl;
2708 
2709  runTime.setTime(timeDirs[0], 0);
2710  baseRunTime.setTime(timeDirs[0], 0);
2711  Info<< "Time = " << runTime.timeName() << endl << endl;
2712 
2713 
2714  Info<< "Reading undecomposed mesh (on master)" << endl;
2716  (
2717  IOobject
2718  (
2719  regionName,
2720  baseRunTime.timeName(),
2721  baseRunTime,
2723  ),
2724  true // read on master only
2725  );
2726 
2727  Info<< "Reading local, decomposed mesh" << endl;
2729  (
2730  IOobject
2731  (
2732  regionName,
2733  baseMeshPtr().facesInstance(),
2734  runTime,
2736  )
2737  );
2738  fvMesh& mesh = meshPtr();
2739 
2740 
2741  // Read addressing back to base mesh
2743  readProcAddressing(mesh, baseMeshPtr, distMap);
2744 
2745  // Construct field mapper
2746  autoPtr<parFvFieldReconstructor> fvReconstructorPtr
2747  (
2749  (
2750  baseMeshPtr(),
2751  mesh,
2752  distMap(),
2753  Pstream::master() // do I need to write?
2754  )
2755  );
2756 
2757 
2758 
2759  // Since we start from Times[0] and not runTime.timeName() we
2760  // might overlook point motion in the first timestep
2761  // (since mesh.readUpdate() below will not be triggered). Instead
2762  // detect points by hand
2764  {
2765  Info<< " Detected initial mesh motion;"
2766  << " reconstructing points" << nl
2767  << endl;
2768  fvReconstructorPtr().reconstructPoints();
2769  }
2770 
2771 
2772  // Loop over all times
2773  forAll(timeDirs, timeI)
2774  {
2775  if (newTimes && masterTimeDirSet.found(timeDirs[timeI].name()))
2776  {
2777  Info<< "Skipping time " << timeDirs[timeI].name()
2778  << endl << endl;
2779  continue;
2780  }
2781 
2782  // Set time for global database
2783  runTime.setTime(timeDirs[timeI], timeI);
2784  baseRunTime.setTime(timeDirs[timeI], timeI);
2785 
2786  Info<< "Time = " << runTime.timeName() << endl << endl;
2787 
2788 
2789  // Check if any new meshes need to be read.
2791 
2792  if (procStat == fvMesh::POINTS_MOVED)
2793  {
2794  Info<< " Dected mesh motion; reconstructing points" << nl
2795  << endl;
2796  fvReconstructorPtr().reconstructPoints();
2797  }
2798  else if
2799  (
2800  procStat == fvMesh::TOPO_CHANGE
2801  || procStat == fvMesh::TOPO_PATCH_CHANGE
2802  )
2803  {
2804  Info<< " Detected topology change;"
2805  << " reconstructing addressing" << nl << endl;
2806 
2807  if (baseMeshPtr.valid())
2808  {
2809  // Cannot do a baseMesh::readUpdate() since not all
2810  // processors will have mesh files. So instead just
2811  // recreate baseMesh
2812  baseMeshPtr.clear();
2813  baseMeshPtr = fvMeshTools::newMesh
2814  (
2815  IOobject
2816  (
2817  regionName,
2818  baseRunTime.timeName(),
2819  baseRunTime,
2821  ),
2822  true // read on master only
2823  );
2824  }
2825 
2826  // Re-read procXXXaddressing
2827  readProcAddressing(mesh, baseMeshPtr, distMap);
2828 
2829  // Reset field mapper
2830  fvReconstructorPtr.reset
2831  (
2833  (
2834  baseMeshPtr(),
2835  mesh,
2836  distMap(),
2837  Pstream::master()
2838  )
2839  );
2840  lagrangianReconstructorPtr.clear();
2841  }
2842 
2843 
2844  // Get list of objects
2845  IOobjectList objects(mesh, runTime.timeName());
2846 
2847 
2848  // Mesh fields (vol, surface, volInternal)
2849  reconstructMeshFields
2850  (
2851  fvReconstructorPtr(),
2852  objects,
2853  selectedFields
2854  );
2855 
2856  // Clouds (note: might not be present on all processors)
2857  reconstructLagrangian
2858  (
2859  lagrangianReconstructorPtr,
2860  baseMeshPtr(),
2861  mesh,
2862  distMap(),
2863  selectedLagrangianFields
2864  );
2865 
2866  // If there are any "uniform" directories copy them from
2867  // the master processor
2868  if (Pstream::master())
2869  {
2870  fileName uniformDir0 = runTime.timePath()/"uniform";
2871  if (isDir(uniformDir0))
2872  {
2873  Info<< "Detected additional non-decomposed files in "
2874  << uniformDir0 << endl;
2875  cp(uniformDir0, baseRunTime.timePath());
2876  }
2877  }
2878  }
2879  }
2880  }
2881  else
2882  {
2883  // Time coming from processor0 (or undecomposed if no processor0)
2884  scalar masterTime;
2885  if (decompose)
2886  {
2887  // Use base time. This is to handle e.g. startTime = latestTime
2888  // which will not do anything if there are no processor directories
2889  masterTime = timeSelector::selectIfPresent
2890  (
2891  baseRunTime,
2892  args
2893  )[0].value();
2894  }
2895  else
2896  {
2897  masterTime = timeSelector::selectIfPresent
2898  (
2899  runTime,
2900  args
2901  )[0].value();
2902  }
2903  Pstream::scatter(masterTime);
2904  Info<< "Setting time to that of master or undecomposed case : "
2905  << masterTime << endl;
2906  runTime.setTime(masterTime, 0);
2907 
2908 
2909 
2910  forAll(regionNames, regioni)
2911  {
2912  const word& regionName = regionNames[regioni];
2913  const fileName meshSubDir
2914  (
2917  : regionNames[regioni]/polyMesh::meshSubDir
2918  );
2919 
2920  if (decompose)
2921  {
2922  Info<< "\n\nDecomposing mesh " << regionName << nl << endl;
2923  }
2924  else
2925  {
2926  Info<< "\n\nRedistributing mesh " << regionName << nl << endl;
2927  }
2928 
2929 
2930  // Get time instance directory
2931  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
2932  // At this point we should be able to read at least a mesh on
2933  // processor0. Note the changing of the processor0 casename to
2934  // enforce it to read/write from the undecomposed case
2935 
2936  fileName masterInstDir;
2937  if (Pstream::master())
2938  {
2939  if (decompose)
2940  {
2941  Info<< "Setting caseName to " << baseRunTime.caseName()
2942  << " to find undecomposed mesh" << endl;
2943  runTime.caseName() = baseRunTime.caseName();
2944  }
2945 
2946  masterInstDir = runTime.findInstance
2947  (
2948  meshSubDir,
2949  "faces",
2951  );
2952 
2953  if (decompose)
2954  {
2955  Info<< "Restoring caseName to " << proc0CaseName << endl;
2956  runTime.caseName() = proc0CaseName;
2957  }
2958  }
2959  Pstream::scatter(masterInstDir);
2960 
2961  // Check who has a mesh
2962  const fileName meshPath =
2963  runTime.path()/masterInstDir/meshSubDir/"faces";
2964 
2965  Info<< "Checking for mesh in " << meshPath << nl << endl;
2966 
2967 
2968  boolList haveMesh(Pstream::nProcs(), false);
2969  haveMesh[Pstream::myProcNo()] = isFile(meshPath);
2970  Pstream::gatherList(haveMesh);
2971  Pstream::scatterList(haveMesh);
2972  Info<< "Per processor mesh availability:" << nl
2973  << " " << flatOutput(haveMesh) << nl << endl;
2974 
2975  // Load mesh (or create dummy one)
2976  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2977 
2978  if (Pstream::master() && decompose)
2979  {
2980  Info<< "Setting caseName to " << baseRunTime.caseName()
2981  << " to read undecomposed mesh" << endl;
2982  runTime.caseName() = baseRunTime.caseName();
2983  }
2984 
2986  (
2987  IOobject
2988  (
2989  regionName,
2990  masterInstDir,
2991  runTime,
2993  )
2994  );
2995 
2996  if (Pstream::master() && decompose)
2997  {
2998  Info<< "Restoring caseName to " << proc0CaseName << endl;
2999  runTime.caseName() = proc0CaseName;
3000  }
3001 
3002  fvMesh& mesh = meshPtr();
3003 
3004 
3005  const label nOldCells = mesh.nCells();
3006  //Pout<< "Loaded mesh : nCells:" << nOldCells
3007  // << " nPatches:" << mesh.boundaryMesh().size() << endl;
3008 
3009 
3010  // Global matching tolerance
3011  const scalar tolDim = getMergeDistance
3012  (
3013  args,
3014  runTime,
3015  mesh.bounds()
3016  );
3017 
3018  // Determine decomposition
3019  // ~~~~~~~~~~~~~~~~~~~~~~~
3020 
3021  label nDestProcs;
3022  labelList finalDecomp;
3023  determineDecomposition
3024  (
3025  baseRunTime,
3026  decompDictFile,
3027  decompose,
3028  proc0CaseName,
3029  mesh,
3030  writeCellDist,
3031 
3032  nDestProcs,
3033  finalDecomp
3034  );
3035 
3036  if (dryrun)
3037  {
3038  if (!Pstream::master() && !haveMesh[Pstream::myProcNo()])
3039  {
3040  // Remove dummy mesh created by loadOrCreateMesh
3041  const bool oldParRun = Pstream::parRun();
3042  Pstream::parRun() = false;
3043  mesh.removeFiles();
3044  rmDir(mesh.objectRegistry::objectPath());
3045  Pstream::parRun() = oldParRun;
3046  }
3047  continue;
3048  }
3049 
3050 
3051 
3053  List<wordList> fieldNames;
3054 
3055  // Detect lagrangian fields
3056  if (Pstream::master() && decompose)
3057  {
3058  runTime.caseName() = baseRunTime.caseName();
3059  }
3061  (
3062  mesh,
3063  cloudNames,
3064  fieldNames
3065  );
3066 
3067  // Read lagrangian fields and store on cloud (objectRegistry)
3069  (
3070  cloudNames.size()
3071  );
3072  readLagrangian
3073  (
3074  mesh,
3075  cloudNames,
3076  selectedLagrangianFields,
3077  clouds
3078  );
3079  if (Pstream::master() && decompose)
3080  {
3081  runTime.caseName() = proc0CaseName;
3082  }
3083 
3084 
3085  // Load fields, do all distribution (mesh and fields - but not
3086  // lagrangian fields; these are done later)
3087  autoPtr<mapDistributePolyMesh> distMap = redistributeAndWrite
3088  (
3089  baseRunTime,
3090  tolDim,
3091  haveMesh,
3092  meshSubDir,
3093  true, // read fields
3094  decompose, // decompose, i.e. read from undecomposed case
3095  false, // no reconstruction
3096  overwrite,
3097  proc0CaseName,
3098  nDestProcs,
3099  finalDecomp,
3100  masterInstDir,
3101  mesh
3102  );
3103 
3104 
3105  // Redistribute any clouds
3106  redistributeLagrangian
3107  (
3108  lagrangianReconstructorPtr,
3109  mesh,
3110  nOldCells,
3111  distMap(),
3112  clouds
3113  );
3114 
3115 
3116  // Copy any uniform data
3117  const fileName uniformDir("uniform");
3118  if (isDir(baseRunTime.timePath()/uniformDir))
3119  {
3120  Info<< "Detected additional non-decomposed files in "
3121  << baseRunTime.timePath()/uniformDir << endl;
3122  cp
3123  (
3124  baseRunTime.timePath()/uniformDir,
3125  runTime.timePath()/uniformDir
3126  );
3127  }
3128  }
3129  }
3130 
3131 
3132  Info<< "End\n" << endl;
3133 
3134  return 0;
3135 }
3136 
3137 
3138 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::TimePaths::findTimes
static instantList findTimes(const fileName &directory, const word &constantName="constant")
Search a given directory for valid time directories.
Definition: TimePaths.C:140
Foam::IOobject::NO_WRITE
Definition: IOobject.H:130
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
Construct autoPtr of T with forwarding arguments.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:71
volFields.H
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::mapDistributeBase::subMap
const labelListList & subMap() const
From subsetted data back to original data.
Definition: mapDistributeBase.H:282
Foam::autoPtr::reset
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:109
Foam::fvc::reconstruct
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> reconstruct(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcReconstruct.C:56
Foam::cloud::prefix
static const word prefix
The prefix to local: lagrangian.
Definition: cloud.H:87
Foam::UPstream::commsTypes::blocking
Foam::parFvFieldReconstructor::reconstructFvVolumeInternalFields
label reconstructFvVolumeInternalFields(const IOobjectList &objects, const wordRes &selectedFields=wordRes()) const
Read, reconstruct and write all/selected volume internal fields.
Foam::TimePaths::globalCaseName
const fileName & globalCaseName() const
Return global case name.
Definition: TimePathsI.H:48
Foam::Tensor< scalar >
Foam::mapDistributeBase::constructHasFlip
bool constructHasFlip() const
Does constructMap include a sign.
Definition: mapDistributeBase.H:318
Foam::volTensorField
GeometricField< tensor, fvPatchField, volMesh > volTensorField
Definition: volFieldsFwd.H:64
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:104
faceProcAddressing
PtrList< labelIOList > & faceProcAddressing
Definition: checkFaceAddressingComp.H:9
Foam::SymmTensor< scalar >
meshPtr
Foam::autoPtr< Foam::fvMesh > meshPtr(nullptr)
Foam::UPstream::commsTypes::nonBlocking
Foam::IOobject::AUTO_WRITE
Definition: IOobject.H:129
Foam::boundBox::mag
scalar mag() const
The magnitude of the bounding box span.
Definition: boundBoxI.H:133
Foam::dimless
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Dimensionless.
Definition: dimensionSets.H:50
Foam::UPstream::masterNo
static constexpr int masterNo() noexcept
Process index of the master.
Definition: UPstream.H:433
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeTopological.C:94
cloudName
const word cloudName(propsDict.get< word >("cloud"))
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
regionProperties.H
Foam::parLagrangianRedistributor::redistributeStoredFields
label redistributeStoredFields(const mapDistributeBase &map, passivePositionParticleCloud &cloud) const
Redistribute and write stored lagrangian fields.
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::IOField
A primitive field of type <T> with automated input and output.
Definition: foamVtkLagrangianWriter.H:61
Foam::fvMesh::write
virtual bool write(const bool valid=true) const
Write mesh using IO settings from time.
Definition: fvMesh.C:895
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:64
processorFvPatchField.H
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:62
Foam::polyMesh::POINTS_MOVED
Definition: polyMesh.H:94
Foam::polyMesh::defaultRegion
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:312
Foam::argList::getOrDefault
T getOrDefault(const word &optName, const T &deflt) const
Get a value from the named option if present, or return default.
Definition: argListI.H:286
Foam::processorFvPatchField
This boundary condition enables processor communication across patches.
Definition: processorFvPatchField.H:66
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:59
Foam::fvMeshSubset
Given the original mesh and the list of selected cells, it creates the mesh consisting only of the de...
Definition: fvMeshSubset.H:73
topoSet.H
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::DynamicList< word >
Foam::globalMeshData::processorPatches
const labelList & processorPatches() const
Return list of processor patch labels.
Definition: globalMeshData.H:404
Foam::dictionary::found
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for an entry (const access) with the given keyword.
Definition: dictionary.C:364
unmappedPassivePositionParticleCloud.H
Foam::mapDistributeBase::distribute
static void distribute(const Pstream::commsTypes commsType, const List< labelPair > &schedule, const label constructSize, const labelListList &subMap, const bool subHasFlip, const labelListList &constructMap, const bool constructHasFlip, List< T > &, const negateOp &negOp, const int tag=UPstream::msgType())
Distribute data. Note:schedule only used for.
Definition: mapDistributeBaseTemplates.C:122
Foam::OPstream
Output inter-processor communications stream.
Definition: OPstream.H:52
Foam::Pstream::scatterList
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
Definition: gatherScatterList.C:215
Foam::Time::writeFormat
IOstream::streamFormat writeFormat() const
The write stream format.
Definition: Time.H:387
Foam::mapDistributePolyMesh::distributeCellData
void distributeCellData(List< T > &lst) const
Distribute list of cell data.
Definition: mapDistributePolyMesh.H:256
addOverwriteOption.H
Foam::primitiveMesh::nFaces
label nFaces() const
Number of mesh faces.
Definition: primitiveMeshI.H:90
globalIndex.H
IOmapDistributePolyMesh.H
Foam::UPstream::nProcs
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:427
Foam::fileName::name
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Definition: fileNameI.H:209
Foam::polyMesh::meshSubDir
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:315
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:415
Foam::regionProperties::names
wordList names() const
The region names. Sorted by region type.
Definition: regionProperties.C:89
Foam::Time::timeName
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:785
Foam::argList::addNote
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:413
Foam::Time::functionObjects
const functionObjectList & functionObjects() const
Return the list of function objects.
Definition: Time.H:499
Foam::timeSelector::select
instantList select(const instantList &times) const
Select a list of Time values that are within the ranges.
Definition: timeSelector.C:95
Foam::polyMesh::facesInstance
const fileName & facesInstance() const
Return the current instance directory for faces.
Definition: polyMesh.C:821
Foam::mapDistributePolyMesh::transfer
void transfer(mapDistributePolyMesh &map)
Transfer the contents of the argument and annul the argument.
Definition: mapDistributePolyMesh.C:193
Foam::UPstream::waitRequests
static void waitRequests(const label start=0)
Wait until all requests (from start onwards) have finished.
Definition: UPstream.C:234
Foam::combineReduce
void combineReduce(const List< UPstream::commsStruct > &comms, T &Value, const CombineOp &cop, const int tag, const label comm)
Definition: PstreamCombineReduceOps.H:54
Foam::processorPolyPatch::neighbProcNo
int neighbProcNo() const
Return neighbour processor number.
Definition: processorPolyPatch.H:274
Foam::Pstream::scatter
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Distribute without modification. Reverse of gather.
Definition: gatherScatter.C:150
Foam::argList
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:123
Foam::unmappedPassivePositionParticleCloud
passivePositionParticleCloud but with autoMap and writing disabled. Only used for its objectRegistry ...
Definition: unmappedPassivePositionParticleCloud.H:52
Foam::isFile
bool isFile(const fileName &name, const bool checkGzip=true, const bool followLink=true)
Does the name exist as a FILE in the file system?
Definition: MSwindows.C:658
Foam::rm
bool rm(const fileName &file)
Remove a file (or its gz equivalent), returning true if successful.
Definition: MSwindows.C:994
Foam::autoPtr::valid
bool valid() const noexcept
True if the managed pointer is non-null.
Definition: autoPtr.H:148
IOobjectList.H
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:435
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
surfaceFields.H
Foam::surfaceFields.
Foam::UPstream::defaultCommsType
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:273
Foam::CompactIOField
A Field of objects of type <T> with automated input and output using a compact storage....
Definition: CompactIOField.H:53
decompositionMethod.H
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:81
Foam::HashSet< word >
parLagrangianRedistributor.H
Foam::meshRefinement::removeFiles
static void removeFiles(const polyMesh &)
Helper: remove all relevant files from mesh instance.
Definition: meshRefinement.C:3416
Foam::decompositionModel
MeshObject wrapper of decompositionMethod.
Definition: decompositionModel.H:57
Foam::polyBoundaryMesh::start
label start() const
The start label of the boundary faces in the polyMesh face list.
Definition: polyBoundaryMesh.C:638
Foam::argList::rootPath
const fileName & rootPath() const
Return root path.
Definition: argListI.H:63
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::polyBoundaryMesh::names
wordList names() const
Return a list of patch names.
Definition: polyBoundaryMesh.C:593
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
foamDlOpenLibs.H
Foam::mapDistributePolyMesh::cellMap
const mapDistribute & cellMap() const
Cell distribute map.
Definition: mapDistributePolyMesh.H:223
Foam::fvMesh::readUpdate
virtual readUpdateState readUpdate()
Update the mesh based on the mesh files saved in time.
Definition: fvMesh.C:519
Foam::parLagrangianRedistributor::findClouds
static void findClouds(const fvMesh &, wordList &cloudNames, List< wordList > &objectNames)
Find all clouds (on all processors) and for each cloud all.
Foam::polyMesh::TOPO_PATCH_CHANGE
Definition: polyMesh.H:96
Foam::parFvFieldReconstructor::reconstructFvSurfaceFields
label reconstructFvSurfaceFields(const IOobjectList &objects, const wordRes &selectedFields=wordRes()) const
Read, reconstruct and write all/selected surface fields.
Foam::polyMesh::pointsInstance
const fileName & pointsInstance() const
Return the current instance directory for points.
Definition: polyMesh.C:815
regionName
Foam::word regionName
Definition: createNamedDynamicFvMesh.H:1
Foam::decompositionMethod::parallelAware
virtual bool parallelAware() const =0
Is method parallel aware?
Foam::argList::noFunctionObjects
static void noFunctionObjects(bool addWithOption=false)
Remove '-noFunctionObjects' option and ignore any occurrences.
Definition: argList.C:454
Foam::primitiveMesh::nCells
label nCells() const
Number of mesh cells.
Definition: primitiveMeshI.H:96
Foam::Field< scalar >
Foam::IOobject::writeOpt
writeOption writeOpt() const
The write option.
Definition: IOobjectI.H:177
Foam::volSymmTensorField
GeometricField< symmTensor, fvPatchField, volMesh > volSymmTensorField
Definition: volFieldsFwd.H:63
Foam::functionObjectList::off
void off()
Switch the function objects off.
Definition: functionObjectList.C:573
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::parLagrangianRedistributor
Lagrangian field redistributor.
Definition: parLagrangianRedistributor.H:61
Foam::Time::timePath
fileName timePath() const
Return current time path.
Definition: Time.H:375
Foam::fvMeshTools::newMesh
static autoPtr< fvMesh > newMesh(const IOobject &io, const bool masterOnlyReading)
Read mesh or create dummy mesh (0 cells, >0 patches). Works in two.
Definition: fvMeshTools.C:424
Foam::polyMesh::removeFiles
void removeFiles(const fileName &instanceDir) const
Remove all files from mesh instance.
Definition: polyMesh.C:1264
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:472
Foam::mapDistributePolyMesh::faceMap
const mapDistribute & faceMap() const
Face distribute map.
Definition: mapDistributePolyMesh.H:217
argList.H
Foam::mapDistribute
Class containing processor-to-processor mapping information.
Definition: mapDistribute.H:163
Foam::decompositionModel::decomposer
decompositionMethod & decomposer() const
Definition: decompositionModel.H:122
Foam::IOobject::READ_IF_PRESENT
Definition: IOobject.H:122
Foam::mapDistributePolyMesh::patchMap
const mapDistribute & patchMap() const
Patch distribute map.
Definition: mapDistributePolyMesh.H:229
Foam::decompositionMethod::nDomains
static label nDomains(const dictionary &decompDict)
Return the numberOfSubdomains entry from the dictionary.
Definition: decompositionMethod.C:62
Foam::TimePaths::times
instantList times() const
Search the case for valid time directories.
Definition: TimePaths.C:149
addRegionOption.H
Foam::parLagrangianRedistributor::redistributeLagrangianPositions
autoPtr< mapDistributeBase > redistributeLagrangianPositions(passivePositionParticleCloud &cloud) const
Redistribute and write lagrangian positions.
Foam::CompactIOList< face, label >
Foam::andOp
Definition: ops.H:233
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:43
Foam::processorPolyPatch
Neighbour processor patch.
Definition: processorPolyPatch.H:58
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:62
Foam::polyMesh::TOPO_CHANGE
Definition: polyMesh.H:95
Foam::volScalarField
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:57
Foam::regionProperties
Simple class to hold region information for coupled region simulations.
Definition: regionProperties.H:60
Foam::pow
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Definition: dimensionedScalar.C:75
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
fld
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputLagrangian.H:23
Foam::hexRef8Data
Various for reading/decomposing/reconstructing/distributing refinement data.
Definition: hexRef8Data.H:60
Foam::UPstream::commsTypeNames
static const Enum< commsTypes > commsTypeNames
Names of the communication types.
Definition: UPstream.H:74
Foam::timeSelector::selectIfPresent
static instantList selectIfPresent(Time &runTime, const argList &args)
Definition: timeSelector.C:272
Foam::mapDistributePolyMesh::oldPatchSizes
const labelList & oldPatchSizes() const
List of the old patch sizes.
Definition: mapDistributePolyMesh.H:193
Foam::UPstream::commsTypes::scheduled
forAllIters
#define forAllIters(container, iter)
Iterate across all elements in the container object.
Definition: stdFoam.H:223
timeName
word timeName
Definition: getTimeIndex.H:3
Foam::argList::path
fileName path() const
Return the full path to the (processor local) case.
Definition: argListI.H:81
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
Foam::primitiveMesh::nBoundaryFaces
label nBoundaryFaces() const
Number of boundary faces (== nFaces - nInternalFaces)
Definition: primitiveMeshI.H:84
Foam::Time::controlDict
const dictionary & controlDict() const
Return read access to the controlDict dictionary.
Definition: Time.H:364
Foam::eqOp
Definition: ops.H:71
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
meshRefinement.H
Foam::decompositionMethod
Abstract base class for domain decomposition.
Definition: decompositionMethod.H:51
Foam::mapDistributeBase::subHasFlip
bool subHasFlip() const
Does subMap include a sign.
Definition: mapDistributeBase.H:306
hexRef8Data.H
Foam::GeoMesh
Generic mesh wrapper used by volMesh, surfaceMesh, pointMesh etc.
Definition: GeoMesh.H:48
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:84
fvMesh.H
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
cloudNames
const wordList cloudNames(cloudFields.sortedToc())
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::PtrList::set
const T * set(const label i) const
Return const pointer to element (if set) or nullptr.
Definition: PtrListI.H:143
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
Foam::ListOps::uniqueEqOp
List helper to append y unique elements onto the end of x.
Definition: ListOps.H:577
PstreamReduceOps.H
Inter-processor communication reduction functions.
Foam::SphericalTensor< scalar >
Foam::IOobjectList
List of IOobjects with searching and retrieving facilities.
Definition: IOobjectList.H:55
Foam::Time::findInstance
word findInstance(const fileName &dir, const word &name=word::null, const IOobject::readOption rOpt=IOobject::MUST_READ, const word &stopInstance=word::null) const
Definition: Time.C:802
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::readFields
void readFields(const typename GeoFieldType::Mesh &mesh, const IOobjectList &objects, const wordHashSet &selectedFields, LIFOStack< regIOobject * > &storedObjects)
Read the selected GeometricFields of the templated type.
Definition: ReadFieldsTemplates.C:312
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:445
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:439
Foam::polyMesh::readUpdateState
readUpdateState
Enumeration defining the state of the mesh after a read update.
Definition: polyMesh.H:91
Foam::HashTable
A HashTable similar to std::unordered_map.
Definition: HashTable.H:105
Foam::sigFpe::requested
static bool requested()
Check if SIGFPE signals handler is to be enabled.
Definition: sigFpe.C:142
Foam::polyBoundaryMesh::nNonProcessor
label nNonProcessor() const
The number of patches before the first processor patch.
Definition: polyBoundaryMesh.C:573
Foam::volVectorField
GeometricField< vector, fvPatchField, volMesh > volVectorField
Definition: volFieldsFwd.H:60
Foam::polyMesh::bounds
const boundBox & bounds() const
Return mesh bounding box.
Definition: polyMesh.H:441
Foam::fvMesh::boundary
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:555
Foam::mapDistributeBase::constructSize
label constructSize() const
Constructed data size.
Definition: mapDistributeBase.H:270
Foam::decompositionModel::New
static const decompositionModel & New(const polyMesh &mesh, const fileName &decompDictFile="")
Read (optionally from absolute path) and register on mesh.
Definition: decompositionModel.C:116
Foam::argList::addBoolOption
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
Definition: argList.C:325
Time.H
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
Foam::TimePaths::system
const word & system() const
Return system name.
Definition: TimePathsI.H:94
Foam::IOstreamOption::ASCII
"ascii" (normal default)
Definition: IOstreamOption.H:72
Foam::UPstream::msgType
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:492
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:372
Foam::Pstream::gatherList
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
Definition: gatherScatterList.C:52
Foam::Time::caseName
const fileName & caseName() const
Return case name.
Definition: TimePathsI.H:54
Foam::parFvFieldReconstructor::reconstructFvVolumeFields
label reconstructFvVolumeFields(const IOobjectList &objects, const wordRes &selectedFields=wordRes()) const
Read, reconstruct and write all/selected volume fields.
Foam::UPstream::nRequests
static label nRequests()
Get number of outstanding requests.
Definition: UPstream.C:224
fvMeshDistribute.H
Foam::cp
bool cp(const fileName &src, const fileName &dst, const bool followLink=true)
Copy the source to the destination (recursively if necessary).
Definition: MSwindows.C:802
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::parLagrangianRedistributor::readFields
static label readFields(const passivePositionParticleCloud &cloud, const IOobjectList &objects, const wordRes &selectedFields=wordRes())
Read and store all fields of a cloud.
Foam::Time::path
fileName path() const
Return path.
Definition: Time.H:358
Foam::flatOutput
FlatOutput< Container > flatOutput(const Container &obj, label len=0)
Global flatOutput function.
Definition: FlatOutput.H:85
Foam::IOstream::defaultPrecision
static unsigned int defaultPrecision()
Return the default precision.
Definition: IOstream.H:333
fvMeshTools.H
Foam::rmDir
bool rmDir(const fileName &directory, const bool silent=false)
Remove a directory and its contents (optionally silencing warnings)
Definition: MSwindows.C:1018
Foam::lagrangianReconstructor
Reconstructor for lagrangian positions and fields.
Definition: lagrangianReconstructor.H:56
Foam::timeSelector::addOptions
static void addOptions(const bool constant=true, const bool withZero=false)
Add timeSelector options to argList::validOptions.
Definition: timeSelector.C:108
Foam::Vector< scalar >
Foam::Time::rootPath
const fileName & rootPath() const
Return root path.
Definition: TimePathsI.H:42
Foam::List< labelList >
Foam::IOmapDistributePolyMesh
IOmapDistributePolyMesh is derived from mapDistributePolyMesh and IOobject to give the mapDistributeP...
Definition: IOmapDistributePolyMesh.H:53
Foam::decompositionMethod::decompose
virtual labelList decompose(const pointField &points, const scalarField &pointWeights) const
Return for every coordinate the wanted processor number.
Definition: decompositionMethod.H:244
Foam::Time::setTime
virtual void setTime(const Time &t)
Reset the time and time-index to those of the given time.
Definition: Time.C:1006
Foam::UList< label >
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::primitiveMesh::nPoints
label nPoints() const
Number of mesh points.
Definition: primitiveMeshI.H:37
Foam::identity
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
Definition: labelList.C:38
Foam::IOList< label >
Foam::wordRes
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:51
Foam::argList::globalPath
fileName globalPath() const
Return the full path to the global case.
Definition: argListI.H:87
timeSelector.H
createTime.H
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::autoPtr::clear
void clear() noexcept
Same as reset(nullptr)
Definition: autoPtr.H:178
Foam::boundBox
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:63
Foam::mapDistributeBase
Class containing processor-to-processor mapping information.
Definition: mapDistributeBase.H:103
Foam::mapDistribute::reverseDistribute
void reverseDistribute(const label constructSize, List< T > &, const bool dummyTransform=true, const int tag=UPstream::msgType()) const
Reverse distribute data using default commsType.
Definition: mapDistributeTemplates.C:182
Foam::fvMesh::time
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:248
Foam::IPstream
Input inter-processor communications stream.
Definition: IPstream.H:52
Foam::mapDistributePolyMesh::pointMap
const mapDistribute & pointMap() const
Point distribute map.
Definition: mapDistributePolyMesh.H:211
decompositionModel.H
cyclicACMIFvPatch.H
Foam::mapDistributePolyMesh::nOldFaces
label nOldFaces() const
Number of faces in mesh before distribution.
Definition: mapDistributePolyMesh.H:181
Foam::instant
An instant of time. Contains the time value and name.
Definition: instant.H:52
Foam::volSphericalTensorField
GeometricField< sphericalTensor, fvPatchField, volMesh > volSphericalTensorField
Definition: volFieldsFwd.H:62
Foam::mapDistributePolyMesh
Class containing mesh-to-mesh mapping information after a mesh distribution where we send parts of me...
Definition: mapDistributePolyMesh.H:66
Foam::polyMesh::globalData
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1234
Foam::mapDistributePolyMesh::nOldPoints
label nOldPoints() const
Number of points in mesh before distribution.
Definition: mapDistributePolyMesh.H:175
Foam::IOobject::objectPath
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:209
Foam::mapDistributePolyMesh::nOldCells
label nOldCells() const
Number of cells in mesh before distribution.
Definition: mapDistributePolyMesh.H:187
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::TimePaths::constant
const word & constant() const
Return constant name.
Definition: TimePathsI.H:88
Foam::GeometricField< scalar, fvPatchField, volMesh >
Foam::mapDistributeBase::constructMap
const labelListList & constructMap() const
From subsetted data to new reconstructed data.
Definition: mapDistributeBase.H:294
Foam::IOobjectList::lookupClass
IOobjectList lookupClass(const char *clsName) const
The list of IOobjects with the given headerClassName.
Definition: IOobjectList.C:290
Foam::argList::addOption
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Add an option to validOptions with usage information.
Definition: argList.C:336
Foam::IOobject::NO_READ
Definition: IOobject.H:123
args
Foam::argList args(argc, argv)
Foam::mkDir
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:507
parFvFieldReconstructor.H
Foam::mapDistributePolyMesh::distributePointData
void distributePointData(List< T > &lst) const
Distribute list of point data.
Definition: mapDistributePolyMesh.H:242
Foam::topoSet::removeFiles
static void removeFiles(const polyMesh &)
Helper: remove all sets files from mesh instance.
Definition: topoSet.C:638
DebugVar
#define DebugVar(var)
Report a variable name and value.
Definition: messageStream.H:376
zeroGradientFvPatchFields.H
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:298
Foam::fvMeshDistribute
Sends/receives parts of mesh+fvfields to neighbouring processors. Used in load balancing.
Definition: fvMeshDistribute.H:73
pointFields.H
Foam::polyMesh::setInstance
void setInstance(const fileName &instance, const IOobject::writeOption wOpt=IOobject::AUTO_WRITE)
Set the instance for mesh files.
Definition: polyMeshIO.C:36
fields
multivariateSurfaceInterpolationScheme< scalar >::fieldTable fields
Definition: createFields.H:97
Foam::parFvFieldReconstructor
Finite volume reconstructor for volume and surface fields.
Definition: parFvFieldReconstructor.H:61
Foam::isDir
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: MSwindows.C:643
Foam::loadOrCreateMesh
autoPtr< fvMesh > loadOrCreateMesh(const IOobject &io)
Load (if it exists) or create zero cell mesh given an IOobject:
Foam::argList::found
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:157
loadOrCreateMesh.H
Load or create (0 size) a mesh. Used in distributing meshes to a larger number of processors.
Foam::flipOp
Functor to negate primitives. Dummy for most other types.
Definition: flipOp.H:53
Foam::IOobject::MUST_READ
Definition: IOobject.H:120
Foam::flipLabelOp
Negate integer values.
Definition: flipOp.H:85
Foam::polyMesh::tetBasePtIs
const labelIOList & tetBasePtIs() const
Return the tetBasePtIs.
Definition: polyMesh.C:861