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(),
1017  calculatedFvsPatchLabelField::typeName
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().boundaryMesh()[completePatchi].start();
1039  }
1040  else if (isA<processorFvPatch>(fvp))
1041  {
1042  procFaceAddressingBf_[proci][procPatchi] =
1043  fvp.patchSlice(procFaceAddressing_[proci]);
1044  }
1045  else
1046  {
1047  procFaceAddressingBf_[proci][procPatchi] =
1048  mag(fvp.patchSlice(procFaceAddressing_[proci]))
1049  - completeMesh().boundaryMesh()[procPatchi].start();
1050  }
1051  }
1052  }
1053  }
1054 
1055  return procFaceAddressingBf_;
1056 }
1057 
1058 
1059 void Foam::domainDecomposition::writeComplete(const bool doSets) const
1060 {
1061  const bool topologyWrite =
1062  static_cast<const faceCompactIOList&>(completeMesh().faces())
1063  .writeOpt() == IOobject::AUTO_WRITE;
1064 
1065  // Set the precision of the points data to be min 10
1067 
1068  // Write the complete mesh
1069  completeMesh().write();
1070 
1071  // Everything written below is topological data, so quit here if not
1072  // writing topology
1073  if (!topologyWrite) return;
1074 
1075  // Read, reconstruct and write sets
1076  if (doSets)
1077  {
1078  const IOobjectList proc0SetObjects
1079  (
1080  procMeshes_[0],
1081  runTimes_.procTimes()[0].name(),
1082  polyMesh::meshSubDir/"sets"
1083  );
1084 
1085  const IOobjectList proc0CellSetObjects
1086  (
1087  proc0SetObjects.lookupClass(cellSet::typeName)
1088  );
1089  const IOobjectList proc0FaceSetObjects
1090  (
1091  proc0SetObjects.lookupClass(faceSet::typeName)
1092  );
1093  const IOobjectList proc0PointSetObjects
1094  (
1095  proc0SetObjects.lookupClass(pointSet::typeName)
1096  );
1097 
1098  forAllConstIter(IOobjectList, proc0FaceSetObjects, iter)
1099  {
1100  reconstructSet<faceSet>(iter.key())->write();
1101  }
1102  forAllConstIter(IOobjectList, proc0CellSetObjects, iter)
1103  {
1104  reconstructSet<cellSet>(iter.key())->write();
1105  }
1106  forAllConstIter(IOobjectList, proc0PointSetObjects, iter)
1107  {
1108  reconstructSet<pointSet>(iter.key())->write();
1109  }
1110  }
1111 
1112  // Read, decompose, and write refinement data (if any)
1113  UPtrList<const labelList> cellMaps(nProcs());
1114  UPtrList<const labelList> pointMaps(nProcs());
1115  PtrList<const hexRef8Data> refinementDatas(nProcs());
1116  for (label proci = 0; proci < nProcs(); proci++)
1117  {
1118  const fvMesh& procMesh = procMeshes_[proci];
1119 
1120  cellMaps.set(proci, &procCellAddressing_[proci]);
1121  pointMaps.set(proci, &procPointAddressing_[proci]);
1122  refinementDatas.set
1123  (
1124  proci,
1125  new hexRef8Data
1126  (
1127  IOobject
1128  (
1129  "dummy",
1130  completeMesh().facesInstance(),
1132  procMesh,
1135  false
1136  )
1137  )
1138  );
1139  }
1140  hexRef8Data
1141  (
1142  IOobject
1143  (
1144  "dummy",
1145  completeMesh().facesInstance(),
1147  completeMesh(),
1150  false
1151  ),
1152  cellMaps,
1153  pointMaps,
1154  refinementDatas
1155  ).write();
1156 
1157  // Write decomposition addressing
1158  writeAddressing();
1159 }
1160 
1161 
1162 void Foam::domainDecomposition::writeProcs(const bool doSets) const
1163 {
1164  const bool topologyWrite =
1165  static_cast<const faceCompactIOList&>(procMeshes()[0].faces())
1166  .writeOpt() == IOobject::AUTO_WRITE;
1167 
1168  // Write out the meshes
1169  for (label proci = 0; proci < nProcs(); proci++)
1170  {
1171  const fvMesh& procMesh = procMeshes_[proci];
1172 
1173  // Set the precision of the points data to be min 10
1175 
1176  // Write the processor mesh
1177  procMesh.write();
1178  }
1179 
1180  // Everything written below is topological data, so quit here if not
1181  // writing topology
1182  if (!topologyWrite) return;
1183 
1184  // Read, decompose, and write any sets
1185  if (doSets)
1186  {
1187  const IOobjectList setObjects
1188  (
1189  completeMesh(),
1190  completeMesh().facesInstance(),
1191  polyMesh::meshSubDir/"sets"
1192  );
1193 
1194  const IOobjectList cellSetObjects
1195  (
1196  setObjects.lookupClass(cellSet::typeName)
1197  );
1198  const IOobjectList faceSetObjects
1199  (
1200  setObjects.lookupClass(faceSet::typeName)
1201  );
1202  const IOobjectList pointSetObjects
1203  (
1204  setObjects.lookupClass(pointSet::typeName)
1205  );
1206 
1207  forAllConstIter(IOobjectList, cellSetObjects, iter)
1208  {
1209  PtrList<cellSet> procCellSets =
1210  decomposeSet<cellSet>(iter.key());
1211  forAll(procCellSets, proci)
1212  {
1213  procCellSets[proci].write();
1214  }
1215  }
1216  forAllConstIter(IOobjectList, faceSetObjects, iter)
1217  {
1218  PtrList<faceSet> procFaceSets =
1219  decomposeSet<faceSet>(iter.key());
1220  forAll(procFaceSets, proci)
1221  {
1222  procFaceSets[proci].write();
1223  }
1224  }
1225  forAllConstIter(IOobjectList, pointSetObjects, iter)
1226  {
1227  PtrList<pointSet> procPointSets =
1228  decomposeSet<pointSet>(iter.key());
1229  forAll(procPointSets, proci)
1230  {
1231  procPointSets[proci].write();
1232  }
1233  }
1234  }
1235 
1236  // Read, decompose, and write refinement data (if any)
1238  (
1239  IOobject
1240  (
1241  "dummy",
1242  completeMesh().facesInstance(),
1244  completeMesh(),
1247  false
1248  )
1249  );
1250  for (label proci = 0; proci < nProcs(); proci++)
1251  {
1252  const fvMesh& procMesh = procMeshes_[proci];
1253 
1254  hexRef8Data
1255  (
1256  IOobject
1257  (
1258  "dummy",
1259  completeMesh().facesInstance(),
1261  procMesh,
1264  false
1265  ),
1267  procCellAddressing_[proci],
1268  procPointAddressing_[proci]
1269  ).write();
1270  }
1271 
1272  // Write decomposition addressing
1273  writeAddressing();
1274 }
1275 
1276 
1277 template<class SetType>
1279 (
1280  const word& name
1281 ) const
1282 {
1283  PtrList<SetType> result(nProcs());
1284 
1285  const SetType completeSet(completeMesh_, name);
1286 
1287  for (label proci = 0; proci < nProcs(); proci++)
1288  {
1289  const fvMesh& procMesh = procMeshes_[proci];
1290 
1291  result.set
1292  (
1293  proci,
1294  new SetType(procMesh, name, completeSet.size()/nProcs())
1295  );
1296 
1297  for (label i = 0; i < result[proci].maxSize(procMesh); ++ i)
1298  {
1299  if (completeSet.found(setIndex<SetType>(proci, i)))
1300  {
1301  result[proci].insert(i);
1302  }
1303  }
1304  }
1305 
1306  return result;
1307 }
1308 
1309 
1310 template
1312 Foam::domainDecomposition::decomposeSet<Foam::cellSet>
1313 (
1314  const word& name
1315 ) const;
1316 
1317 
1318 template
1320 Foam::domainDecomposition::decomposeSet<Foam::faceSet>
1321 (
1322  const word& name
1323 ) const;
1324 
1325 
1326 template
1328 Foam::domainDecomposition::decomposeSet<Foam::pointSet>
1329 (
1330  const word& name
1331 ) const;
1332 
1333 
1334 template<class SetType>
1336 (
1337  const word& name
1338 ) const
1339 {
1340  autoPtr<SetType> result(new SetType(completeMesh_, name, 128));
1341 
1342  for (label proci = 0; proci < nProcs(); proci++)
1343  {
1344  const fvMesh& procMesh = procMeshes_[proci];
1345 
1346  const SetType procSet(procMesh, name, IOobject::READ_IF_PRESENT);
1347 
1348  forAllConstIter(typename SetType, procSet, iter)
1349  {
1350  result().insert(setIndex<SetType>(proci, iter.key()));
1351  }
1352  }
1353 
1354  return result;
1355 }
1356 
1357 
1358 template
1360 Foam::domainDecomposition::reconstructSet<Foam::cellSet>
1361 (
1362  const word& name
1363 ) const;
1364 
1365 
1366 template
1368 Foam::domainDecomposition::reconstructSet<Foam::faceSet>
1369 (
1370  const word& name
1371 ) const;
1372 
1373 
1374 template
1376 Foam::domainDecomposition::reconstructSet<Foam::pointSet>
1377 (
1378  const word& name
1379 ) const;
1380 
1381 
1382 // ************************************************************************* //
#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:957
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:1780
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:254
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