domainDecomposition.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2025 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "domainDecomposition.H"
27 #include "decompositionMethod.H"
28 #include "IOobjectList.H"
29 #include "cellSet.H"
30 #include "faceSet.H"
31 #include "fvMeshStitcher.H"
32 #include "pointSet.H"
33 #include "hexRef8Data.H"
34 #include "cyclicFvPatch.H"
35 #include "processorCyclicFvPatch.H"
36 #include "nonConformalFvPatch.H"
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
43 }
44 
45 
46 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
47 
48 Foam::label Foam::domainDecomposition::compareInstances
49 (
50  const fileName& a,
51  const fileName& b
52 ) const
53 {
54  const word& constant = runTimes_.completeTime().constant();
55 
56  if (a == constant && b == constant) return 0;
57 
58  if (a == constant) return +1;
59 
60  if (b == constant) return -1;
61 
62  const scalar aValue = instant(a).value();
63  const scalar bValue = instant(b).value();
64 
65  if (aValue < bValue) return +1;
66 
67  if (aValue > bValue) return -1;
68 
69  return 0;
70 }
71 
72 
73 void Foam::domainDecomposition::validateComplete() const
74 {
75  if (!haveComplete())
76  {
78  << "Complete data requested but complete mesh has not been "
79  << "generated or read" << exit(FatalError);
80  }
81 }
82 
83 
84 void Foam::domainDecomposition::validateProcs() const
85 {
86  if (!haveProcs())
87  {
89  << "Decomposed data requested but decomposed mesh has not been "
90  << "generated or read" << exit(FatalError);
91  }
92 }
93 
94 
95 void Foam::domainDecomposition::readComplete(const bool doPost)
96 {
97  completeMesh_.reset
98  (
99  new fvMesh
100  (
101  IOobject
102  (
103  regionName_,
104  runTimes_.completeTime().name(),
105  meshPath_,
106  runTimes_.completeTime(),
109  ),
110  false
111  )
112  );
113 
114  completeMesh_->postConstruct
115  (
116  false,
117  false,
119  );
120 }
121 
122 
123 void Foam::domainDecomposition::readProcs(const bool doPost)
124 {
125  for (label proci = 0; proci < nProcs(); proci++)
126  {
127  procMeshes_.set
128  (
129  proci,
130  new fvMesh
131  (
132  IOobject
133  (
134  regionName_,
135  runTimes_.procTimes()[proci].name(),
136  meshPath_,
137  runTimes_.procTimes()[proci],
140  ),
141  false
142  )
143  );
144 
145  procMeshes_[proci].postConstruct
146  (
147  false,
148  false,
150  );
151  }
152 }
153 
154 
155 void Foam::domainDecomposition::readCompleteAddressing()
156 {
157  cellProc_ =
159  (
160  IOobject
161  (
162  "cellProc",
163  completeMesh().facesInstance(),
164  completeMesh().meshSubDir,
165  completeMesh(),
168  false
169  )
170  );
171 }
172 
173 
174 void Foam::domainDecomposition::readProcsAddressing()
175 {
176  for (label proci = 0; proci < nProcs(); proci++)
177  {
178  const fvMesh& procMesh = procMeshes_[proci];
179 
180  procPointAddressing_[proci] =
182  (
183  IOobject
184  (
185  "pointProcAddressing",
186  procMesh.facesInstance(),
187  procMesh.meshSubDir,
188  procMesh,
191  false
192  )
193  );
194 
195  procFaceAddressing_[proci] =
197  (
198  IOobject
199  (
200  "faceProcAddressing",
201  procMesh.facesInstance(),
202  procMesh.meshSubDir,
203  procMesh,
206  false
207  )
208  );
209 
210  procCellAddressing_[proci] =
212  (
213  IOobject
214  (
215  "cellProcAddressing",
216  procMesh.facesInstance(),
217  procMesh.meshSubDir,
218  procMesh,
221  false
222  )
223  );
224  }
225 }
226 
227 
228 void Foam::domainDecomposition::readAddressing()
229 {
230  readCompleteAddressing();
231  readProcsAddressing();
232  procFaceAddressingBf_.clear();
233 }
234 
235 
236 Foam::fvMesh::readUpdateState Foam::domainDecomposition::readUpdate()
237 {
238  validateComplete();
239  validateProcs();
240 
241  // Do read-update on all meshes
243  completeMesh_->readUpdate(fvMesh::stitchType::none);
244 
245  forAll(runTimes_.procTimes(), proci)
246  {
247  fvMesh::readUpdateState procStat =
248  procMeshes_[proci].readUpdate(fvMesh::stitchType::none);
249 
250  stat = procStat > stat ? procStat : stat;
251  }
252 
253  return stat;
254 }
255 
256 
257 void Foam::domainDecomposition::writeCompleteAddressing() const
258 {
259  labelIOList cellProc
260  (
261  IOobject
262  (
263  "cellProc",
264  completeMesh().facesInstance(),
265  completeMesh().meshSubDir,
266  completeMesh(),
269  ),
270  cellProc_
271  );
272 
273  cellProc.write();
274 }
275 
276 
277 void Foam::domainDecomposition::writeProcsAddressing() const
278 {
279  for (label proci = 0; proci < nProcs(); proci++)
280  {
281  const fvMesh& procMesh = procMeshes_[proci];
282 
283  labelIOList pointProcAddressing
284  (
285  IOobject
286  (
287  "pointProcAddressing",
288  procMesh.facesInstance(),
289  procMesh.meshSubDir,
290  procMesh,
293  ),
294  procPointAddressing_[proci]
295  );
296  pointProcAddressing.write();
297 
298  labelIOList faceProcAddressing
299  (
300  IOobject
301  (
302  "faceProcAddressing",
303  procMesh.facesInstance(),
304  procMesh.meshSubDir,
305  procMesh,
308  ),
309  procFaceAddressing_[proci]
310  );
311  faceProcAddressing.write();
312 
313  labelIOList cellProcAddressing
314  (
315  IOobject
316  (
317  "cellProcAddressing",
318  procMesh.facesInstance(),
319  procMesh.meshSubDir,
320  procMesh,
323  ),
324  procCellAddressing_[proci]
325  );
326  cellProcAddressing.write();
327  }
328 }
329 
330 
331 void Foam::domainDecomposition::writeAddressing() const
332 {
333  writeCompleteAddressing();
334  writeProcsAddressing();
335 }
336 
337 
338 void Foam::domainDecomposition::writeProcPoints(const fileName& inst)
339 {
340  IOobject completePointsIo
341  (
342  "points",
343  inst,
345  completeMesh(),
348  false
349  );
350 
351  if (!completePointsIo.headerOk()) return;
352 
353  const pointIOField completePoints(completePointsIo);
354 
355  for (label proci = 0; proci < nProcs(); proci++)
356  {
357  pointIOField procPoints
358  (
359  IOobject
360  (
361  "points",
362  inst,
364  procMeshes()[proci],
367  false
368  ),
369  pointField
370  (
371  completePoints,
372  procPointAddressing_[proci]
373  )
374  );
375 
376  procPoints.write();
377  }
378 }
379 
380 
381 void Foam::domainDecomposition::writeCompletePoints(const fileName& inst)
382 {
383  pointIOField completePoints
384  (
385  IOobject
386  (
387  "points",
388  inst,
390  completeMesh(),
393  false
394  ),
395  pointField(completeMesh().nPoints())
396  );
397 
398  for (label proci = 0; proci < nProcs(); proci++)
399  {
400  IOobject procPointsIo
401  (
402  "points",
403  inst,
405  procMeshes()[proci],
408  false
409  );
410 
411  if (!procPointsIo.headerOk()) return;
412 
413  completePoints.rmap
414  (
415  pointIOField(procPointsIo),
416  procPointAddressing_[proci]
417  );
418  }
419 
420  completePoints.write();
421 }
422 
423 
424 template<>
425 inline Foam::label Foam::domainDecomposition::setIndex<Foam::cellSet>
426 (
427  const label proci,
428  const label procCelli
429 ) const
430 {
431  return procCellAddressing_[proci][procCelli];
432 }
433 
434 
435 template<>
436 inline Foam::label Foam::domainDecomposition::setIndex<Foam::faceSet>
437 (
438  const label proci,
439  const label procFacei
440 ) const
441 {
442  return mag(procFaceAddressing_[proci][procFacei]) - 1;
443 }
444 
445 
446 template<>
447 inline Foam::label Foam::domainDecomposition::setIndex<Foam::pointSet>
448 (
449  const label proci,
450  const label procPointi
451 ) const
452 {
453  return procPointAddressing_[proci][procPointi];
454 }
455 
456 
457 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
458 
460 (
461  const processorRunTimes& runTimes,
462  const fileName& meshPath,
463  const word& regionName,
464  const multiDomainDecomposition& regionMeshes
465 )
466 :
467  runTimes_(runTimes),
468  meshPath_(meshPath),
469  regionName_(regionName),
470  completeMesh_(nullptr),
471  procMeshes_(nProcs()),
472  regionMeshes_(regionMeshes),
473  cellProc_(),
474  procPointAddressing_(nProcs()),
475  procFaceAddressing_(nProcs()),
476  procCellAddressing_(nProcs()),
477  procFaceAddressingBf_()
478 {}
479 
480 
481 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
482 
484 {}
485 
486 
487 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
488 
490 {
491  readComplete(true);
492 }
493 
494 
496 {
497  readComplete(false);
498 
500  (
501  "cellProc",
502  completeMesh().facesInstance(),
504  completeMesh()
505  );
506  IOobject procFaceIo
507  (
508  "faces",
509  completeMesh().facesInstance(),
510  completeMesh().meshDir(),
511  runTimes_.procTimes()[0]
512  );
513  typeIOobject<labelIOList> procAddrIo
514  (
515  "cellProcAddressing",
516  completeMesh().facesInstance(),
517  completeMesh().meshDir(),
518  runTimes_.procTimes()[0]
519  );
520 
521  const bool load = addrIo.headerOk() && procFaceIo.headerOk();
522 
523  if (load)
524  {
525  readProcs(false);
526 
527  if (procAddrIo.headerOk())
528  {
529  readAddressing();
530  }
531  else
532  {
533  readCompleteAddressing();
534 
536  << nl << " Processor meshes exist but have no addressing."
537  << nl << nl << " This could be because the processor meshes "
538  << "have changed. Decomposing the" << nl << " mesh would "
539  << "overwrite that change. If you are sure that this is "
540  << "appropriate," << nl << " then delete the "
541  << fileName("processor*")/procFaceIo.relativePath().c_str()
542  << " directories and re-run this" << nl << " command."
543  << exit(FatalError);
544  }
545 
546  decomposePoints();
547  }
548  else
549  {
550  if
551  (
552  completeMesh().facesInstance()
553  != runTimes_.completeTime().name()
554  && completeMesh().facesInstance()
555  != runTimes_.completeTime().constant()
556  )
557  {
559  << "Cannot begin mesh decomposition at time "
560  << fileName(runTimes_.completeTime().name()) << nl
561  << "The mesh at this instant is that of an earlier"
562  << " time " << completeMesh().facesInstance() << nl
563  << "Decomposition must start from this earlier time"
564  << exit(FatalError);
565  }
566 
567  decompose();
568  }
569 
570  if (doPost)
571  {
572  postReadDecompose();
573  unconformReadDecompose();
574  }
575 
576  return !load;
577 }
578 
579 
581 {
582  completeMesh_->stitcher().connect(false, false, true);
583 }
584 
585 
587 {
588  if (!completeConformal())
589  {
590  procFaceAddressingBf_.clear();
591 
592  forAll(procMeshes_, proci)
593  {
594  procMeshes_[proci].conform();
595  }
596 
597  unconform();
598  }
599 }
600 
601 
603 (
604  const bool decomposed,
605  const bool doSets
606 )
607 {
608  writeProcs(doSets);
609 
610  if (decomposed)
611  {
612  writeProcPoints(completeMesh().facesInstance());
613  }
614 }
615 
616 
618 {
619  readProcs(false);
620 
621  IOobject faceIo
622  (
623  "faces",
624  procMeshes()[0].facesInstance(),
625  procMeshes()[0].meshDir(),
626  runTimes_.completeTime()
627  );
629  (
630  "cellProc",
631  procMeshes()[0].facesInstance(),
632  procMeshes()[0].meshDir(),
633  runTimes_.completeTime()
634  );
635  typeIOobject<labelIOList> procAddrIo
636  (
637  "cellProcAddressing",
638  procMeshes()[0].facesInstance(),
640  procMeshes()[0]
641  );
642 
643  const bool load = faceIo.headerOk() && procAddrIo.headerOk();
644 
645  if (load)
646  {
647  typeIOobject<pointIOField> completePointsIo
648  (
649  "points",
650  procMeshes()[0].pointsInstance(),
651  procMeshes()[0].meshDir(),
652  runTimes_.completeTime()
653  );
654 
655  readComplete(false);
656 
657  if (addrIo.headerOk())
658  {
659  readAddressing();
660  }
661  else
662  {
663  readProcsAddressing();
664 
666  << nl << " A complete mesh exists but has no "
667  << addrIo.name() << " addressing." << nl << nl << " This "
668  << "could be because the complete mesh has changed. "
669  << "Reconstructing the" << nl << " mesh would overwrite "
670  << "that change. If you are sure that this is appropriate,"
671  << nl << " then delete the " << faceIo.relativePath()
672  << " directory and re-run this command." << nl << nl
673  << " Or, it could be because the complete and processor "
674  << "meshes were decomposed" << nl << " by a version of "
675  << "OpenFOAM that pre-dates the automatic generation of "
676  << nl << " " << addrIo.name() << " addressing. This will be "
677  << "assumed and the " << addrIo.name() << " addressing will"
678  << nl << " be re-built" << nl << endl;
679 
680  cellProc_ = labelList(completeMesh().nCells(), -1);
681 
682  for (label proci = 0; proci < nProcs(); proci++)
683  {
685  (
686  cellProc_,
687  procCellAddressing_[proci]
688  ) = proci;
689  }
690 
691  writeCompleteAddressing();
692  }
693 
694  reconstructPoints();
695  }
696  else
697  {
698  if
699  (
700  procMeshes()[0].facesInstance()
701  != runTimes_.procTimes()[0].name()
702  && procMeshes()[0].facesInstance()
703  != runTimes_.procTimes()[0].constant()
704  )
705  {
707  << "Cannot begin mesh reconstruction at time "
708  << fileName(runTimes_.procTimes()[0].name()) << nl
709  << "The mesh at this instant is that of an earlier"
710  << " time " << procMeshes()[0].facesInstance() << nl
711  << "Reconstruction must start from this earlier time"
712  << exit(FatalError);
713  }
714 
715  reconstruct();
716  }
717 
718  if (doPost)
719  {
720  postReadReconstruct();
721  unconformReadReconstruct();
722  }
723 
724  return !load;
725 }
726 
727 
729 {
730  forAll(procMeshes_, proci)
731  {
732  procMeshes_[proci].stitcher().connect(false, false, true);
733  }
734 }
735 
736 
738 {
739  if (!procsConformal())
740  {
741  procFaceAddressingBf_.clear();
742 
743  completeMesh_->conform();
744 
745  unconform();
746  }
747 }
748 
749 
751 (
752  const bool reconstructed,
753  const bool doSets
754 )
755 {
756  writeComplete(doSets);
757 
758  if (reconstructed)
759  {
760  writeCompletePoints(procMeshes()[0].facesInstance());
761  }
762 }
763 
764 
766 {
767  validateComplete();
768 
769  return completeMesh_->readUpdate(fvMesh::stitchType::nonGeometric);
770 }
771 
772 
774 (
775  const bool doPost
776 )
777 {
778  const fvMesh::readUpdateState stat = readUpdate();
779 
780  // Topology changes
781  {
782  const label facesCompare =
783  compareInstances
784  (
785  completeMesh().facesInstance(),
786  procMeshes_[0].facesInstance()
787  );
788 
789  // If the complete mesh has newer topology then we need to decompose
790  if (facesCompare == -1)
791  {
792  decompose();
793  }
794 
795  // If there has been matching topology change then reload the addressing
796  if (facesCompare == 0 && stat >= fvMesh::TOPO_CHANGE)
797  {
798  readAddressing();
799  }
800 
801  // The processor meshes should not have newer topology when decomposing
802  if (facesCompare == +1)
803  {
805  << "Cannot decompose at time "
806  << procMeshes_[0].facesInstance()
807  << " because the processor mesh topology has evolved further"
808  << " than the complete mesh topology." << exit(FatalError);
809  }
810  }
811 
812  // Geometry changes
813  {
814  const label pointsCompare =
815  compareInstances
816  (
817  completeMesh().pointsInstance(),
818  procMeshes_[0].pointsInstance()
819  );
820 
821  // If the complete mesh has newer geometry then we need to decompose
822  // the points
823  if (pointsCompare == -1)
824  {
825  decomposePoints();
826  }
827 
828  // The processor meshes should not have newer geometry when decomposing
829  if (pointsCompare == +1)
830  {
832  << "Cannot decompose at time "
833  << procMeshes_[0].pointsInstance()
834  << " because the processor mesh geometry has evolved further"
835  << " than the complete mesh geometry." << exit(FatalError);
836  }
837  }
838 
839  if (doPost)
840  {
841  postReadUpdateDecompose(stat);
842  unconformReadUpdateDecompose(stat);
843  }
844 
845  return stat;
846 }
847 
848 
850 (
851  const fvMesh::readUpdateState stat
852 )
853 {
854  if (completeMesh_->stitcher().stitches() && stat != fvMesh::UNCHANGED)
855  {
856  procFaceAddressingBf_.clear();
857 
858  completeMesh_->stitcher().connect(false, false, true);
859  }
860 }
861 
862 
864 (
865  const fvMesh::readUpdateState stat
866 )
867 {
868  if (completeMesh_->stitcher().stitches() && stat != fvMesh::UNCHANGED)
869  {
870  forAll(procMeshes_, proci)
871  {
872  procMeshes_[proci].conform();
873  }
874 
875  unconform();
876  }
877 }
878 
879 
881 (
882  const bool doPost
883 )
884 {
885  const fvMesh::readUpdateState stat = readUpdate();
886 
887  // Topology changes
888  {
889  const label facesCompare =
890  compareInstances
891  (
892  completeMesh().facesInstance(),
893  procMeshes_[0].facesInstance()
894  );
895 
896  // The complete mesh should not have newer topology when reconstructing
897  if (facesCompare == -1)
898  {
900  << "Cannot reconstruct at time "
901  << completeMesh().facesInstance()
902  << " because the complete mesh topology has evolved further"
903  << " than the processor mesh topology." << exit(FatalError);
904  }
905 
906  // If there has been matching topology change then reload the addressing
907  if (facesCompare == 0 && stat >= fvMesh::TOPO_CHANGE)
908  {
909  readAddressing();
910  }
911 
912  // If the processor meshes have newer topology then we need to
913  // reconstruct
914  if (facesCompare == +1)
915  {
916  reconstruct();
917  }
918  }
919 
920  // Geometry changes
921  {
922  const label pointsCompare =
923  compareInstances
924  (
925  completeMesh().pointsInstance(),
926  procMeshes_[0].pointsInstance()
927  );
928 
929  // The complete mesh should not have newer geometry when reconstructing
930  if (pointsCompare == -1)
931  {
933  << "Cannot reconstruct at time "
934  << completeMesh().pointsInstance()
935  << " because the complete mesh geometry has evolved further"
936  << " than the processor mesh geometry." << exit(FatalError);
937  }
938 
939  // If the processor meshes have newer geometry then we need to
940  // reconstruct the points
941  if (pointsCompare == +1)
942  {
943  reconstructPoints();
944  }
945  }
946 
947  if (doPost)
948  {
949  postReadUpdateReconstruct(stat);
950  unconformReadUpdateReconstruct(stat);
951  }
952 
953  return stat;
954 }
955 
956 
958 (
959  const fvMesh::readUpdateState stat
960 )
961 {
962  if (completeMesh_->stitcher().stitches() && stat != fvMesh::UNCHANGED)
963  {
964  procFaceAddressingBf_.clear();
965 
966  forAll(procMeshes_, proci)
967  {
968  procMeshes_[proci].stitcher().connect(false, false, true);
969  }
970  }
971 }
972 
973 
975 (
976  const fvMesh::readUpdateState stat
977 )
978 {
979  if (completeMesh_->stitcher().stitches() && stat != fvMesh::UNCHANGED)
980  {
981  completeMesh_->conform();
982 
983  unconform();
984  }
985 }
986 
987 
990 {
991  validateComplete();
992  {
993  // Get any non-conformal proc-face addressing
994  List<List<DynamicList<label>>> nonConformalProcFaceAddressingBf =
995  this->nonConformalProcFaceAddressingBf();
996 
997  // Build finite volume face addressing boundary fields
998  procFaceAddressingBf_.resize(nProcs());
999  forAll(procMeshes_, proci)
1000  {
1001  const fvMesh& procMesh = procMeshes_[proci];
1002 
1003  procFaceAddressingBf_.set
1004  (
1005  proci,
1007  (
1008  procMesh.boundary(),
1010  calculatedFvsPatchLabelField::typeName
1011  )
1012  );
1013 
1014  forAll(procMesh.boundary(), procPatchi)
1015  {
1016  const fvPatch& fvp = procMesh.boundary()[procPatchi];
1017 
1018  if (isA<nonConformalFvPatch>(fvp))
1019  {
1020  procFaceAddressingBf_[proci][procPatchi] =
1021  nonConformalProcFaceAddressingBf[proci][procPatchi];
1022  }
1023  else if (isA<processorCyclicFvPatch>(fvp))
1024  {
1025  const label completePatchi =
1026  refCast<const processorCyclicFvPatch>(fvp)
1027  .referPatchIndex();
1028 
1029  procFaceAddressingBf_[proci][procPatchi] =
1030  mag(fvp.patchSlice(procFaceAddressing_[proci]))
1031  - completeMesh().boundaryMesh()[completePatchi].start();
1032  }
1033  else if (isA<processorFvPatch>(fvp))
1034  {
1035  procFaceAddressingBf_[proci][procPatchi] =
1036  fvp.patchSlice(procFaceAddressing_[proci]);
1037  }
1038  else
1039  {
1040  procFaceAddressingBf_[proci][procPatchi] =
1041  mag(fvp.patchSlice(procFaceAddressing_[proci]))
1042  - completeMesh().boundaryMesh()[procPatchi].start();
1043  }
1044  }
1045  }
1046  }
1047 
1048  return procFaceAddressingBf_;
1049 }
1050 
1051 
1052 void Foam::domainDecomposition::writeComplete(const bool doSets) const
1053 {
1054  const bool topologyWrite =
1055  static_cast<const faceCompactIOList&>(completeMesh().faces())
1056  .writeOpt() == IOobject::AUTO_WRITE;
1057 
1058  // Set the precision of the points data to be min 10
1060 
1061  // Write the complete mesh
1062  completeMesh().write();
1063 
1064  // Everything written below is topological data, so quit here if not
1065  // writing topology
1066  if (!topologyWrite) return;
1067 
1068  // Read, reconstruct and write sets
1069  if (doSets)
1070  {
1071  const IOobjectList proc0SetObjects
1072  (
1073  procMeshes_[0],
1074  runTimes_.procTimes()[0].name(),
1075  polyMesh::meshSubDir/"sets"
1076  );
1077 
1078  const IOobjectList proc0CellSetObjects
1079  (
1080  proc0SetObjects.lookupClass(cellSet::typeName)
1081  );
1082  const IOobjectList proc0FaceSetObjects
1083  (
1084  proc0SetObjects.lookupClass(faceSet::typeName)
1085  );
1086  const IOobjectList proc0PointSetObjects
1087  (
1088  proc0SetObjects.lookupClass(pointSet::typeName)
1089  );
1090 
1091  forAllConstIter(IOobjectList, proc0FaceSetObjects, iter)
1092  {
1093  reconstructSet<faceSet>(iter.key())->write();
1094  }
1095  forAllConstIter(IOobjectList, proc0CellSetObjects, iter)
1096  {
1097  reconstructSet<cellSet>(iter.key())->write();
1098  }
1099  forAllConstIter(IOobjectList, proc0PointSetObjects, iter)
1100  {
1101  reconstructSet<pointSet>(iter.key())->write();
1102  }
1103  }
1104 
1105  // Read, decompose, and write refinement data (if any)
1106  UPtrList<const labelList> cellMaps(nProcs());
1107  UPtrList<const labelList> pointMaps(nProcs());
1108  PtrList<const hexRef8Data> refinementDatas(nProcs());
1109  for (label proci = 0; proci < nProcs(); proci++)
1110  {
1111  const fvMesh& procMesh = procMeshes_[proci];
1112 
1113  cellMaps.set(proci, &procCellAddressing_[proci]);
1114  pointMaps.set(proci, &procPointAddressing_[proci]);
1115  refinementDatas.set
1116  (
1117  proci,
1118  new hexRef8Data
1119  (
1120  IOobject
1121  (
1122  "dummy",
1123  completeMesh().facesInstance(),
1125  procMesh,
1128  false
1129  )
1130  )
1131  );
1132  }
1133  hexRef8Data
1134  (
1135  IOobject
1136  (
1137  "dummy",
1138  completeMesh().facesInstance(),
1140  completeMesh(),
1143  false
1144  ),
1145  cellMaps,
1146  pointMaps,
1147  refinementDatas
1148  ).write();
1149 
1150  // Write decomposition addressing
1151  writeAddressing();
1152 }
1153 
1154 
1155 void Foam::domainDecomposition::writeProcs(const bool doSets) const
1156 {
1157  const bool topologyWrite =
1158  static_cast<const faceCompactIOList&>(procMeshes()[0].faces())
1159  .writeOpt() == IOobject::AUTO_WRITE;
1160 
1161  // Write out the meshes
1162  for (label proci = 0; proci < nProcs(); proci++)
1163  {
1164  const fvMesh& procMesh = procMeshes_[proci];
1165 
1166  // Set the precision of the points data to be min 10
1168 
1169  // Write the processor mesh
1170  procMesh.write();
1171  }
1172 
1173  // Everything written below is topological data, so quit here if not
1174  // writing topology
1175  if (!topologyWrite) return;
1176 
1177  // Read, decompose, and write any sets
1178  if (doSets)
1179  {
1180  const IOobjectList setObjects
1181  (
1182  completeMesh(),
1183  completeMesh().facesInstance(),
1184  polyMesh::meshSubDir/"sets"
1185  );
1186 
1187  const IOobjectList cellSetObjects
1188  (
1189  setObjects.lookupClass(cellSet::typeName)
1190  );
1191  const IOobjectList faceSetObjects
1192  (
1193  setObjects.lookupClass(faceSet::typeName)
1194  );
1195  const IOobjectList pointSetObjects
1196  (
1197  setObjects.lookupClass(pointSet::typeName)
1198  );
1199 
1200  forAllConstIter(IOobjectList, cellSetObjects, iter)
1201  {
1202  PtrList<cellSet> procCellSets =
1203  decomposeSet<cellSet>(iter.key());
1204  forAll(procCellSets, proci)
1205  {
1206  procCellSets[proci].write();
1207  }
1208  }
1209  forAllConstIter(IOobjectList, faceSetObjects, iter)
1210  {
1211  PtrList<faceSet> procFaceSets =
1212  decomposeSet<faceSet>(iter.key());
1213  forAll(procFaceSets, proci)
1214  {
1215  procFaceSets[proci].write();
1216  }
1217  }
1218  forAllConstIter(IOobjectList, pointSetObjects, iter)
1219  {
1220  PtrList<pointSet> procPointSets =
1221  decomposeSet<pointSet>(iter.key());
1222  forAll(procPointSets, proci)
1223  {
1224  procPointSets[proci].write();
1225  }
1226  }
1227  }
1228 
1229  // Read, decompose, and write refinement data (if any)
1231  (
1232  IOobject
1233  (
1234  "dummy",
1235  completeMesh().facesInstance(),
1237  completeMesh(),
1240  false
1241  )
1242  );
1243  for (label proci = 0; proci < nProcs(); proci++)
1244  {
1245  const fvMesh& procMesh = procMeshes_[proci];
1246 
1247  hexRef8Data
1248  (
1249  IOobject
1250  (
1251  "dummy",
1252  completeMesh().facesInstance(),
1254  procMesh,
1257  false
1258  ),
1260  procCellAddressing_[proci],
1261  procPointAddressing_[proci]
1262  ).write();
1263  }
1264 
1265  // Write decomposition addressing
1266  writeAddressing();
1267 }
1268 
1269 
1270 template<class SetType>
1272 (
1273  const word& name
1274 ) const
1275 {
1276  PtrList<SetType> result(nProcs());
1277 
1278  const SetType completeSet(completeMesh_, name);
1279 
1280  for (label proci = 0; proci < nProcs(); proci++)
1281  {
1282  const fvMesh& procMesh = procMeshes_[proci];
1283 
1284  result.set
1285  (
1286  proci,
1287  new SetType(procMesh, name, completeSet.size()/nProcs())
1288  );
1289 
1290  for (label i = 0; i < result[proci].maxSize(procMesh); ++ i)
1291  {
1292  if (completeSet.found(setIndex<SetType>(proci, i)))
1293  {
1294  result[proci].insert(i);
1295  }
1296  }
1297  }
1298 
1299  return result;
1300 }
1301 
1302 
1303 template
1305 Foam::domainDecomposition::decomposeSet<Foam::cellSet>
1306 (
1307  const word& name
1308 ) const;
1309 
1310 
1311 template
1313 Foam::domainDecomposition::decomposeSet<Foam::faceSet>
1314 (
1315  const word& name
1316 ) const;
1317 
1318 
1319 template
1321 Foam::domainDecomposition::decomposeSet<Foam::pointSet>
1322 (
1323  const word& name
1324 ) const;
1325 
1326 
1327 template<class SetType>
1329 (
1330  const word& name
1331 ) const
1332 {
1333  autoPtr<SetType> result(new SetType(completeMesh_, name, 128));
1334 
1335  for (label proci = 0; proci < nProcs(); proci++)
1336  {
1337  const fvMesh& procMesh = procMeshes_[proci];
1338 
1339  const SetType procSet(procMesh, name, IOobject::READ_IF_PRESENT);
1340 
1341  forAllConstIter(typename SetType, procSet, iter)
1342  {
1343  result().insert(setIndex<SetType>(proci, iter.key()));
1344  }
1345  }
1346 
1347  return result;
1348 }
1349 
1350 
1351 template
1353 Foam::domainDecomposition::reconstructSet<Foam::cellSet>
1354 (
1355  const word& name
1356 ) const;
1357 
1358 
1359 template
1361 Foam::domainDecomposition::reconstructSet<Foam::faceSet>
1362 (
1363  const word& name
1364 ) const;
1365 
1366 
1367 template
1369 Foam::domainDecomposition::reconstructSet<Foam::pointSet>
1370 (
1371  const word& name
1372 ) const;
1373 
1374 
1375 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:476
Generic GeometricBoundaryField class.
static const GeometricField< Type, GeoMesh, PrimitiveField > & null()
Return a null geometric field.
bool set(const Key &, const T &newElmt)
Set a new hashedEntry, overwriting existing entries.
Definition: HashTableI.H:91
List of IOobjects with searching and retrieving facilities.
Definition: IOobjectList.H:53
IOobjectList lookupClass(const word &className) const
Return the list for all IOobjects of a given class.
Definition: IOobjectList.C:190
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
fileName relativePath() const
Return the path relative to the case directory.
Definition: IOobject.C:396
bool headerOk()
Read header of local object without type-checking.
const word & name() const
Return name.
Definition: IOobject.H:307
static unsigned int defaultPrecision()
Return the default precision.
Definition: IOstream.H:473
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:91
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: PtrList.H:75
bool set(const label) const
Is element set.
Definition: PtrListI.H:62
static const word & constant()
Return constant name.
Definition: TimePaths.H:122
A List with indirect addressing.
Definition: UIndirectList.H:60
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: UPtrList.H:66
bool set(const label) const
Is element set.
Definition: UPtrListI.H:87
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
Automatic domain decomposition class for finite-volume meshes.
bool readDecompose(const bool doPost)
Read in the complete mesh. Read the processor meshes if they are.
fvMesh::readUpdateState readUpdateDecompose(const bool doPost)
Read-update for decomposition.
fvMesh::readUpdateState readUpdateReconstruct(const bool doPost)
Read-update for reconstruction.
void postReadReconstruct()
Post-read-construction steps for the meshes after read-reconstruct.
void postReadDecompose()
Post-read-construction steps for the meshes after read-decompose.
PtrList< SetType > decomposeSet(const word &name) const
Decompose a set.
void unconformReadReconstruct()
Synchronise non-conformal structure after read-reconstruct.
void readComplete()
Read the complete mesh only.
autoPtr< SetType > reconstructSet(const word &name) const
Reconstruct a set.
void unconformReadUpdateReconstruct(const fvMesh::readUpdateState stat)
Synchronise non-conformal structure after read-update-reconstruct.
void postReadUpdateReconstruct(const fvMesh::readUpdateState stat)
Complete read-update-reconstruct.
fvMesh::readUpdateState readUpdateComplete()
Read-update the complete mesh only.
void writeProcs(const bool doSets) const
Write the decomposed meshes and associated data.
void writeReadReconstruct(const bool reconstructed, const bool doSets)
Write following read-reconstruct.
void writeReadDecompose(const bool decomposed, const bool doSets)
Write following read-decompose.
bool readReconstruct(const bool doPost)
Read in the processor meshes. Read the complete mesh if it is.
void writeComplete(const bool doSets) const
Write the decomposed meshes and associated data.
void postReadUpdateDecompose(const fvMesh::readUpdateState stat)
Complete read-update-decompose.
const PtrList< surfaceLabelField::Boundary > & procFaceAddressingBf() const
Access the labels of faces for each processor (see notes above)
domainDecomposition(const processorRunTimes &procRunTimes, const fileName &meshPath, const word &regionName, const multiDomainDecomposition &regionMeshes=NullObjectRef< multiDomainDecomposition >())
Construct from processor run times and region name.
void unconformReadDecompose()
Synchronise non-conformal structure after read-decompose.
void unconformReadUpdateDecompose(const fvMesh::readUpdateState stat)
Synchronise non-conformal structure after read-update-decompose.
virtual ~domainDecomposition()
Destructor.
A class for handling file names.
Definition: fileName.H:82
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:96
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:962
readUpdateState
Enumeration defining the state of the mesh after a read update.
Definition: fvMesh.H:105
@ TOPO_CHANGE
Definition: fvMesh.H:109
virtual bool write(const bool write=true) const
Write mesh using IO settings from time.
Definition: fvMesh.C:1785
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:64
const List< T >::subList patchSlice(const List< T > &l) const
Slice list to patch.
Definition: fvPatch.H:172
Various for reading/decomposing/reconstructing/distributing refinement data.
Definition: hexRef8Data.H:58
bool write() const
Write.
Definition: hexRef8Data.C:372
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:273
const Time & completeTime() const
Access the complete run time.
Transfers refinement levels such that slow transition between levels is maintained....
Templated form of IOobject providing type information for file reading and header type checking.
Definition: IOobject.H:530
bool headerOk()
Read header (uses typeGlobalFile to find file) and check.
A class for handling words, derived from string.
Definition: word.H:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
label nPoints
volScalarField & b
Definition: createFields.H:27
#define WarningInFunction
Report a warning using Foam::Warning.
tmp< VolField< typename outerProduct< vector, Type >::type > > reconstruct(const SurfaceField< Type > &ssf)
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:258
const word & regionName(const solver &region)
Definition: solver.H:218
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
void mag(LagrangianPatchField< scalar > &f, const LagrangianPatchField< Type > &f1)
vectorIOField pointIOField
pointIOField is a vectorIOField.
Definition: pointIOField.H:42
defineTypeNameAndDebug(combustionModel, 0)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
IOList< label > labelIOList
Label container classes.
Definition: labelIOList.H:42
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
error FatalError
static const char nl
Definition: Ostream.H:267
word meshPath
Definition: setMeshPath.H:1