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-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "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().disconnect(false, false);
859 
860  completeMesh_->stitcher().connect(false, false, true);
861  }
862 }
863 
864 
866 (
867  const fvMesh::readUpdateState stat
868 )
869 {
870  if (completeMesh_->stitcher().stitches() && stat != fvMesh::UNCHANGED)
871  {
872  forAll(procMeshes_, proci)
873  {
874  procMeshes_[proci].conform();
875  }
876 
877  unconform();
878  }
879 }
880 
881 
883 (
884  const bool doPost
885 )
886 {
887  const fvMesh::readUpdateState stat = readUpdate();
888 
889  // Topology changes
890  {
891  const label facesCompare =
892  compareInstances
893  (
894  completeMesh().facesInstance(),
895  procMeshes_[0].facesInstance()
896  );
897 
898  // The complete mesh should not have newer topology when reconstructing
899  if (facesCompare == -1)
900  {
902  << "Cannot reconstruct at time "
903  << completeMesh().facesInstance()
904  << " because the complete mesh topology has evolved further"
905  << " than the processor mesh topology." << exit(FatalError);
906  }
907 
908  // If there has been matching topology change then reload the addressing
909  if (facesCompare == 0 && stat >= fvMesh::TOPO_CHANGE)
910  {
911  readAddressing();
912  }
913 
914  // If the processor meshes have newer topology then we need to
915  // reconstruct
916  if (facesCompare == +1)
917  {
918  reconstruct();
919  }
920  }
921 
922  // Geometry changes
923  {
924  const label pointsCompare =
925  compareInstances
926  (
927  completeMesh().pointsInstance(),
928  procMeshes_[0].pointsInstance()
929  );
930 
931  // The complete mesh should not have newer geometry when reconstructing
932  if (pointsCompare == -1)
933  {
935  << "Cannot reconstruct at time "
936  << completeMesh().pointsInstance()
937  << " because the complete mesh geometry has evolved further"
938  << " than the processor mesh geometry." << exit(FatalError);
939  }
940 
941  // If the processor meshes have newer geometry then we need to
942  // reconstruct the points
943  if (pointsCompare == +1)
944  {
945  reconstructPoints();
946  }
947  }
948 
949  if (doPost)
950  {
951  postReadUpdateReconstruct(stat);
952  unconformReadUpdateReconstruct(stat);
953  }
954 
955  return stat;
956 }
957 
958 
960 (
961  const fvMesh::readUpdateState stat
962 )
963 {
964  if (completeMesh_->stitcher().stitches() && stat != fvMesh::UNCHANGED)
965  {
966  procFaceAddressingBf_.clear();
967 
968  forAll(procMeshes_, proci)
969  {
970  procMeshes_[proci].stitcher().disconnect(false, false);
971 
972  procMeshes_[proci].stitcher().connect(false, false, true);
973  }
974  }
975 }
976 
977 
979 (
980  const fvMesh::readUpdateState stat
981 )
982 {
983  if (completeMesh_->stitcher().stitches() && stat != fvMesh::UNCHANGED)
984  {
985  completeMesh_->conform();
986 
987  unconform();
988  }
989 }
990 
991 
994 {
995  validateComplete();
996  validateProcs();
997 
998  if (procFaceAddressingBf_.empty())
999  {
1000  // Get any non-conformal proc-face addressing
1001  List<List<DynamicList<label>>> nonConformalProcFaceAddressingBf =
1002  this->nonConformalProcFaceAddressingBf();
1003 
1004  // Build finite volume face addressing boundary fields
1005  procFaceAddressingBf_.resize(nProcs());
1006  forAll(procMeshes_, proci)
1007  {
1008  const fvMesh& procMesh = procMeshes_[proci];
1009 
1010  procFaceAddressingBf_.set
1011  (
1012  proci,
1014  (
1015  procMesh.boundary(),
1018  )
1019  );
1020 
1021  forAll(procMesh.boundary(), procPatchi)
1022  {
1023  const fvPatch& fvp = procMesh.boundary()[procPatchi];
1024 
1025  if (isA<nonConformalFvPatch>(fvp))
1026  {
1027  procFaceAddressingBf_[proci][procPatchi] =
1028  nonConformalProcFaceAddressingBf[proci][procPatchi];
1029  }
1030  else if (isA<processorCyclicFvPatch>(fvp))
1031  {
1032  const label completePatchi =
1033  refCast<const processorCyclicFvPatch>(fvp)
1034  .referPatchIndex();
1035 
1036  procFaceAddressingBf_[proci][procPatchi] =
1037  mag(fvp.patchSlice(procFaceAddressing_[proci]))
1038  - completeMesh().poly().boundary()[completePatchi]
1039  .start();
1040  }
1041  else if (isA<processorFvPatch>(fvp))
1042  {
1043  procFaceAddressingBf_[proci][procPatchi] =
1044  fvp.patchSlice(procFaceAddressing_[proci]);
1045  }
1046  else
1047  {
1048  procFaceAddressingBf_[proci][procPatchi] =
1049  mag(fvp.patchSlice(procFaceAddressing_[proci]))
1050  - completeMesh().poly().boundary()[procPatchi].start();
1051  }
1052  }
1053  }
1054  }
1055 
1056  return procFaceAddressingBf_;
1057 }
1058 
1059 
1060 void Foam::domainDecomposition::writeComplete(const bool doSets) const
1061 {
1062  const bool topologyWrite =
1063  static_cast<const faceCompactIOList&>(completeMesh().faces())
1064  .writeOpt() == IOobject::AUTO_WRITE;
1065 
1066  // Ensure the points are written to a sufficient precision
1068 
1069  // Write the complete mesh
1070  completeMesh().write();
1071 
1072  // Everything written below is topological data, so quit here if not
1073  // writing topology
1074  if (!topologyWrite) return;
1075 
1076  // Read, reconstruct and write sets
1077  if (doSets)
1078  {
1079  const IOobjectList proc0SetObjects
1080  (
1081  procMeshes_[0],
1082  runTimes_.procTimes()[0].name(),
1083  polyMesh::meshSubDir/"sets"
1084  );
1085 
1086  const IOobjectList proc0CellSetObjects
1087  (
1088  proc0SetObjects.lookupClass(cellSet::typeName)
1089  );
1090  const IOobjectList proc0FaceSetObjects
1091  (
1092  proc0SetObjects.lookupClass(faceSet::typeName)
1093  );
1094  const IOobjectList proc0PointSetObjects
1095  (
1096  proc0SetObjects.lookupClass(pointSet::typeName)
1097  );
1098 
1099  forAllConstIter(IOobjectList, proc0FaceSetObjects, iter)
1100  {
1101  reconstructSet<faceSet>(iter.key())->write();
1102  }
1103  forAllConstIter(IOobjectList, proc0CellSetObjects, iter)
1104  {
1105  reconstructSet<cellSet>(iter.key())->write();
1106  }
1107  forAllConstIter(IOobjectList, proc0PointSetObjects, iter)
1108  {
1109  reconstructSet<pointSet>(iter.key())->write();
1110  }
1111  }
1112 
1113  // Read, decompose, and write refinement data (if any)
1114  UPtrList<const labelList> cellMaps(nProcs());
1115  UPtrList<const labelList> pointMaps(nProcs());
1116  PtrList<const hexRef8Data> refinementDatas(nProcs());
1117  for (label proci = 0; proci < nProcs(); proci++)
1118  {
1119  const fvMesh& procMesh = procMeshes_[proci];
1120 
1121  cellMaps.set(proci, &procCellAddressing_[proci]);
1122  pointMaps.set(proci, &procPointAddressing_[proci]);
1123  refinementDatas.set
1124  (
1125  proci,
1126  new hexRef8Data
1127  (
1128  IOobject
1129  (
1130  "dummy",
1131  completeMesh().facesInstance(),
1133  procMesh,
1136  false
1137  )
1138  )
1139  );
1140  }
1141  hexRef8Data
1142  (
1143  IOobject
1144  (
1145  "dummy",
1146  completeMesh().facesInstance(),
1148  completeMesh(),
1151  false
1152  ),
1153  cellMaps,
1154  pointMaps,
1155  refinementDatas
1156  ).write();
1157 
1158  // Write decomposition addressing
1159  writeAddressing();
1160 }
1161 
1162 
1163 void Foam::domainDecomposition::writeProcs(const bool doSets) const
1164 {
1165  const bool topologyWrite =
1166  static_cast<const faceCompactIOList&>(procMeshes()[0].faces())
1167  .writeOpt() == IOobject::AUTO_WRITE;
1168 
1169  // Write out the meshes
1170  for (label proci = 0; proci < nProcs(); proci++)
1171  {
1172  const fvMesh& procMesh = procMeshes_[proci];
1173 
1174  // Ensure the points are written to a sufficient precision
1176 
1177  // Write the processor mesh
1178  procMesh.write();
1179  }
1180 
1181  // Everything written below is topological data, so quit here if not
1182  // writing topology
1183  if (!topologyWrite) return;
1184 
1185  // Read, decompose, and write any sets
1186  if (doSets)
1187  {
1188  const IOobjectList setObjects
1189  (
1190  completeMesh(),
1191  completeMesh().facesInstance(),
1192  polyMesh::meshSubDir/"sets"
1193  );
1194 
1195  const IOobjectList cellSetObjects
1196  (
1197  setObjects.lookupClass(cellSet::typeName)
1198  );
1199  const IOobjectList faceSetObjects
1200  (
1201  setObjects.lookupClass(faceSet::typeName)
1202  );
1203  const IOobjectList pointSetObjects
1204  (
1205  setObjects.lookupClass(pointSet::typeName)
1206  );
1207 
1208  forAllConstIter(IOobjectList, cellSetObjects, iter)
1209  {
1210  PtrList<cellSet> procCellSets =
1211  decomposeSet<cellSet>(iter.key());
1212  forAll(procCellSets, proci)
1213  {
1214  procCellSets[proci].write();
1215  }
1216  }
1217  forAllConstIter(IOobjectList, faceSetObjects, iter)
1218  {
1219  PtrList<faceSet> procFaceSets =
1220  decomposeSet<faceSet>(iter.key());
1221  forAll(procFaceSets, proci)
1222  {
1223  procFaceSets[proci].write();
1224  }
1225  }
1226  forAllConstIter(IOobjectList, pointSetObjects, iter)
1227  {
1228  PtrList<pointSet> procPointSets =
1229  decomposeSet<pointSet>(iter.key());
1230  forAll(procPointSets, proci)
1231  {
1232  procPointSets[proci].write();
1233  }
1234  }
1235  }
1236 
1237  // Read, decompose, and write refinement data (if any)
1239  (
1240  IOobject
1241  (
1242  "dummy",
1243  completeMesh().facesInstance(),
1245  completeMesh(),
1248  false
1249  )
1250  );
1251  for (label proci = 0; proci < nProcs(); proci++)
1252  {
1253  const fvMesh& procMesh = procMeshes_[proci];
1254 
1255  hexRef8Data
1256  (
1257  IOobject
1258  (
1259  "dummy",
1260  completeMesh().facesInstance(),
1262  procMesh,
1265  false
1266  ),
1268  procCellAddressing_[proci],
1269  procPointAddressing_[proci]
1270  ).write();
1271  }
1272 
1273  // Write decomposition addressing
1274  writeAddressing();
1275 }
1276 
1277 
1278 template<class SetType>
1280 (
1281  const word& name
1282 ) const
1283 {
1284  PtrList<SetType> result(nProcs());
1285 
1286  const SetType completeSet(completeMesh_, name);
1287 
1288  for (label proci = 0; proci < nProcs(); proci++)
1289  {
1290  const fvMesh& procMesh = procMeshes_[proci];
1291 
1292  result.set
1293  (
1294  proci,
1295  new SetType(procMesh, name, completeSet.size()/nProcs())
1296  );
1297 
1298  for (label i = 0; i < result[proci].maxSize(procMesh); ++ i)
1299  {
1300  if (completeSet.found(setIndex<SetType>(proci, i)))
1301  {
1302  result[proci].insert(i);
1303  }
1304  }
1305  }
1306 
1307  return result;
1308 }
1309 
1310 
1311 template
1313 Foam::domainDecomposition::decomposeSet<Foam::cellSet>
1314 (
1315  const word& name
1316 ) const;
1317 
1318 
1319 template
1321 Foam::domainDecomposition::decomposeSet<Foam::faceSet>
1322 (
1323  const word& name
1324 ) const;
1325 
1326 
1327 template
1329 Foam::domainDecomposition::decomposeSet<Foam::pointSet>
1330 (
1331  const word& name
1332 ) const;
1333 
1334 
1335 template<class SetType>
1337 (
1338  const word& name
1339 ) const
1340 {
1341  autoPtr<SetType> result(new SetType(completeMesh_, name, 128));
1342 
1343  for (label proci = 0; proci < nProcs(); proci++)
1344  {
1345  const fvMesh& procMesh = procMeshes_[proci];
1346 
1347  const SetType procSet(procMesh, name, IOobject::READ_IF_PRESENT);
1348 
1349  forAllConstIter(typename SetType, procSet, iter)
1350  {
1351  result().insert(setIndex<SetType>(proci, iter.key()));
1352  }
1353  }
1354 
1355  return result;
1356 }
1357 
1358 
1359 template
1361 Foam::domainDecomposition::reconstructSet<Foam::cellSet>
1362 (
1363  const word& name
1364 ) const;
1365 
1366 
1367 template
1369 Foam::domainDecomposition::reconstructSet<Foam::faceSet>
1370 (
1371  const word& name
1372 ) const;
1373 
1374 
1375 template
1377 Foam::domainDecomposition::reconstructSet<Foam::pointSet>
1378 (
1379  const word& name
1380 ) const;
1381 
1382 
1383 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:492
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
static unsigned int highPrecision()
Return a high precision for writing data that is.
Definition: IOstream.C:90
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:61
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
Engine for decomposing and reconstructing 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:98
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:932
readUpdateState
Enumeration defining the state of the mesh after a read update.
Definition: fvMesh.H:107
@ TOPO_CHANGE
Definition: fvMesh.H:111
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:58
const List< T >::subList patchSlice(const List< T > &l) const
Slice list to patch.
Definition: fvPatch.H:187
Various for reading/decomposing/reconstructing/distributing refinement data.
Definition: hexRef8Data.H:58
bool write() const
Write.
Definition: hexRef8Data.C:372
Engine for decomposing and reconstructing multi-region systems of finite-volume meshes.
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:263
const Time & completeTime() const
Access the complete run time.
Transfers refinement levels such that slow transition between levels is maintained....
virtual bool write(const bool write=true) const
Write using setting from DB.
Templated form of IOobject providing type information for file reading and header type checking.
Definition: IOobject.H:545
bool headerOk()
Read header (uses typeGlobalFile to find file) and check.
A class for handling words, derived from string.
Definition: word.H:63
#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:288
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
const word & regionName(const solver &region)
Definition: solver.H:218
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
vectorIOField pointIOField
pointIOField is a vectorIOField.
Definition: pointIOField.H:42
IOList< label > labelIOList
Label container classes.
Definition: labelIOList.H:42
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
error FatalError
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
static const char nl
Definition: Ostream.H:297
word meshPath
Definition: setMeshPath.H:1