decompositionMethod.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-2019 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 InClass
25  decompositionMethod
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "decompositionMethod.H"
30 #include "globalIndex.H"
31 #include "syncTools.H"
32 #include "Tuple2.H"
33 #include "faceSet.H"
34 #include "regionSplit.H"
35 #include "localPointRegion.H"
36 #include "minData.H"
37 #include "FaceCellWave.H"
38 
43 
44 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45 
46 namespace Foam
47 {
48  defineTypeNameAndDebug(decompositionMethod, 0);
49  defineRunTimeSelectionTable(decompositionMethod, dictionary);
50 }
51 
52 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
53 
55 (
56  const dictionary& decompositionDict
57 )
58 :
59  decompositionDict_(decompositionDict),
60  nProcessors_
61  (
62  readLabel(decompositionDict.lookup("numberOfSubdomains"))
63  )
64 {
65  // Read any constraints
66  wordList constraintTypes_;
67  if (decompositionDict_.found("constraints"))
68  {
69  // PtrList<dictionary> constraintsList
70  //(
71  // decompositionDict_.lookup("constraints")
72  //);
73  // forAll(constraintsList, i)
74  //{
75  // const dictionary& dict = constraintsList[i];
76  const dictionary& constraintsList = decompositionDict_.subDict
77  (
78  "constraints"
79  );
80  forAllConstIter(dictionary, constraintsList, iter)
81  {
82  const dictionary& dict = iter().dict();
83 
84  constraintTypes_.append(dict.lookup("type"));
85 
86  constraints_.append
87  (
89  (
90  dict,
91  constraintTypes_.last()
92  )
93  );
94  }
95  }
96 
97  // Backwards compatibility
98  if
99  (
100  decompositionDict_.found("preserveBaffles")
101  && findIndex
102  (
103  constraintTypes_,
104  decompositionConstraints::preserveBafflesConstraint::typeName
105  ) == -1
106  )
107  {
108  constraints_.append
109  (
111  );
112  }
113 
114  if
115  (
116  decompositionDict_.found("preservePatches")
117  && findIndex
118  (
119  constraintTypes_,
120  decompositionConstraints::preservePatchesConstraint::typeName
121  ) == -1
122  )
123  {
124  const wordReList pNames(decompositionDict_.lookup("preservePatches"));
125 
126  constraints_.append
127  (
129  );
130  }
131 
132  if
133  (
134  decompositionDict_.found("preserveFaceZones")
135  && findIndex
136  (
137  constraintTypes_,
138  decompositionConstraints::preserveFaceZonesConstraint::typeName
139  ) == -1
140  )
141  {
142  const wordReList zNames(decompositionDict_.lookup("preserveFaceZones"));
143 
144  constraints_.append
145  (
147  );
148  }
149 
150  if
151  (
152  decompositionDict_.found("singleProcessorFaceSets")
153  && findIndex
154  (
155  constraintTypes_,
156  decompositionConstraints::preserveFaceZonesConstraint::typeName
157  ) == -1
158  )
159  {
160  const List<Tuple2<word, label>> zNameAndProcs
161  (
162  decompositionDict_.lookup("singleProcessorFaceSets")
163  );
164 
165  constraints_.append
166  (
168  (
169  zNameAndProcs
170  )
171  );
172  }
173 }
174 
175 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
176 
178 (
179  const dictionary& decompositionDict
180 )
181 {
182  Pout << " Foam::decompositionMethod::New " << decompositionDict << endl;
183 
184  const word methodType(decompositionDict.lookup("method"));
185 
186  Pout<< "Selecting decompositionMethod " << methodType << endl;
187 
188  dictionaryConstructorTable::iterator cstrIter =
189  dictionaryConstructorTablePtr_->find(methodType);
190 
191  if (cstrIter == dictionaryConstructorTablePtr_->end())
192  {
194  << "Unknown decompositionMethod "
195  << methodType << nl << nl
196  << "Valid decompositionMethods are : " << endl
197  << dictionaryConstructorTablePtr_->sortedToc()
198  << exit(FatalError);
199  }
200 
201  return autoPtr<decompositionMethod>(cstrIter()(decompositionDict));
202 }
203 
204 
206 (
207  const polyMesh& mesh,
208  const pointField& points
209 )
210 {
211  scalarField weights(points.size(), 1.0);
212 
213  return decompose(mesh, points, weights);
214 }
215 
216 
218 (
219  const polyMesh& mesh,
220  const labelList& fineToCoarse,
221  const pointField& coarsePoints,
222  const scalarField& coarseWeights
223 )
224 {
225  CompactListList<label> coarseCellCells;
226  calcCellCells
227  (
228  mesh,
229  fineToCoarse,
230  coarsePoints.size(),
231  true, // use global cell labels
232  coarseCellCells
233  );
234 
235  // Decompose based on agglomerated points
236  labelList coarseDistribution
237  (
238  decompose
239  (
240  coarseCellCells(),
241  coarsePoints,
242  coarseWeights
243  )
244  );
245 
246  // Rework back into decomposition for original mesh_
247  labelList fineDistribution(fineToCoarse.size());
248 
249  forAll(fineDistribution, i)
250  {
251  fineDistribution[i] = coarseDistribution[fineToCoarse[i]];
252  }
253 
254  return fineDistribution;
255 }
256 
257 
259 (
260  const polyMesh& mesh,
261  const labelList& fineToCoarse,
262  const pointField& coarsePoints
263 )
264 {
265  scalarField cWeights(coarsePoints.size(), 1.0);
266 
267  return decompose
268  (
269  mesh,
270  fineToCoarse,
271  coarsePoints,
272  cWeights
273  );
274 }
275 
276 
278 (
279  const labelListList& globalCellCells,
280  const pointField& cc
281 )
282 {
283  scalarField cWeights(cc.size(), 1.0);
284 
285  return decompose(globalCellCells, cc, cWeights);
286 }
287 
288 
290 (
291  const polyMesh& mesh,
292  const labelList& agglom,
293  const label nLocalCoarse,
294  const bool parallel,
295  CompactListList<label>& cellCells
296 )
297 {
298  const labelList& faceOwner = mesh.faceOwner();
299  const labelList& faceNeighbour = mesh.faceNeighbour();
300  const polyBoundaryMesh& patches = mesh.boundaryMesh();
301 
302 
303  // Create global cell numbers
304  // ~~~~~~~~~~~~~~~~~~~~~~~~~~
305 
306  globalIndex globalAgglom
307  (
308  nLocalCoarse,
311  parallel
312  );
313 
314 
315  // Get agglomerate owner on other side of coupled faces
316  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
317 
318  labelList globalNeighbour(mesh.nFaces()-mesh.nInternalFaces());
319 
320  forAll(patches, patchi)
321  {
322  const polyPatch& pp = patches[patchi];
323 
324  if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
325  {
326  label facei = pp.start();
327  label bFacei = pp.start() - mesh.nInternalFaces();
328 
329  forAll(pp, i)
330  {
331  globalNeighbour[bFacei] = globalAgglom.toGlobal
332  (
333  agglom[faceOwner[facei]]
334  );
335 
336  bFacei++;
337  facei++;
338  }
339  }
340  }
341 
342  // Get the cell on the other side of coupled patches
343  syncTools::swapBoundaryFaceList(mesh, globalNeighbour);
344 
345 
346  // Count number of faces (internal + coupled)
347  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
348 
349  // Number of faces per coarse cell
350  labelList nFacesPerCell(nLocalCoarse, 0);
351 
352  for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
353  {
354  label own = agglom[faceOwner[facei]];
355  label nei = agglom[faceNeighbour[facei]];
356 
357  nFacesPerCell[own]++;
358  nFacesPerCell[nei]++;
359  }
360 
361  forAll(patches, patchi)
362  {
363  const polyPatch& pp = patches[patchi];
364 
365  if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
366  {
367  label facei = pp.start();
368  label bFacei = pp.start()-mesh.nInternalFaces();
369 
370  forAll(pp, i)
371  {
372  label own = agglom[faceOwner[facei]];
373 
374  label globalNei = globalNeighbour[bFacei];
375  if
376  (
377  !globalAgglom.isLocal(globalNei)
378  || globalAgglom.toLocal(globalNei) != own
379  )
380  {
381  nFacesPerCell[own]++;
382  }
383 
384  facei++;
385  bFacei++;
386  }
387  }
388  }
389 
390 
391  // Fill in offset and data
392  // ~~~~~~~~~~~~~~~~~~~~~~~
393 
394  cellCells.setSize(nFacesPerCell);
395 
396  nFacesPerCell = 0;
397 
398  labelList& m = cellCells.m();
399  const labelList& offsets = cellCells.offsets();
400 
401  // For internal faces is just offsetted owner and neighbour
402  for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
403  {
404  label own = agglom[faceOwner[facei]];
405  label nei = agglom[faceNeighbour[facei]];
406 
407  m[offsets[own] + nFacesPerCell[own]++] = globalAgglom.toGlobal(nei);
408  m[offsets[nei] + nFacesPerCell[nei]++] = globalAgglom.toGlobal(own);
409  }
410 
411  // For boundary faces is offsetted coupled neighbour
412  forAll(patches, patchi)
413  {
414  const polyPatch& pp = patches[patchi];
415 
416  if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
417  {
418  label facei = pp.start();
419  label bFacei = pp.start()-mesh.nInternalFaces();
420 
421  forAll(pp, i)
422  {
423  label own = agglom[faceOwner[facei]];
424 
425  label globalNei = globalNeighbour[bFacei];
426 
427  if
428  (
429  !globalAgglom.isLocal(globalNei)
430  || globalAgglom.toLocal(globalNei) != own
431  )
432  {
433  m[offsets[own] + nFacesPerCell[own]++] = globalNei;
434  }
435 
436  facei++;
437  bFacei++;
438  }
439  }
440  }
441 
442 
443  // Check for duplicates connections between cells
444  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
445  // Done as postprocessing step since we now have cellCells.
446  label newIndex = 0;
447  labelHashSet nbrCells;
448 
449 
450  if (cellCells.size() == 0)
451  {
452  return;
453  }
454 
455  label startIndex = cellCells.offsets()[0];
456 
457  forAll(cellCells, celli)
458  {
459  nbrCells.clear();
460  nbrCells.insert(globalAgglom.toGlobal(celli));
461 
462  label endIndex = cellCells.offsets()[celli+1];
463 
464  for (label i = startIndex; i < endIndex; i++)
465  {
466  if (nbrCells.insert(cellCells.m()[i]))
467  {
468  cellCells.m()[newIndex++] = cellCells.m()[i];
469  }
470  }
471  startIndex = endIndex;
472  cellCells.offsets()[celli+1] = newIndex;
473  }
474 
475  cellCells.m().setSize(newIndex);
476 
477  // forAll(cellCells, celli)
478  //{
479  // Pout<< "Original: Coarse cell " << celli << endl;
480  // forAll(mesh.cellCells()[celli], i)
481  // {
482  // Pout<< " nbr:" << mesh.cellCells()[celli][i] << endl;
483  // }
484  // Pout<< "Compacted: Coarse cell " << celli << endl;
485  // const labelUList cCells = cellCells[celli];
486  // forAll(cCells, i)
487  // {
488  // Pout<< " nbr:" << cCells[i] << endl;
489  // }
490  //}
491 }
492 
493 
495 (
496  const polyMesh& mesh,
497  const labelList& agglom,
498  const label nLocalCoarse,
499  const bool parallel,
500  CompactListList<label>& cellCells,
501  CompactListList<scalar>& cellCellWeights
502 )
503 {
504  const labelList& faceOwner = mesh.faceOwner();
505  const labelList& faceNeighbour = mesh.faceNeighbour();
506  const polyBoundaryMesh& patches = mesh.boundaryMesh();
507 
508 
509  // Create global cell numbers
510  // ~~~~~~~~~~~~~~~~~~~~~~~~~~
511 
512  globalIndex globalAgglom
513  (
514  nLocalCoarse,
517  parallel
518  );
519 
520 
521  // Get agglomerate owner on other side of coupled faces
522  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
523 
524  labelList globalNeighbour(mesh.nFaces()-mesh.nInternalFaces());
525 
526  forAll(patches, patchi)
527  {
528  const polyPatch& pp = patches[patchi];
529 
530  if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
531  {
532  label faceI = pp.start();
533  label bFaceI = pp.start() - mesh.nInternalFaces();
534 
535  forAll(pp, i)
536  {
537  globalNeighbour[bFaceI] = globalAgglom.toGlobal
538  (
539  agglom[faceOwner[faceI]]
540  );
541 
542  bFaceI++;
543  faceI++;
544  }
545  }
546  }
547 
548  // Get the cell on the other side of coupled patches
549  syncTools::swapBoundaryFaceList(mesh, globalNeighbour);
550 
551 
552  // Count number of faces (internal + coupled)
553  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
554 
555  // Number of faces per coarse cell
556  labelList nFacesPerCell(nLocalCoarse, 0);
557 
558  for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
559  {
560  label own = agglom[faceOwner[faceI]];
561  label nei = agglom[faceNeighbour[faceI]];
562 
563  nFacesPerCell[own]++;
564  nFacesPerCell[nei]++;
565  }
566 
567  forAll(patches, patchi)
568  {
569  const polyPatch& pp = patches[patchi];
570 
571  if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
572  {
573  label faceI = pp.start();
574  label bFaceI = pp.start()-mesh.nInternalFaces();
575 
576  forAll(pp, i)
577  {
578  label own = agglom[faceOwner[faceI]];
579 
580  label globalNei = globalNeighbour[bFaceI];
581  if
582  (
583  !globalAgglom.isLocal(globalNei)
584  || globalAgglom.toLocal(globalNei) != own
585  )
586  {
587  nFacesPerCell[own]++;
588  }
589 
590  faceI++;
591  bFaceI++;
592  }
593  }
594  }
595 
596 
597  // Fill in offset and data
598  // ~~~~~~~~~~~~~~~~~~~~~~~
599 
600  cellCells.setSize(nFacesPerCell);
601  cellCellWeights.setSize(nFacesPerCell);
602 
603  nFacesPerCell = 0;
604 
605  labelList& m = cellCells.m();
606  scalarList& w = cellCellWeights.m();
607  const labelList& offsets = cellCells.offsets();
608 
609  // For internal faces is just offsetted owner and neighbour
610  for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
611  {
612  label own = agglom[faceOwner[faceI]];
613  label nei = agglom[faceNeighbour[faceI]];
614 
615  label ownIndex = offsets[own] + nFacesPerCell[own]++;
616  label neiIndex = offsets[nei] + nFacesPerCell[nei]++;
617 
618  m[ownIndex] = globalAgglom.toGlobal(nei);
619  w[ownIndex] = mag(mesh.faceAreas()[faceI]);
620  m[neiIndex] = globalAgglom.toGlobal(own);
621  w[ownIndex] = mag(mesh.faceAreas()[faceI]);
622  }
623 
624  // For boundary faces is offsetted coupled neighbour
625  forAll(patches, patchi)
626  {
627  const polyPatch& pp = patches[patchi];
628 
629  if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
630  {
631  label faceI = pp.start();
632  label bFaceI = pp.start()-mesh.nInternalFaces();
633 
634  forAll(pp, i)
635  {
636  label own = agglom[faceOwner[faceI]];
637 
638  label globalNei = globalNeighbour[bFaceI];
639 
640  if
641  (
642  !globalAgglom.isLocal(globalNei)
643  || globalAgglom.toLocal(globalNei) != own
644  )
645  {
646  label ownIndex = offsets[own] + nFacesPerCell[own]++;
647  m[ownIndex] = globalNei;
648  w[ownIndex] = mag(mesh.faceAreas()[faceI]);
649  }
650 
651  faceI++;
652  bFaceI++;
653  }
654  }
655  }
656 
657 
658  // Check for duplicates connections between cells
659  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
660  // Done as postprocessing step since we now have cellCells.
661  label newIndex = 0;
662  labelHashSet nbrCells;
663 
664 
665  if (cellCells.size() == 0)
666  {
667  return;
668  }
669 
670  label startIndex = cellCells.offsets()[0];
671 
672  forAll(cellCells, cellI)
673  {
674  nbrCells.clear();
675  nbrCells.insert(globalAgglom.toGlobal(cellI));
676 
677  label endIndex = cellCells.offsets()[cellI+1];
678 
679  for (label i = startIndex; i < endIndex; i++)
680  {
681  if (nbrCells.insert(cellCells.m()[i]))
682  {
683  cellCells.m()[newIndex] = cellCells.m()[i];
684  cellCellWeights.m()[newIndex] = cellCellWeights.m()[i];
685  newIndex++;
686  }
687  }
688  startIndex = endIndex;
689  cellCells.offsets()[cellI+1] = newIndex;
690  cellCellWeights.offsets()[cellI+1] = newIndex;
691  }
692 
693  cellCells.m().setSize(newIndex);
694  cellCellWeights.m().setSize(newIndex);
695 }
696 
697 
698 //void Foam::decompositionMethod::calcCellCells
699 //(
700 // const polyMesh& mesh,
701 // const boolList& blockedFace,
702 // const List<labelPair>& explicitConnections,
703 // const labelList& agglom,
704 // const label nLocalCoarse,
705 // const bool parallel,
706 // CompactListList<label>& cellCells
707 //)
708 //{
709 // const labelList& faceOwner = mesh.faceOwner();
710 // const labelList& faceNeighbour = mesh.faceNeighbour();
711 // const polyBoundaryMesh& patches = mesh.boundaryMesh();
712 //
713 //
714 // // Create global cell numbers
715 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~
716 //
717 // globalIndex globalAgglom
718 // (
719 // nLocalCoarse,
720 // Pstream::msgType(),
721 // Pstream::worldComm,
722 // parallel
723 // );
724 //
725 //
726 // // Get agglomerate owner on other side of coupled faces
727 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
728 //
729 // labelList globalNeighbour(mesh.nFaces()-mesh.nInternalFaces());
730 //
731 // forAll(patches, patchi)
732 // {
733 // const polyPatch& pp = patches[patchi];
734 //
735 // if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
736 // {
737 // label facei = pp.start();
738 // label bFacei = pp.start() - mesh.nInternalFaces();
739 //
740 // forAll(pp, i)
741 // {
742 // globalNeighbour[bFacei] = globalAgglom.toGlobal
743 // (
744 // agglom[faceOwner[facei]]
745 // );
746 //
747 // bFacei++;
748 // facei++;
749 // }
750 // }
751 // }
752 //
753 // // Get the cell on the other side of coupled patches
754 // syncTools::swapBoundaryFaceList(mesh, globalNeighbour);
755 //
756 //
757 // // Count number of faces (internal + coupled)
758 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
759 //
760 // // Number of faces per coarse cell
761 // labelList nFacesPerCell(nLocalCoarse, 0);
762 //
763 // // 1. Internal faces
764 // for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
765 // {
766 // if (!blockedFace[facei])
767 // {
768 // label own = agglom[faceOwner[facei]];
769 // label nei = agglom[faceNeighbour[facei]];
770 //
771 // nFacesPerCell[own]++;
772 // nFacesPerCell[nei]++;
773 // }
774 // }
775 //
776 // // 2. Coupled faces
777 // forAll(patches, patchi)
778 // {
779 // const polyPatch& pp = patches[patchi];
780 //
781 // if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
782 // {
783 // label facei = pp.start();
784 // label bFacei = pp.start()-mesh.nInternalFaces();
785 //
786 // forAll(pp, i)
787 // {
788 // if (!blockedFace[facei])
789 // {
790 // label own = agglom[faceOwner[facei]];
791 //
792 // label globalNei = globalNeighbour[bFacei];
793 // if
794 // (
795 // !globalAgglom.isLocal(globalNei)
796 // || globalAgglom.toLocal(globalNei) != own
797 // )
798 // {
799 // nFacesPerCell[own]++;
800 // }
801 //
802 // facei++;
803 // bFacei++;
804 // }
805 // }
806 // }
807 // }
808 //
809 // // 3. Explicit connections between non-coupled boundary faces
810 // forAll(explicitConnections, i)
811 // {
812 // const labelPair& baffle = explicitConnections[i];
813 // label f0 = baffle.first();
814 // label f1 = baffle.second();
815 //
816 // if (!blockedFace[f0] && blockedFace[f1])
817 // {
818 // label f0Own = agglom[faceOwner[f0]];
819 // label f1Own = agglom[faceOwner[f1]];
820 //
821 // // Always count the connection between the two owner sides
822 // if (f0Own != f1Own)
823 // {
824 // nFacesPerCell[f0Own]++;
825 // nFacesPerCell[f1Own]++;
826 // }
827 //
828 // // Add any neighbour side connections
829 // if (mesh.isInternalFace(f0))
830 // {
831 // label f0Nei = agglom[faceNeighbour[f0]];
832 //
833 // if (mesh.isInternalFace(f1))
834 // {
835 // // Internal faces
836 // label f1Nei = agglom[faceNeighbour[f1]];
837 //
838 // if (f0Own != f1Nei)
839 // {
840 // nFacesPerCell[f0Own]++;
841 // nFacesPerCell[f1Nei]++;
842 // }
843 // if (f0Nei != f1Own)
844 // {
845 // nFacesPerCell[f0Nei]++;
846 // nFacesPerCell[f1Own]++;
847 // }
848 // if (f0Nei != f1Nei)
849 // {
850 // nFacesPerCell[f0Nei]++;
851 // nFacesPerCell[f1Nei]++;
852 // }
853 // }
854 // else
855 // {
856 // // f1 boundary face
857 // if (f0Nei != f1Own)
858 // {
859 // nFacesPerCell[f0Nei]++;
860 // nFacesPerCell[f1Own]++;
861 // }
862 // }
863 // }
864 // else
865 // {
866 // if (mesh.isInternalFace(f1))
867 // {
868 // label f1Nei = agglom[faceNeighbour[f1]];
869 // if (f0Own != f1Nei)
870 // {
871 // nFacesPerCell[f0Own]++;
872 // nFacesPerCell[f1Nei]++;
873 // }
874 // }
875 // }
876 // }
877 // }
878 //
879 //
880 // // Fill in offset and data
881 // // ~~~~~~~~~~~~~~~~~~~~~~~
882 //
883 // cellCells.setSize(nFacesPerCell);
884 //
885 // nFacesPerCell = 0;
886 //
887 // labelList& m = cellCells.m();
888 // const labelList& offsets = cellCells.offsets();
889 //
890 // // 1. For internal faces is just offsetted owner and neighbour
891 // for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
892 // {
893 // if (!blockedFace[facei])
894 // {
895 // label own = agglom[faceOwner[facei]];
896 // label nei = agglom[faceNeighbour[facei]];
897 //
898 // m[offsets[own] + nFacesPerCell[own]++] =
899 // globalAgglom.toGlobal(nei);
900 // m[offsets[nei] + nFacesPerCell[nei]++] =
901 // globalAgglom.toGlobal(own);
902 // }
903 // }
904 //
905 // // 2. For boundary faces is offsetted coupled neighbour
906 // forAll(patches, patchi)
907 // {
908 // const polyPatch& pp = patches[patchi];
909 //
910 // if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
911 // {
912 // label facei = pp.start();
913 // label bFacei = pp.start()-mesh.nInternalFaces();
914 //
915 // forAll(pp, i)
916 // {
917 // if (!blockedFace[facei])
918 // {
919 // label own = agglom[faceOwner[facei]];
920 //
921 // label globalNei = globalNeighbour[bFacei];
922 //
923 // if
924 // (
925 // !globalAgglom.isLocal(globalNei)
926 // || globalAgglom.toLocal(globalNei) != own
927 // )
928 // {
929 // m[offsets[own] + nFacesPerCell[own]++] = globalNei;
930 // }
931 //
932 // facei++;
933 // bFacei++;
934 // }
935 // }
936 // }
937 // }
938 //
939 // // 3. Explicit connections between non-coupled boundary faces
940 // forAll(explicitConnections, i)
941 // {
942 // const labelPair& baffle = explicitConnections[i];
943 // label f0 = baffle.first();
944 // label f1 = baffle.second();
945 //
946 // if (!blockedFace[f0] && blockedFace[f1])
947 // {
948 // label f0Own = agglom[faceOwner[f0]];
949 // label f1Own = agglom[faceOwner[f1]];
950 //
951 // // Always count the connection between the two owner sides
952 // if (f0Own != f1Own)
953 // {
954 // m[offsets[f0Own] + nFacesPerCell[f0Own]++] =
955 // globalAgglom.toGlobal(f1Own);
956 // m[offsets[f1Own] + nFacesPerCell[f1Own]++] =
957 // globalAgglom.toGlobal(f0Own);
958 // }
959 //
960 // // Add any neighbour side connections
961 // if (mesh.isInternalFace(f0))
962 // {
963 // label f0Nei = agglom[faceNeighbour[f0]];
964 //
965 // if (mesh.isInternalFace(f1))
966 // {
967 // // Internal faces
968 // label f1Nei = agglom[faceNeighbour[f1]];
969 //
970 // if (f0Own != f1Nei)
971 // {
972 // m[offsets[f0Own] + nFacesPerCell[f0Own]++] =
973 // globalAgglom.toGlobal(f1Nei);
974 // m[offsets[f1Nei] + nFacesPerCell[f1Nei]++] =
975 // globalAgglom.toGlobal(f1Nei);
976 // }
977 // if (f0Nei != f1Own)
978 // {
979 // m[offsets[f0Nei] + nFacesPerCell[f0Nei]++] =
980 // globalAgglom.toGlobal(f1Own);
981 // m[offsets[f1Own] + nFacesPerCell[f1Own]++] =
982 // globalAgglom.toGlobal(f0Nei);
983 // }
984 // if (f0Nei != f1Nei)
985 // {
986 // m[offsets[f0Nei] + nFacesPerCell[f0Nei]++] =
987 // globalAgglom.toGlobal(f1Nei);
988 // m[offsets[f1Nei] + nFacesPerCell[f1Nei]++] =
989 // globalAgglom.toGlobal(f0Nei);
990 // }
991 // }
992 // else
993 // {
994 // // f1 boundary face
995 // if (f0Nei != f1Own)
996 // {
997 // m[offsets[f0Nei] + nFacesPerCell[f0Nei]++] =
998 // globalAgglom.toGlobal(f1Own);
999 // m[offsets[f1Own] + nFacesPerCell[f1Own]++] =
1000 // globalAgglom.toGlobal(f0Nei);
1001 // }
1002 // }
1003 // }
1004 // else
1005 // {
1006 // if (mesh.isInternalFace(f1))
1007 // {
1008 // label f1Nei = agglom[faceNeighbour[f1]];
1009 // if (f0Own != f1Nei)
1010 // {
1011 // m[offsets[f0Own] + nFacesPerCell[f0Own]++] =
1012 // globalAgglom.toGlobal(f1Nei);
1013 // m[offsets[f1Nei] + nFacesPerCell[f1Nei]++] =
1014 // globalAgglom.toGlobal(f0Own);
1015 // }
1016 // }
1017 // }
1018 // }
1019 // }
1020 //
1021 //
1022 // // Check for duplicates connections between cells
1023 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1024 // // Done as postprocessing step since we now have cellCells.
1025 // label newIndex = 0;
1026 // labelHashSet nbrCells;
1027 //
1028 //
1029 // if (cellCells.size() == 0)
1030 // {
1031 // return;
1032 // }
1033 //
1034 // label startIndex = cellCells.offsets()[0];
1035 //
1036 // forAll(cellCells, celli)
1037 // {
1038 // nbrCells.clear();
1039 // nbrCells.insert(globalAgglom.toGlobal(celli));
1040 //
1041 // label endIndex = cellCells.offsets()[celli+1];
1042 //
1043 // for (label i = startIndex; i < endIndex; i++)
1044 // {
1045 // if (nbrCells.insert(cellCells.m()[i]))
1046 // {
1047 // cellCells.m()[newIndex++] = cellCells.m()[i];
1048 // }
1049 // }
1050 // startIndex = endIndex;
1051 // cellCells.offsets()[celli+1] = newIndex;
1052 // }
1053 //
1054 // cellCells.m().setSize(newIndex);
1055 //
1056 // // forAll(cellCells, celli)
1057 // //{
1058 // // Pout<< "Original: Coarse cell " << celli << endl;
1059 // // forAll(mesh.cellCells()[celli], i)
1060 // // {
1061 // // Pout<< " nbr:" << mesh.cellCells()[celli][i] << endl;
1062 // // }
1063 // // Pout<< "Compacted: Coarse cell " << celli << endl;
1064 // // const labelUList cCells = cellCells[celli];
1065 // // forAll(cCells, i)
1066 // // {
1067 // // Pout<< " nbr:" << cCells[i] << endl;
1068 // // }
1069 // //}
1070 //}
1071 
1072 
1075  const polyMesh& mesh,
1076  const scalarField& cellWeights,
1077 
1078  //- Whether owner and neighbour should be on same processor
1079  // (takes priority over explicitConnections)
1080  const boolList& blockedFace,
1081 
1082  //- Whether whole sets of faces (and point neighbours) need to be kept
1083  // on single processor
1084  const PtrList<labelList>& specifiedProcessorFaces,
1085  const labelList& specifiedProcessor,
1086 
1087  //- Additional connections between boundary faces
1088  const List<labelPair>& explicitConnections
1089 )
1090 {
1091  // Any weights specified?
1092  label nWeights = returnReduce(cellWeights.size(), sumOp<label>());
1093 
1094  if (nWeights > 0 && cellWeights.size() != mesh.nCells())
1095  {
1097  << "Number of weights " << cellWeights.size()
1098  << " differs from number of cells " << mesh.nCells()
1099  << exit(FatalError);
1100  }
1101 
1102 
1103  // Any processor sets?
1104  label nProcSets = 0;
1105  forAll(specifiedProcessorFaces, setI)
1106  {
1107  nProcSets += specifiedProcessorFaces[setI].size();
1108  }
1109  reduce(nProcSets, sumOp<label>());
1110 
1111  // Any non-mesh connections?
1112  label nConnections = returnReduce
1113  (
1114  explicitConnections.size(),
1115  sumOp<label>()
1116  );
1117 
1118  // Any faces not blocked?
1119  label nUnblocked = 0;
1120  forAll(blockedFace, facei)
1121  {
1122  if (!blockedFace[facei])
1123  {
1124  nUnblocked++;
1125  }
1126  }
1127  reduce(nUnblocked, sumOp<label>());
1128 
1129 
1130 
1131  // Either do decomposition on cell centres or on agglomeration
1132 
1133  labelList finalDecomp;
1134 
1135 
1136  if (nProcSets+nConnections+nUnblocked == 0)
1137  {
1138  // No constraints, possibly weights
1139 
1140  if (nWeights > 0)
1141  {
1142  finalDecomp = decompose
1143  (
1144  mesh,
1145  mesh.cellCentres(),
1146  cellWeights
1147  );
1148  }
1149  else
1150  {
1151  finalDecomp = decompose(mesh, mesh.cellCentres());
1152  }
1153  }
1154  else
1155  {
1156  if (debug)
1157  {
1158  Info<< "Constrained decomposition:" << endl
1159  << " faces with same owner and neighbour processor : "
1160  << nUnblocked << endl
1161  << " baffle faces with same owner processor : "
1162  << nConnections << endl
1163  << " faces all on same processor : "
1164  << nProcSets << endl << endl;
1165  }
1166 
1167  // Determine local regions, separated by blockedFaces
1168  regionSplit localRegion(mesh, blockedFace, explicitConnections, false);
1169 
1170 
1171  if (debug)
1172  {
1173  Info<< "Constrained decomposition:" << endl
1174  << " split into " << localRegion.nLocalRegions()
1175  << " regions."
1176  << endl;
1177  }
1178 
1179  // Determine region cell centres
1180  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1181 
1182  // This just takes the first cell in the region. Otherwise the problem
1183  // is with cyclics - if we'd average the region centre might be
1184  // somewhere in the middle of the domain which might not be anywhere
1185  // near any of the cells.
1186 
1187  pointField regionCentres(localRegion.nLocalRegions(), point::max);
1188 
1189  forAll(localRegion, celli)
1190  {
1191  label regionI = localRegion[celli];
1192 
1193  if (regionCentres[regionI] == point::max)
1194  {
1195  regionCentres[regionI] = mesh.cellCentres()[celli];
1196  }
1197  }
1198 
1199  // Do decomposition on agglomeration
1200  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1201 
1202  scalarField regionWeights(localRegion.nLocalRegions(), 0);
1203 
1204  if (nWeights > 0)
1205  {
1206  forAll(localRegion, celli)
1207  {
1208  label regionI = localRegion[celli];
1209 
1210  regionWeights[regionI] += cellWeights[celli];
1211  }
1212  }
1213  else
1214  {
1215  forAll(localRegion, celli)
1216  {
1217  label regionI = localRegion[celli];
1218 
1219  regionWeights[regionI] += 1.0;
1220  }
1221  }
1222 
1223  finalDecomp = decompose
1224  (
1225  mesh,
1226  localRegion,
1227  regionCentres,
1228  regionWeights
1229  );
1230 
1231 
1232 
1233  // Implement the explicitConnections since above decompose
1234  // does not know about them
1235  forAll(explicitConnections, i)
1236  {
1237  const labelPair& baffle = explicitConnections[i];
1238  label f0 = baffle.first();
1239  label f1 = baffle.second();
1240 
1241  if (!blockedFace[f0] && !blockedFace[f1])
1242  {
1243  // Note: what if internal faces and owner and neighbour on
1244  // different processor? So for now just push owner side
1245  // proc
1246 
1247  const label proci = finalDecomp[mesh.faceOwner()[f0]];
1248 
1249  finalDecomp[mesh.faceOwner()[f1]] = proci;
1250  if (mesh.isInternalFace(f1))
1251  {
1252  finalDecomp[mesh.faceNeighbour()[f1]] = proci;
1253  }
1254  }
1255  else if (blockedFace[f0] != blockedFace[f1])
1256  {
1258  << "On explicit connection between faces " << f0
1259  << " and " << f1
1260  << " the two blockedFace status are not equal : "
1261  << blockedFace[f0] << " and " << blockedFace[f1]
1262  << exit(FatalError);
1263  }
1264  }
1265 
1266 
1267  // blockedFaces corresponding to processor faces need to be handled
1268  // separately since not handled by local regionSplit. We need to
1269  // walk now across coupled faces and make sure to move a whole
1270  // global region across
1271  if (Pstream::parRun())
1272  {
1273  // Re-do regionSplit
1274 
1275  // Field on cells and faces.
1276  List<minData> cellData(mesh.nCells());
1277  List<minData> faceData(mesh.nFaces());
1278 
1279  // Take over blockedFaces by seeding a negative number
1280  // (so is always less than the decomposition)
1281  label nUnblocked = 0;
1282  forAll(blockedFace, facei)
1283  {
1284  if (blockedFace[facei])
1285  {
1286  faceData[facei] = minData(-123);
1287  }
1288  else
1289  {
1290  nUnblocked++;
1291  }
1292  }
1293 
1294  // Seed unblocked faces with destination processor
1295  labelList seedFaces(nUnblocked);
1296  List<minData> seedData(nUnblocked);
1297  nUnblocked = 0;
1298 
1299  forAll(blockedFace, facei)
1300  {
1301  if (!blockedFace[facei])
1302  {
1303  label own = mesh.faceOwner()[facei];
1304  seedFaces[nUnblocked] = facei;
1305  seedData[nUnblocked] = minData(finalDecomp[own]);
1306  nUnblocked++;
1307  }
1308  }
1309 
1310 
1311  // Propagate information inwards
1312  FaceCellWave<minData> deltaCalc
1313  (
1314  mesh,
1315  seedFaces,
1316  seedData,
1317  faceData,
1318  cellData,
1319  mesh.globalData().nTotalCells()+1
1320  );
1321 
1322  // And extract
1323  forAll(finalDecomp, celli)
1324  {
1325  if (cellData[celli].valid(deltaCalc.data()))
1326  {
1327  finalDecomp[celli] = cellData[celli].data();
1328  }
1329  }
1330  }
1331 
1332 
1333  // For specifiedProcessorFaces rework the cellToProc to enforce
1334  // all on one processor since we can't guarantee that the input
1335  // to regionSplit was a single region.
1336  // E.g. faceSet 'a' with the cells split into two regions
1337  // by a notch formed by two walls
1338  //
1339  // \ /
1340  // \ /
1341  // ---a----+-----a-----
1342  //
1343  //
1344  // Note that reworking the cellToProc might make the decomposition
1345  // unbalanced.
1346  forAll(specifiedProcessorFaces, setI)
1347  {
1348  const labelList& set = specifiedProcessorFaces[setI];
1349 
1350  label proci = specifiedProcessor[setI];
1351  if (proci == -1)
1352  {
1353  // If no processor specified use the one from the
1354  // 0th element
1355  proci = finalDecomp[mesh.faceOwner()[set[0]]];
1356  }
1357 
1358  forAll(set, fI)
1359  {
1360  const face& f = mesh.faces()[set[fI]];
1361  forAll(f, fp)
1362  {
1363  const labelList& pFaces = mesh.pointFaces()[f[fp]];
1364  forAll(pFaces, i)
1365  {
1366  label facei = pFaces[i];
1367 
1368  finalDecomp[mesh.faceOwner()[facei]] = proci;
1369  if (mesh.isInternalFace(facei))
1370  {
1371  finalDecomp[mesh.faceNeighbour()[facei]] = proci;
1372  }
1373  }
1374  }
1375  }
1376  }
1377 
1378 
1379  if (debug && Pstream::parRun())
1380  {
1381  labelList nbrDecomp;
1382  syncTools::swapBoundaryCellList(mesh, finalDecomp, nbrDecomp);
1383 
1384  const polyBoundaryMesh& patches = mesh.boundaryMesh();
1385  forAll(patches, patchi)
1386  {
1387  const polyPatch& pp = patches[patchi];
1388  if (pp.coupled())
1389  {
1390  forAll(pp, i)
1391  {
1392  label facei = pp.start()+i;
1393  label own = mesh.faceOwner()[facei];
1394  label bFacei = facei-mesh.nInternalFaces();
1395 
1396  if (!blockedFace[facei])
1397  {
1398  label ownProc = finalDecomp[own];
1399  label nbrProc = nbrDecomp[bFacei];
1400  if (ownProc != nbrProc)
1401  {
1403  << "patch:" << pp.name()
1404  << " face:" << facei
1405  << " at:" << mesh.faceCentres()[facei]
1406  << " ownProc:" << ownProc
1407  << " nbrProc:" << nbrProc
1408  << exit(FatalError);
1409  }
1410  }
1411  }
1412  }
1413  }
1414  }
1415  }
1416 
1417  return finalDecomp;
1418 }
1419 
1420 
1423  const polyMesh& mesh,
1424  boolList& blockedFace,
1425  PtrList<labelList>& specifiedProcessorFaces,
1426  labelList& specifiedProcessor,
1427  List<labelPair>& explicitConnections
1428 )
1429 {
1430  blockedFace.setSize(mesh.nFaces());
1431  blockedFace = true;
1432 
1433  specifiedProcessorFaces.clear();
1434  explicitConnections.clear();
1435 
1436  forAll(constraints_, constraintI)
1437  {
1438  constraints_[constraintI].add
1439  (
1440  mesh,
1441  blockedFace,
1442  specifiedProcessorFaces,
1443  specifiedProcessor,
1444  explicitConnections
1445  );
1446  }
1447 }
1448 
1449 
1452  const polyMesh& mesh,
1453  const boolList& blockedFace,
1454  const PtrList<labelList>& specifiedProcessorFaces,
1455  const labelList& specifiedProcessor,
1456  const List<labelPair>& explicitConnections,
1457  labelList& decomposition
1458 )
1459 {
1460  forAll(constraints_, constraintI)
1461  {
1462  constraints_[constraintI].apply
1463  (
1464  mesh,
1465  blockedFace,
1466  specifiedProcessorFaces,
1467  specifiedProcessor,
1468  explicitConnections,
1469  decomposition
1470  );
1471  }
1472 }
1473 
1474 
1477  const polyMesh& mesh,
1478  const scalarField& cellWeights
1479 )
1480 {
1481  // Collect all constraints
1482 
1483  boolList blockedFace;
1484  PtrList<labelList> specifiedProcessorFaces;
1485  labelList specifiedProcessor;
1486  List<labelPair> explicitConnections;
1487  setConstraints
1488  (
1489  mesh,
1490  blockedFace,
1491  specifiedProcessorFaces,
1492  specifiedProcessor,
1493  explicitConnections
1494  );
1495 
1496 
1497  // Construct decomposition method and either do decomposition on
1498  // cell centres or on agglomeration
1499 
1500  labelList finalDecomp = decompose
1501  (
1502  mesh,
1503  cellWeights, // optional weights
1504  blockedFace, // any cells to be combined
1505  specifiedProcessorFaces,// any whole cluster of cells to be kept
1506  specifiedProcessor,
1507  explicitConnections // baffles
1508  );
1509 
1510 
1511  // Give any constraint the option of modifying the decomposition
1512 
1513  applyConstraints
1514  (
1515  mesh,
1516  blockedFace,
1517  specifiedProcessorFaces,
1518  specifiedProcessor,
1519  explicitConnections,
1520  finalDecomp
1521  );
1522 
1523  return finalDecomp;
1524 }
1525 
1526 
1527 // ************************************************************************* //
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:434
bool isLocal(const label i) const
Is on local processor.
Definition: globalIndexI.H:95
virtual labelList decompose(const pointField &points, const scalarField &pointWeights)
Return for every coordinate the wanted processor number.
This class separates the mesh into distinct unconnected regions, each of which is then given a label ...
Definition: regionSplit.H:119
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
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
const word & name() const
Return name.
label nLocalRegions() const
Return local number of regions.
Definition: regionSplit.H:195
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:158
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
label nInternalFaces() const
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1175
label nFaces() const
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:163
const List< T > & m() const
Return the packed matrix of data.
label nCells() const
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
Wave propagation of information through grid. Every iteration information goes through one layer of c...
Definition: FaceCellWave.H:76
label nTotalCells() const
Return total number of cells in decomposed mesh.
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:476
Constraint to keep/move owner and neighbour of faceZone onto same processor.
patches[0]
static label worldComm
Default communicator (all processors)
Definition: UPstream.H:278
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:108
scalar f1
Definition: createFields.H:28
static void calcCellCells(const polyMesh &mesh, const labelList &agglom, const label nLocalCoarse, const bool global, CompactListList< label > &cellCells)
Helper: determine (local or global) cellCells from mesh.
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:699
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:63
Detects baffles and keeps owner and neighbour on same processor.
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: contiguous.H:49
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:313
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:124
A class for handling words, derived from string.
Definition: word.H:59
void clear()
Clear all entries from table.
Definition: HashTable.C:468
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:177
void setConstraints(const polyMesh &mesh, boolList &blockedFace, PtrList< labelList > &specifiedProcessorFaces, labelList &specifiedProcessor, List< labelPair > &explicitConnections)
Helper: extract constraints:
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1169
label size() const
Return the primary size, i.e. the number of rows.
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1394
label toLocal(const label i) const
From global to local on current processor.
Definition: globalIndexI.H:117
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1156
const vectorField & cellCentres() const
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
label readLabel(Istream &is)
Definition: label.H:64
decompositionMethod(const dictionary &decompositionDict)
Construct given the decomposition dictionary.
static autoPtr< decompositionMethod > New(const dictionary &decompositionDict)
Return a reference to the selected decomposition method.
Foam::polyBoundaryMesh.
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
A packed storage unstructured matrix of objects of type <T> using an offset table for access...
void setSize(const label mRows)
Reset size of CompactListList.
static const char nl
Definition: Ostream.H:265
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
static autoPtr< decompositionConstraint > New(const dictionary &constraintsDict, const word &type)
Return a reference to the selected decompositionConstraint.
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
const Type & second() const
Return second.
Definition: Pair.H:99
Constraint to keep owner and neighbour of (cyclic) patch on same processor.
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData)
Swap to obtain neighbour cell values for all boundary faces.
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
const vectorField & faceCentres() const
void setSize(const label)
Reset size of List.
Definition: List.C:281
label toGlobal(const label i) const
From local to global.
Definition: globalIndexI.H:82
T * data()
Return a pointer to the first data element,.
Definition: UListI.H:149
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
void applyConstraints(const polyMesh &mesh, const boolList &blockedFace, const PtrList< labelList > &specifiedProcessorFaces, const labelList &specifiedProcessor, const List< labelPair > &explicitConnections, labelList &finalDecomp)
Helper: apply constraints to a decomposition. This gives.
label patchi
const List< label > & offsets() const
Return the offset table (= size()+1)
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: List.H:70
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
const vectorField & faceAreas() const
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:303
void clear()
Clear the PtrList, i.e. set size to zero deleting all the.
Definition: PtrList.C:174
messageStream Info
const labelListList & pointFaces() const
dimensioned< scalar > mag(const dimensioned< Type > &)
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Constraint to keep all cells connected to face or point of faceSet on a single processor.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &l)
Swap coupled boundary face values.
Definition: syncTools.H:430
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
T & last()
Return the last element of the list.
Definition: UListI.H:128
For use with FaceCellWave. Transports minimum passive data.
Definition: minData.H:61
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=*(cellModeller::lookup("hex"));labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells]=cellShape(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< small) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
const Type & first() const
Return first.
Definition: Pair.H:87
Namespace for OpenFOAM.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:583