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