1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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.
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
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/>.
24 \*----------------------------------------------------------------------------*/
26 #include "fvMeshDistribute.H"
27 #include "PstreamCombineReduceOps.H"
28 #include "fvMeshAdder.H"
29 #include "faceCoupleInfo.H"
30 #include "processorFvPatchField.H"
31 #include "processorFvsPatchField.H"
32 #include "processorCyclicPolyPatch.H"
33 #include "processorCyclicFvPatchField.H"
34 #include "processorCyclicFvsPatchField.H"
35 #include "polyTopoChange.H"
36 #include "removeCells.H"
37 #include "polyModifyFace.H"
38 #include "polyRemovePoint.H"
39 #include "mergePoints.H"
40 #include "mapDistributePolyMesh.H"
41 #include "surfaceFields.H"
42 #include "syncTools.H"
43 #include "CompactListList.H"
45 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
47 defineTypeNameAndDebug(Foam::fvMeshDistribute, 0);
50 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52 Foam::labelList Foam::fvMeshDistribute::select
54 const bool selectEqual,
55 const labelList& values,
63 if (selectEqual == (values[i] == value))
74 if (selectEqual == (values[i] == value))
83 // Check all procs have same names and in exactly same order.
84 void Foam::fvMeshDistribute::checkEqualWordList
90 List<wordList> allNames(Pstream::nProcs());
91 allNames[Pstream::myProcNo()] = lst;
92 Pstream::gatherList(allNames);
93 Pstream::scatterList(allNames);
95 for (label procI = 1; procI < Pstream::nProcs(); procI++)
97 if (allNames[procI] != allNames[0])
99 FatalErrorIn("fvMeshDistribute::checkEqualWordList(..)")
100 << "When checking for equal " << msg.c_str() << " :" << endl
101 << "processor0 has:" << allNames[0] << endl
102 << "processor" << procI << " has:" << allNames[procI] << endl
103 << msg.c_str() << " need to be synchronised on all processors."
110 Foam::wordList Foam::fvMeshDistribute::mergeWordList(const wordList& procNames)
112 List<wordList> allNames(Pstream::nProcs());
113 allNames[Pstream::myProcNo()] = procNames;
114 Pstream::gatherList(allNames);
115 Pstream::scatterList(allNames);
117 HashSet<word> mergedNames;
118 forAll(allNames, procI)
120 forAll(allNames[procI], i)
122 mergedNames.insert(allNames[procI][i]);
125 return mergedNames.toc();
129 // Print some info on mesh.
130 void Foam::fvMeshDistribute::printMeshInfo(const fvMesh& mesh)
132 Pout<< "Primitives:" << nl
133 << " points :" << mesh.nPoints() << nl
134 << " bb :" << boundBox(mesh.points(), false) << nl
135 << " internalFaces:" << mesh.nInternalFaces() << nl
136 << " faces :" << mesh.nFaces() << nl
137 << " cells :" << mesh.nCells() << nl;
139 const fvBoundaryMesh& patches = mesh.boundary();
141 Pout<< "Patches:" << endl;
142 forAll(patches, patchI)
144 const polyPatch& pp = patches[patchI].patch();
146 Pout<< " " << patchI << " name:" << pp.name()
147 << " size:" << pp.size()
148 << " start:" << pp.start()
149 << " type:" << pp.type()
153 if (mesh.pointZones().size())
155 Pout<< "PointZones:" << endl;
156 forAll(mesh.pointZones(), zoneI)
158 const pointZone& pz = mesh.pointZones()[zoneI];
159 Pout<< " " << zoneI << " name:" << pz.name()
160 << " size:" << pz.size()
164 if (mesh.faceZones().size())
166 Pout<< "FaceZones:" << endl;
167 forAll(mesh.faceZones(), zoneI)
169 const faceZone& fz = mesh.faceZones()[zoneI];
170 Pout<< " " << zoneI << " name:" << fz.name()
171 << " size:" << fz.size()
175 if (mesh.cellZones().size())
177 Pout<< "CellZones:" << endl;
178 forAll(mesh.cellZones(), zoneI)
180 const cellZone& cz = mesh.cellZones()[zoneI];
181 Pout<< " " << zoneI << " name:" << cz.name()
182 << " size:" << cz.size()
189 void Foam::fvMeshDistribute::printCoupleInfo
191 const primitiveMesh& mesh,
192 const labelList& sourceFace,
193 const labelList& sourceProc,
194 const labelList& sourcePatch,
195 const labelList& sourceNewNbrProc
199 << "Current coupling info:"
202 forAll(sourceFace, bFaceI)
204 label meshFaceI = mesh.nInternalFaces() + bFaceI;
206 Pout<< " meshFace:" << meshFaceI
207 << " fc:" << mesh.faceCentres()[meshFaceI]
208 << " connects to proc:" << sourceProc[bFaceI]
209 << "/face:" << sourceFace[bFaceI]
210 << " which will move to proc:" << sourceNewNbrProc[bFaceI]
216 // Finds (non-empty) patch that exposed internal and proc faces can be put into.
217 Foam::label Foam::fvMeshDistribute::findNonEmptyPatch() const
219 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
221 label nonEmptyPatchI = -1;
223 forAllReverse(patches, patchI)
225 const polyPatch& pp = patches[patchI];
227 if (!isA<emptyPolyPatch>(pp) && !pp.coupled())
229 nonEmptyPatchI = patchI;
234 if (nonEmptyPatchI == -1)
236 FatalErrorIn("fvMeshDistribute::findNonEmptyPatch() const")
237 << "Cannot find a patch which is neither of type empty nor"
238 << " coupled in patches " << patches.names() << endl
239 << "There has to be at least one such patch for"
240 << " distribution to work" << abort(FatalError);
245 Pout<< "findNonEmptyPatch : using patch " << nonEmptyPatchI
246 << " name:" << patches[nonEmptyPatchI].name()
247 << " type:" << patches[nonEmptyPatchI].type()
248 << " to put exposed faces into." << endl;
252 // Do additional test for processor patches intermingled with non-proc
254 label procPatchI = -1;
256 forAll(patches, patchI)
258 if (isA<processorPolyPatch>(patches[patchI]))
262 else if (procPatchI != -1)
264 FatalErrorIn("fvMeshDistribute::findNonEmptyPatch() const")
265 << "Processor patches should be at end of patch list."
267 << "Have processor patch " << procPatchI
268 << " followed by non-processor patch " << patchI
269 << " in patches " << patches.names()
270 << abort(FatalError);
274 return nonEmptyPatchI;
278 //// Appends processorPolyPatch. Returns patchID.
279 //Foam::label Foam::fvMeshDistribute::addProcPatch
281 // const word& patchName,
282 // const label nbrProc
285 // // Clear local fields and e.g. polyMesh globalMeshData.
289 // polyBoundaryMesh& polyPatches =
290 // const_cast<polyBoundaryMesh&>(mesh_.boundaryMesh());
291 // fvBoundaryMesh& fvPatches = const_cast<fvBoundaryMesh&>(mesh_.boundary());
293 // if (polyPatches.findPatchID(patchName) != -1)
297 // "fvMeshDistribute::addProcPatch(const word&, const label)"
299 // << "Cannot create patch " << patchName << " since already exists."
301 // << "Current patch names:" << polyPatches.names()
302 // << exit(FatalError);
310 // label sz = polyPatches.size();
313 // polyPatches.setSize(sz+1);
317 // new processorPolyPatch
323 // mesh_.boundaryMesh(),
324 // Pstream::myProcNo(),
328 // fvPatches.setSize(sz+1);
334 // polyPatches[sz], // point to newly added polyPatch
343 // Appends polyPatch. Returns patchID.
344 Foam::label Foam::fvMeshDistribute::addPatch(polyPatch* patchPtr)
346 // Clear local fields and e.g. polyMesh globalMeshData.
349 polyBoundaryMesh& polyPatches =
350 const_cast<polyBoundaryMesh&>(mesh_.boundaryMesh());
351 fvBoundaryMesh& fvPatches = const_cast<fvBoundaryMesh&>(mesh_.boundary());
353 if (polyPatches.findPatchID(patchPtr->name()) != -1)
355 FatalErrorIn("fvMeshDistribute::addPatch(polyPatch*)")
356 << "Cannot create patch " << patchPtr->name()
357 << " since already exists." << nl
358 << "Current patch names:" << polyPatches.names()
366 label sz = polyPatches.size();
369 polyPatches.setSize(sz+1);
370 polyPatches.set(sz, patchPtr);
371 fvPatches.setSize(sz+1);
377 polyPatches[sz], // point to newly added polyPatch
386 // Deletes last patch
387 void Foam::fvMeshDistribute::deleteTrailingPatch()
389 // Clear local fields and e.g. polyMesh globalMeshData.
392 polyBoundaryMesh& polyPatches =
393 const_cast<polyBoundaryMesh&>(mesh_.boundaryMesh());
394 fvBoundaryMesh& fvPatches = const_cast<fvBoundaryMesh&>(mesh_.boundary());
396 if (polyPatches.empty())
398 FatalErrorIn("fvMeshDistribute::deleteTrailingPatch(fvMesh&)")
399 << "No patches in mesh"
400 << abort(FatalError);
403 label sz = polyPatches.size();
405 label nFaces = polyPatches[sz-1].size();
407 // Remove last polyPatch
410 Pout<< "deleteTrailingPatch : Removing patch " << sz-1
411 << " : " << polyPatches[sz-1].name() << " size:" << nFaces << endl;
416 FatalErrorIn("fvMeshDistribute::deleteTrailingPatch()")
417 << "There are still " << nFaces << " faces in patch to be deleted "
418 << sz-1 << ' ' << polyPatches[sz-1].name()
419 << abort(FatalError);
422 // Remove actual patch
423 polyPatches.setSize(sz-1);
424 fvPatches.setSize(sz-1);
428 // Delete all processor patches. Move any processor faces into the last
429 // non-processor patch.
430 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::deleteProcPatches
432 const label destinationPatch
435 // New patchID per boundary faces to be repatched. Is -1 (no change)
437 labelList newPatchID(mesh_.nFaces() - mesh_.nInternalFaces(), -1);
439 label nProcPatches = 0;
441 forAll(mesh_.boundaryMesh(), patchI)
443 const polyPatch& pp = mesh_.boundaryMesh()[patchI];
445 if (isA<processorPolyPatch>(pp))
449 Pout<< "Moving all faces of patch " << pp.name()
450 << " into patch " << destinationPatch
454 label offset = pp.start() - mesh_.nInternalFaces();
458 newPatchID[offset+i] = destinationPatch;
465 // Note: order of boundary faces been kept the same since the
466 // destinationPatch is at the end and we have visited the patches in
467 // incremental order.
468 labelListList dummyFaceMaps;
469 autoPtr<mapPolyMesh> map = repatch(newPatchID, dummyFaceMaps);
472 // Delete (now empty) processor patches.
473 forAllReverse(mesh_.boundaryMesh(), patchI)
475 const polyPatch& pp = mesh_.boundaryMesh()[patchI];
477 if (isA<processorPolyPatch>(pp))
479 deleteTrailingPatch();
480 deleteTrailingPatchFields<volScalarField>();
481 deleteTrailingPatchFields<volVectorField>();
482 deleteTrailingPatchFields<volSphericalTensorField>();
483 deleteTrailingPatchFields<volSymmTensorField>();
484 deleteTrailingPatchFields<volTensorField>();
486 deleteTrailingPatchFields<surfaceScalarField>();
487 deleteTrailingPatchFields<surfaceVectorField>();
488 deleteTrailingPatchFields<surfaceSphericalTensorField>();
489 deleteTrailingPatchFields<surfaceSymmTensorField>();
490 deleteTrailingPatchFields<surfaceTensorField>();
499 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::repatch
501 const labelList& newPatchID, // per boundary face -1 or new patchID
502 labelListList& constructFaceMap
505 polyTopoChange meshMod(mesh_);
507 forAll(newPatchID, bFaceI)
509 if (newPatchID[bFaceI] != -1)
511 label faceI = mesh_.nInternalFaces() + bFaceI;
513 label zoneID = mesh_.faceZones().whichZone(faceI);
514 bool zoneFlip = false;
518 const faceZone& fZone = mesh_.faceZones()[zoneID];
519 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
526 mesh_.faces()[faceI], // modified face
527 faceI, // label of face
528 mesh_.faceOwner()[faceI], // owner
531 newPatchID[bFaceI], // patch for face
532 false, // remove from zone
533 zoneID, // zone for face
534 zoneFlip // face flip in zone
541 // Do mapping of fields from one patchField to the other ourselves since
542 // is currently not supported by updateMesh.
544 // Store boundary fields (we only do this for surfaceFields)
545 PtrList<FieldField<fvsPatchField, scalar> > sFlds;
546 saveBoundaryFields<scalar, surfaceMesh>(sFlds);
547 PtrList<FieldField<fvsPatchField, vector> > vFlds;
548 saveBoundaryFields<vector, surfaceMesh>(vFlds);
549 PtrList<FieldField<fvsPatchField, sphericalTensor> > sptFlds;
550 saveBoundaryFields<sphericalTensor, surfaceMesh>(sptFlds);
551 PtrList<FieldField<fvsPatchField, symmTensor> > sytFlds;
552 saveBoundaryFields<symmTensor, surfaceMesh>(sytFlds);
553 PtrList<FieldField<fvsPatchField, tensor> > tFlds;
554 saveBoundaryFields<tensor, surfaceMesh>(tFlds);
556 // Change the mesh (no inflation). Note: parallel comms allowed.
557 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
559 // Update fields. No inflation, parallel sync.
560 mesh_.updateMesh(map);
562 // Map patch fields using stored boundary fields. Note: assumes order
563 // of fields has not changed in object registry!
564 mapBoundaryFields<scalar, surfaceMesh>(map, sFlds);
565 mapBoundaryFields<vector, surfaceMesh>(map, vFlds);
566 mapBoundaryFields<sphericalTensor, surfaceMesh>(map, sptFlds);
567 mapBoundaryFields<symmTensor, surfaceMesh>(map, sytFlds);
568 mapBoundaryFields<tensor, surfaceMesh>(map, tFlds);
571 // Move mesh (since morphing does not do this)
572 if (map().hasMotionPoints())
574 mesh_.movePoints(map().preMotionPoints());
577 // Adapt constructMaps.
581 label index = findIndex(map().reverseFaceMap(), -1);
587 "fvMeshDistribute::repatch(const labelList&, labelListList&)"
588 ) << "reverseFaceMap contains -1 at index:"
590 << "This means that the repatch operation was not just"
591 << " a shuffle?" << abort(FatalError);
595 forAll(constructFaceMap, procI)
597 inplaceRenumber(map().reverseFaceMap(), constructFaceMap[procI]);
605 // Detect shared points. Need processor patches to be present.
606 // Background: when adding bits of mesh one can get points which
607 // share the same position but are only detectable to be topologically
608 // the same point when doing parallel analysis. This routine will
609 // merge those points.
610 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::mergeSharedPoints
612 labelListList& constructPointMap
615 // Find out which sets of points get merged and create a map from
616 // mesh point to unique point.
617 Map<label> pointToMaster
619 fvMeshAdder::findSharedPoints
626 if (returnReduce(pointToMaster.size(), sumOp<label>()) == 0)
628 return autoPtr<mapPolyMesh>(NULL);
631 polyTopoChange meshMod(mesh_);
633 fvMeshAdder::mergePoints(mesh_, pointToMaster, meshMod);
635 // Change the mesh (no inflation). Note: parallel comms allowed.
636 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
638 // Update fields. No inflation, parallel sync.
639 mesh_.updateMesh(map);
641 // Adapt constructMaps for merged points.
642 forAll(constructPointMap, procI)
644 labelList& constructMap = constructPointMap[procI];
646 forAll(constructMap, i)
648 label oldPointI = constructMap[i];
650 label newPointI = map().reversePointMap()[oldPointI];
654 constructMap[i] = -newPointI-2;
656 else if (newPointI >= 0)
658 constructMap[i] = newPointI;
662 FatalErrorIn("fvMeshDistribute::mergeSharedPoints()")
663 << "Problem. oldPointI:" << oldPointI
664 << " newPointI:" << newPointI << abort(FatalError);
672 // Construct the local environment of all boundary faces.
673 void Foam::fvMeshDistribute::getNeighbourData
675 const labelList& distribution,
676 labelList& sourceFace,
677 labelList& sourceProc,
678 labelList& sourcePatch,
679 labelList& sourceNewNbrProc
682 label nBnd = mesh_.nFaces() - mesh_.nInternalFaces();
683 sourceFace.setSize(nBnd);
684 sourceProc.setSize(nBnd);
685 sourcePatch.setSize(nBnd);
686 sourceNewNbrProc.setSize(nBnd);
688 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
690 // Get neighbouring meshFace labels and new processor of coupled boundaries.
691 labelList nbrFaces(nBnd, -1);
692 labelList nbrNewNbrProc(nBnd, -1);
694 forAll(patches, patchI)
696 const polyPatch& pp = patches[patchI];
700 label offset = pp.start() - mesh_.nInternalFaces();
702 // Mesh labels of faces on this side
705 label bndI = offset + i;
706 nbrFaces[bndI] = pp.start()+i;
709 // Which processor they will end up on
710 SubList<label>(nbrNewNbrProc, pp.size(), offset).assign
712 UIndirectList<label>(distribution, pp.faceCells())()
718 // Exchange the boundary data
719 syncTools::swapBoundaryFaceList(mesh_, nbrFaces);
720 syncTools::swapBoundaryFaceList(mesh_, nbrNewNbrProc);
723 forAll(patches, patchI)
725 const polyPatch& pp = patches[patchI];
726 label offset = pp.start() - mesh_.nInternalFaces();
728 if (isA<processorPolyPatch>(pp))
730 const processorPolyPatch& procPatch =
731 refCast<const processorPolyPatch>(pp);
733 // Check which of the two faces we store.
735 if (procPatch.owner())
737 // Use my local face labels
740 label bndI = offset + i;
741 sourceFace[bndI] = pp.start()+i;
742 sourceProc[bndI] = Pstream::myProcNo();
743 sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
748 // Use my neighbours face labels
751 label bndI = offset + i;
752 sourceFace[bndI] = nbrFaces[bndI];
753 sourceProc[bndI] = procPatch.neighbProcNo();
754 sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
760 if (isA<processorCyclicPolyPatch>(pp))
762 patchI = refCast<const processorCyclicPolyPatch>
770 label bndI = offset + i;
771 sourcePatch[bndI] = patchI;
774 else if (isA<cyclicPolyPatch>(pp))
776 const cyclicPolyPatch& cpp = refCast<const cyclicPolyPatch>(pp);
782 label bndI = offset + i;
783 sourceFace[bndI] = pp.start()+i;
784 sourceProc[bndI] = Pstream::myProcNo();
785 sourcePatch[bndI] = patchI;
786 sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
793 label bndI = offset + i;
794 sourceFace[bndI] = nbrFaces[bndI];
795 sourceProc[bndI] = Pstream::myProcNo();
796 sourcePatch[bndI] = patchI;
797 sourceNewNbrProc[bndI] = nbrNewNbrProc[bndI];
803 // Normal (physical) boundary
806 label bndI = offset + i;
807 sourceFace[bndI] = -1;
808 sourceProc[bndI] = -1;
809 sourcePatch[bndI] = patchI;
810 sourceNewNbrProc[bndI] = -1;
817 // Subset the neighbourCell/neighbourProc fields
818 void Foam::fvMeshDistribute::subsetBoundaryData
821 const labelList& faceMap,
822 const labelList& cellMap,
824 const labelList& oldDistribution,
825 const labelList& oldFaceOwner,
826 const labelList& oldFaceNeighbour,
827 const label oldInternalFaces,
829 const labelList& sourceFace,
830 const labelList& sourceProc,
831 const labelList& sourcePatch,
832 const labelList& sourceNewNbrProc,
837 labelList& subNewNbrProc
840 subFace.setSize(mesh.nFaces() - mesh.nInternalFaces());
841 subProc.setSize(mesh.nFaces() - mesh.nInternalFaces());
842 subPatch.setSize(mesh.nFaces() - mesh.nInternalFaces());
843 subNewNbrProc.setSize(mesh.nFaces() - mesh.nInternalFaces());
845 forAll(subFace, newBFaceI)
847 label newFaceI = newBFaceI + mesh.nInternalFaces();
849 label oldFaceI = faceMap[newFaceI];
851 // Was oldFaceI internal face? If so which side did we get.
852 if (oldFaceI < oldInternalFaces)
854 subFace[newBFaceI] = oldFaceI;
855 subProc[newBFaceI] = Pstream::myProcNo();
856 subPatch[newBFaceI] = -1;
858 label oldOwn = oldFaceOwner[oldFaceI];
859 label oldNei = oldFaceNeighbour[oldFaceI];
861 if (oldOwn == cellMap[mesh.faceOwner()[newFaceI]])
863 // We kept the owner side. Where does the neighbour move to?
864 subNewNbrProc[newBFaceI] = oldDistribution[oldNei];
868 // We kept the neighbour side.
869 subNewNbrProc[newBFaceI] = oldDistribution[oldOwn];
874 // Was boundary face. Take over boundary information
875 label oldBFaceI = oldFaceI - oldInternalFaces;
877 subFace[newBFaceI] = sourceFace[oldBFaceI];
878 subProc[newBFaceI] = sourceProc[oldBFaceI];
879 subPatch[newBFaceI] = sourcePatch[oldBFaceI];
880 subNewNbrProc[newBFaceI] = sourceNewNbrProc[oldBFaceI];
886 // Find cells on mesh whose faceID/procID match the neighbour cell/proc of
887 // domainMesh. Store the matching face.
888 void Foam::fvMeshDistribute::findCouples
890 const primitiveMesh& mesh,
891 const labelList& sourceFace,
892 const labelList& sourceProc,
893 const labelList& sourcePatch,
896 const primitiveMesh& domainMesh,
897 const labelList& domainFace,
898 const labelList& domainProc,
899 const labelList& domainPatch,
901 labelList& masterCoupledFaces,
902 labelList& slaveCoupledFaces
905 // Store domain neighbour as map so we can easily look for pair
906 // with same face+proc.
907 HashTable<label, labelPair, labelPair::Hash<> > map(domainFace.size());
909 forAll(domainProc, bFaceI)
911 if (domainProc[bFaceI] != -1 && domainPatch[bFaceI] == -1)
915 labelPair(domainFace[bFaceI], domainProc[bFaceI]),
922 // Try to match mesh data.
924 masterCoupledFaces.setSize(domainFace.size());
925 slaveCoupledFaces.setSize(domainFace.size());
928 forAll(sourceFace, bFaceI)
930 if (sourceProc[bFaceI] != -1 && sourcePatch[bFaceI] == -1)
932 labelPair myData(sourceFace[bFaceI], sourceProc[bFaceI]);
934 HashTable<label, labelPair, labelPair::Hash<> >::const_iterator
935 iter = map.find(myData);
937 if (iter != map.end())
939 label nbrBFaceI = iter();
941 masterCoupledFaces[coupledI] = mesh.nInternalFaces() + bFaceI;
942 slaveCoupledFaces[coupledI] =
943 domainMesh.nInternalFaces()
951 masterCoupledFaces.setSize(coupledI);
952 slaveCoupledFaces.setSize(coupledI);
956 Pout<< "findCouples : found " << coupledI
957 << " faces that will be stitched" << nl << endl;
962 // Map data on boundary faces to new mesh (resulting from adding two meshes)
963 Foam::labelList Foam::fvMeshDistribute::mapBoundaryData
965 const primitiveMesh& mesh, // mesh after adding
966 const mapAddedPolyMesh& map,
967 const labelList& boundaryData0, // mesh before adding
968 const label nInternalFaces1,
969 const labelList& boundaryData1 // added mesh
972 labelList newBoundaryData(mesh.nFaces() - mesh.nInternalFaces());
974 forAll(boundaryData0, oldBFaceI)
976 label newFaceI = map.oldFaceMap()[oldBFaceI + map.nOldInternalFaces()];
978 // Face still exists (is necessary?) and still boundary face
979 if (newFaceI >= 0 && newFaceI >= mesh.nInternalFaces())
981 newBoundaryData[newFaceI - mesh.nInternalFaces()] =
982 boundaryData0[oldBFaceI];
986 forAll(boundaryData1, addedBFaceI)
988 label newFaceI = map.addedFaceMap()[addedBFaceI + nInternalFaces1];
990 if (newFaceI >= 0 && newFaceI >= mesh.nInternalFaces())
992 newBoundaryData[newFaceI - mesh.nInternalFaces()] =
993 boundaryData1[addedBFaceI];
997 return newBoundaryData;
1001 // Remove cells. Add all exposed faces to patch oldInternalPatchI
1002 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::doRemoveCells
1004 const labelList& cellsToRemove,
1005 const label oldInternalPatchI
1008 // Mesh change engine
1009 polyTopoChange meshMod(mesh_);
1011 // Cell removal topo engine. Do NOT synchronize parallel since
1012 // we are doing a local cell removal.
1013 removeCells cellRemover(mesh_, false);
1015 // Get all exposed faces
1016 labelList exposedFaces(cellRemover.getExposedFaces(cellsToRemove));
1018 // Insert the topo changes
1019 cellRemover.setRefinement
1023 labelList(exposedFaces.size(), oldInternalPatchI), // patch for exposed
1028 // Change the mesh. No inflation. Note: no parallel comms allowed.
1029 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, false);
1032 mesh_.updateMesh(map);
1034 // Move mesh (since morphing does not do this)
1035 if (map().hasMotionPoints())
1037 mesh_.movePoints(map().preMotionPoints());
1044 // Delete and add processor patches. Changes mesh and returns per neighbour proc
1045 // the processor patchID.
1046 void Foam::fvMeshDistribute::addProcPatches
1048 const labelList& nbrProc, // processor that neighbour is now on
1049 const labelList& referPatchID, // patchID (or -1) I originated from
1050 List<Map<label> >& procPatchID
1053 // Now use the neighbourFace/Proc to repatch the mesh. These lists
1054 // contain for all current boundary faces the global patchID (for non-proc
1055 // patch) or the processor.
1057 procPatchID.setSize(Pstream::nProcs());
1059 forAll(nbrProc, bFaceI)
1061 label procI = nbrProc[bFaceI];
1063 if (procI != -1 && procI != Pstream::myProcNo())
1065 if (!procPatchID[procI].found(referPatchID[bFaceI]))
1067 // No patch for neighbour yet. Is either a normal processor
1068 // patch or a processorCyclic patch.
1070 if (referPatchID[bFaceI] == -1)
1072 // Ordinary processor boundary
1074 const word patchName =
1076 + name(Pstream::myProcNo())
1080 procPatchID[procI].insert
1082 referPatchID[bFaceI],
1085 new processorPolyPatch
1090 mesh_.boundaryMesh().size(),
1091 mesh_.boundaryMesh(),
1092 Pstream::myProcNo(),
1098 addPatchFields<volScalarField>
1100 processorFvPatchField<scalar>::typeName
1102 addPatchFields<volVectorField>
1104 processorFvPatchField<vector>::typeName
1106 addPatchFields<volSphericalTensorField>
1108 processorFvPatchField<sphericalTensor>::typeName
1110 addPatchFields<volSymmTensorField>
1112 processorFvPatchField<symmTensor>::typeName
1114 addPatchFields<volTensorField>
1116 processorFvPatchField<tensor>::typeName
1119 addPatchFields<surfaceScalarField>
1121 processorFvPatchField<scalar>::typeName
1123 addPatchFields<surfaceVectorField>
1125 processorFvPatchField<vector>::typeName
1127 addPatchFields<surfaceSphericalTensorField>
1129 processorFvPatchField<sphericalTensor>::typeName
1131 addPatchFields<surfaceSymmTensorField>
1133 processorFvPatchField<symmTensor>::typeName
1135 addPatchFields<surfaceTensorField>
1137 processorFvPatchField<tensor>::typeName
1142 // Processor boundary originating from cyclic
1143 const word& cycName = mesh_.boundaryMesh()
1145 referPatchID[bFaceI]
1148 const word patchName =
1150 + name(Pstream::myProcNo())
1156 procPatchID[procI].insert
1158 referPatchID[bFaceI],
1161 new processorCyclicPolyPatch
1166 mesh_.boundaryMesh().size(),
1167 mesh_.boundaryMesh(),
1168 Pstream::myProcNo(),
1175 addPatchFields<volScalarField>
1177 processorCyclicFvPatchField<scalar>::typeName
1179 addPatchFields<volVectorField>
1181 processorCyclicFvPatchField<vector>::typeName
1183 addPatchFields<volSphericalTensorField>
1185 processorCyclicFvPatchField<sphericalTensor>::typeName
1187 addPatchFields<volSymmTensorField>
1189 processorCyclicFvPatchField<symmTensor>::typeName
1191 addPatchFields<volTensorField>
1193 processorCyclicFvPatchField<tensor>::typeName
1196 addPatchFields<surfaceScalarField>
1198 processorCyclicFvPatchField<scalar>::typeName
1200 addPatchFields<surfaceVectorField>
1202 processorCyclicFvPatchField<vector>::typeName
1204 addPatchFields<surfaceSphericalTensorField>
1206 processorCyclicFvPatchField<sphericalTensor>::typeName
1208 addPatchFields<surfaceSymmTensorField>
1210 processorCyclicFvPatchField<symmTensor>::typeName
1212 addPatchFields<surfaceTensorField>
1214 processorCyclicFvPatchField<tensor>::typeName
1223 // Get boundary faces to be repatched. Is -1 or new patchID
1224 Foam::labelList Foam::fvMeshDistribute::getBoundaryPatch
1226 const labelList& nbrProc, // new processor per boundary face
1227 const labelList& referPatchID, // patchID (or -1) I originated from
1228 const List<Map<label> >& procPatchID // per proc the new procPatches
1231 labelList patchIDs(nbrProc);
1233 forAll(nbrProc, bFaceI)
1235 if (nbrProc[bFaceI] == Pstream::myProcNo())
1237 label origPatchI = referPatchID[bFaceI];
1238 patchIDs[bFaceI] = origPatchI;
1240 else if (nbrProc[bFaceI] != -1)
1242 label origPatchI = referPatchID[bFaceI];
1243 patchIDs[bFaceI] = procPatchID[nbrProc[bFaceI]][origPatchI];
1247 patchIDs[bFaceI] = -1;
1254 // Send mesh and coupling data.
1255 void Foam::fvMeshDistribute::sendMesh
1260 const wordList& pointZoneNames,
1261 const wordList& faceZoneNames,
1262 const wordList& cellZoneNames,
1264 const labelList& sourceFace,
1265 const labelList& sourceProc,
1266 const labelList& sourcePatch,
1267 const labelList& sourceNewNbrProc,
1273 Pout<< "Sending to domain " << domain << nl
1274 << " nPoints:" << mesh.nPoints() << nl
1275 << " nFaces:" << mesh.nFaces() << nl
1276 << " nCells:" << mesh.nCells() << nl
1277 << " nPatches:" << mesh.boundaryMesh().size() << nl
1281 // Assume sparse, possibly overlapping point zones. Get contents
1282 // in merged-zone indices.
1283 CompactListList<label> zonePoints;
1285 const pointZoneMesh& pointZones = mesh.pointZones();
1287 labelList rowSizes(pointZoneNames.size(), 0);
1289 forAll(pointZoneNames, nameI)
1291 label myZoneID = pointZones.findZoneID(pointZoneNames[nameI]);
1295 rowSizes[nameI] = pointZones[myZoneID].size();
1298 zonePoints.setSize(rowSizes);
1300 forAll(pointZoneNames, nameI)
1302 label myZoneID = pointZones.findZoneID(pointZoneNames[nameI]);
1306 zonePoints[nameI].assign(pointZones[myZoneID]);
1311 // Assume sparse, possibly overlapping face zones
1312 CompactListList<label> zoneFaces;
1313 CompactListList<bool> zoneFaceFlip;
1315 const faceZoneMesh& faceZones = mesh.faceZones();
1317 labelList rowSizes(faceZoneNames.size(), 0);
1319 forAll(faceZoneNames, nameI)
1321 label myZoneID = faceZones.findZoneID(faceZoneNames[nameI]);
1325 rowSizes[nameI] = faceZones[myZoneID].size();
1329 zoneFaces.setSize(rowSizes);
1330 zoneFaceFlip.setSize(rowSizes);
1332 forAll(faceZoneNames, nameI)
1334 label myZoneID = faceZones.findZoneID(faceZoneNames[nameI]);
1338 zoneFaces[nameI].assign(faceZones[myZoneID]);
1339 zoneFaceFlip[nameI].assign(faceZones[myZoneID].flipMap());
1344 // Assume sparse, possibly overlapping cell zones
1345 CompactListList<label> zoneCells;
1347 const cellZoneMesh& cellZones = mesh.cellZones();
1349 labelList rowSizes(cellZoneNames.size(), 0);
1351 forAll(cellZoneNames, nameI)
1353 label myZoneID = cellZones.findZoneID(cellZoneNames[nameI]);
1357 rowSizes[nameI] = cellZones[myZoneID].size();
1361 zoneCells.setSize(rowSizes);
1363 forAll(cellZoneNames, nameI)
1365 label myZoneID = cellZones.findZoneID(cellZoneNames[nameI]);
1369 zoneCells[nameI].assign(cellZones[myZoneID]);
1373 ////- Assume full cell zones
1374 //labelList cellZoneID;
1377 // cellZoneID.setSize(mesh.nCells());
1380 // const cellZoneMesh& cellZones = mesh.cellZones();
1382 // forAll(cellZones, zoneI)
1384 // UIndirectList<label>(cellZoneID, cellZones[zoneI]) = zoneI;
1391 << CompactListList<label, face>(mesh.faces())
1393 << mesh.faceNeighbour()
1394 << mesh.boundaryMesh()
1404 << sourceNewNbrProc;
1409 Pout<< "Started sending mesh to domain " << domain
1415 // Receive mesh. Opposite of sendMesh
1416 Foam::autoPtr<Foam::fvMesh> Foam::fvMeshDistribute::receiveMesh
1419 const wordList& pointZoneNames,
1420 const wordList& faceZoneNames,
1421 const wordList& cellZoneNames,
1422 const Time& runTime,
1423 labelList& domainSourceFace,
1424 labelList& domainSourceProc,
1425 labelList& domainSourcePatch,
1426 labelList& domainSourceNewNbrProc,
1430 pointField domainPoints(fromNbr);
1431 faceList domainFaces = CompactListList<label, face>(fromNbr)();
1432 labelList domainAllOwner(fromNbr);
1433 labelList domainAllNeighbour(fromNbr);
1434 PtrList<entry> patchEntries(fromNbr);
1436 CompactListList<label> zonePoints(fromNbr);
1437 CompactListList<label> zoneFaces(fromNbr);
1438 CompactListList<bool> zoneFaceFlip(fromNbr);
1439 CompactListList<label> zoneCells(fromNbr);
1444 >> domainSourcePatch
1445 >> domainSourceNewNbrProc;
1448 autoPtr<fvMesh> domainMeshPtr
1454 fvMesh::defaultRegion,
1459 xferMove(domainPoints),
1460 xferMove(domainFaces),
1461 xferMove(domainAllOwner),
1462 xferMove(domainAllNeighbour),
1463 false // no parallel comms
1466 fvMesh& domainMesh = domainMeshPtr();
1468 List<polyPatch*> patches(patchEntries.size());
1470 forAll(patchEntries, patchI)
1472 patches[patchI] = polyPatch::New
1474 patchEntries[patchI].keyword(),
1475 patchEntries[patchI].dict(),
1477 domainMesh.boundaryMesh()
1480 // Add patches; no parallel comms
1481 domainMesh.addFvPatches(patches, false);
1484 List<pointZone*> pZonePtrs(pointZoneNames.size());
1485 forAll(pZonePtrs, i)
1487 pZonePtrs[i] = new pointZone
1492 domainMesh.pointZones()
1496 List<faceZone*> fZonePtrs(faceZoneNames.size());
1497 forAll(fZonePtrs, i)
1499 fZonePtrs[i] = new faceZone
1505 domainMesh.faceZones()
1509 List<cellZone*> cZonePtrs(cellZoneNames.size());
1510 forAll(cZonePtrs, i)
1512 cZonePtrs[i] = new cellZone
1517 domainMesh.cellZones()
1520 domainMesh.addZones(pZonePtrs, fZonePtrs, cZonePtrs);
1522 return domainMeshPtr;
1526 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1528 // Construct from components
1529 Foam::fvMeshDistribute::fvMeshDistribute(fvMesh& mesh, const scalar mergeTol)
1536 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1538 Foam::labelList Foam::fvMeshDistribute::countCells
1540 const labelList& distribution
1543 labelList nCells(Pstream::nProcs(), 0);
1544 forAll(distribution, cellI)
1546 label newProc = distribution[cellI];
1548 if (newProc < 0 || newProc >= Pstream::nProcs())
1550 FatalErrorIn("fvMeshDistribute::distribute(const labelList&)")
1551 << "Distribution should be in range 0.." << Pstream::nProcs()-1
1553 << "At index " << cellI << " distribution:" << newProc
1554 << abort(FatalError);
1562 Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
1564 const labelList& distribution
1567 // Some checks on distribution
1568 if (distribution.size() != mesh_.nCells())
1570 FatalErrorIn("fvMeshDistribute::distribute(const labelList&)")
1571 << "Size of distribution:"
1572 << distribution.size() << " mesh nCells:" << mesh_.nCells()
1573 << abort(FatalError);
1577 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
1579 // Check all processors have same non-proc patches in same order.
1580 if (patches.checkParallelSync(true))
1582 FatalErrorIn("fvMeshDistribute::distribute(const labelList&)")
1583 << "This application requires all non-processor patches"
1584 << " to be present in the same order on all patches" << nl
1585 << "followed by the processor patches (which of course are unique)."
1587 << "Local patches:" << mesh_.boundaryMesh().names()
1588 << abort(FatalError);
1591 // Save some data for mapping later on
1592 const label nOldPoints(mesh_.nPoints());
1593 const label nOldFaces(mesh_.nFaces());
1594 const label nOldCells(mesh_.nCells());
1595 labelList oldPatchStarts(patches.size());
1596 labelList oldPatchNMeshPoints(patches.size());
1597 forAll(patches, patchI)
1599 oldPatchStarts[patchI] = patches[patchI].start();
1600 oldPatchNMeshPoints[patchI] = patches[patchI].nPoints();
1605 // Short circuit trivial case.
1606 if (!Pstream::parRun())
1608 // Collect all maps and return
1609 return autoPtr<mapDistributePolyMesh>
1611 new mapDistributePolyMesh
1618 oldPatchStarts.xfer(),
1619 oldPatchNMeshPoints.xfer(),
1621 labelListList(1, identity(mesh_.nPoints())).xfer(),//subPointMap
1622 labelListList(1, identity(mesh_.nFaces())).xfer(), //subFaceMap
1623 labelListList(1, identity(mesh_.nCells())).xfer(), //subCellMap
1624 labelListList(1, identity(patches.size())).xfer(), //subPatchMap
1626 labelListList(1, identity(mesh_.nPoints())).xfer(),//pointMap
1627 labelListList(1, identity(mesh_.nFaces())).xfer(), //faceMap
1628 labelListList(1, identity(mesh_.nCells())).xfer(), //cellMap
1629 labelListList(1, identity(patches.size())).xfer() //patchMap
1635 // Collect any zone names
1636 const wordList pointZoneNames(mergeWordList(mesh_.pointZones().names()));
1637 const wordList faceZoneNames(mergeWordList(mesh_.faceZones().names()));
1638 const wordList cellZoneNames(mergeWordList(mesh_.cellZones().names()));
1642 // Local environment of all boundary faces
1643 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1645 // A face is uniquely defined by
1649 // To glue the parts of meshes which can get sent from anywhere we
1650 // need to know on boundary faces what the above tuple on both sides is.
1651 // So we need to maintain:
1653 // - original processor id (= trivial)
1654 // For coupled boundaries (where the faces are 'duplicate') we take the
1655 // lowest numbered processor as the data to store.
1657 // Additionally to create the procboundaries we need to know where the owner
1658 // cell on the other side now is: newNeighbourProc.
1661 // physical boundary:
1663 // sourceNewNbrProc = -1
1665 // sourcePatch = patchID
1666 // processor boundary:
1667 // sourceProc = proc (on owner side)
1668 // sourceNewNbrProc = distribution of coupled cell
1669 // sourceFace = face (on owner side)
1672 // ? sourceProc = proc
1673 // ? sourceNewNbrProc = distribution of coupled cell
1674 // ? sourceFace = face (on owner side)
1675 // ? sourcePatch = patchID
1676 // processor-cyclic boundary:
1677 // sourceProc = proc (on owner side)
1678 // sourceNewNbrProc = distribution of coupled cell
1679 // sourceFace = face (on owner side)
1680 // sourcePatch = patchID
1682 labelList sourcePatch;
1683 labelList sourceFace;
1684 labelList sourceProc;
1685 labelList sourceNewNbrProc;
1696 // Remove meshPhi. Since this would otherwise disappear anyway
1697 // during topo changes and we have to guarantee that all the fields
1700 mesh_.resetMotion();
1702 // Get data to send. Make sure is synchronised
1703 const wordList volScalars(mesh_.names(volScalarField::typeName));
1704 checkEqualWordList("volScalarFields", volScalars);
1705 const wordList volVectors(mesh_.names(volVectorField::typeName));
1706 checkEqualWordList("volVectorFields", volVectors);
1707 const wordList volSphereTensors
1709 mesh_.names(volSphericalTensorField::typeName)
1711 checkEqualWordList("volSphericalTensorFields", volSphereTensors);
1712 const wordList volSymmTensors(mesh_.names(volSymmTensorField::typeName));
1713 checkEqualWordList("volSymmTensorFields", volSymmTensors);
1714 const wordList volTensors(mesh_.names(volTensorField::typeName));
1715 checkEqualWordList("volTensorField", volTensors);
1717 const wordList surfScalars(mesh_.names(surfaceScalarField::typeName));
1718 checkEqualWordList("surfaceScalarFields", surfScalars);
1719 const wordList surfVectors(mesh_.names(surfaceVectorField::typeName));
1720 checkEqualWordList("surfaceVectorFields", surfVectors);
1721 const wordList surfSphereTensors
1723 mesh_.names(surfaceSphericalTensorField::typeName)
1725 checkEqualWordList("surfaceSphericalTensorFields", surfSphereTensors);
1726 const wordList surfSymmTensors
1728 mesh_.names(surfaceSymmTensorField::typeName)
1730 checkEqualWordList("surfaceSymmTensorFields", surfSymmTensors);
1731 const wordList surfTensors(mesh_.names(surfaceTensorField::typeName));
1732 checkEqualWordList("surfaceTensorFields", surfTensors);
1737 // Find patch to temporarily put exposed and processor faces into.
1738 label oldInternalPatchI = findNonEmptyPatch();
1742 // Delete processor patches, starting from the back. Move all faces into
1743 // oldInternalPatchI.
1744 labelList repatchFaceMap;
1746 autoPtr<mapPolyMesh> repatchMap = deleteProcPatches(oldInternalPatchI);
1748 // Store face map (only face ordering that changed)
1749 repatchFaceMap = repatchMap().faceMap();
1751 // Reorder all boundary face data (sourceProc, sourceFace etc.)
1756 repatchMap().reverseFaceMap(),
1757 mesh_.nFaces() - mesh_.nInternalFaces(),
1758 mesh_.nInternalFaces()
1760 - mesh_.nInternalFaces()
1763 inplaceReorder(bFaceMap, sourceFace);
1764 inplaceReorder(bFaceMap, sourceProc);
1765 inplaceReorder(bFaceMap, sourcePatch);
1766 inplaceReorder(bFaceMap, sourceNewNbrProc);
1774 Pout<< nl << "MESH WITH PROC PATCHES DELETED:" << endl;
1775 printMeshInfo(mesh_);
1776 printFieldInfo<volScalarField>(mesh_);
1777 printFieldInfo<volVectorField>(mesh_);
1778 printFieldInfo<volSphericalTensorField>(mesh_);
1779 printFieldInfo<volSymmTensorField>(mesh_);
1780 printFieldInfo<volTensorField>(mesh_);
1781 printFieldInfo<surfaceScalarField>(mesh_);
1782 printFieldInfo<surfaceVectorField>(mesh_);
1783 printFieldInfo<surfaceSphericalTensorField>(mesh_);
1784 printFieldInfo<surfaceSymmTensorField>(mesh_);
1785 printFieldInfo<surfaceTensorField>(mesh_);
1791 // Maps from subsetted mesh (that is sent) back to original maps
1792 labelListList subCellMap(Pstream::nProcs());
1793 labelListList subFaceMap(Pstream::nProcs());
1794 labelListList subPointMap(Pstream::nProcs());
1795 labelListList subPatchMap(Pstream::nProcs());
1796 // Maps from subsetted mesh to reconstructed mesh
1797 labelListList constructCellMap(Pstream::nProcs());
1798 labelListList constructFaceMap(Pstream::nProcs());
1799 labelListList constructPointMap(Pstream::nProcs());
1800 labelListList constructPatchMap(Pstream::nProcs());
1805 // Find out schedule
1806 // ~~~~~~~~~~~~~~~~~
1808 labelListList nSendCells(Pstream::nProcs());
1809 nSendCells[Pstream::myProcNo()] = countCells(distribution);
1810 Pstream::gatherList(nSendCells);
1811 Pstream::scatterList(nSendCells);
1815 PstreamBuffers pBufs(Pstream::nonBlocking);
1818 // What to send to neighbouring domains
1819 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1821 forAll(nSendCells[Pstream::myProcNo()], recvProc)
1825 recvProc != Pstream::myProcNo()
1826 && nSendCells[Pstream::myProcNo()][recvProc] > 0
1834 << "SUBSETTING FOR DOMAIN " << recvProc
1835 << " cells to send:"
1836 << nSendCells[Pstream::myProcNo()][recvProc]
1840 // Pstream for sending mesh and fields
1841 //OPstream str(Pstream::blocking, recvProc);
1842 UOPstream str(recvProc, pBufs);
1844 // Mesh subsetting engine
1845 fvMeshSubset subsetter(mesh_);
1847 // Subset the cells of the current domain.
1848 subsetter.setLargeCellSubset
1852 oldInternalPatchI, // oldInternalFaces patch
1853 false // no parallel sync
1856 subCellMap[recvProc] = subsetter.cellMap();
1857 subFaceMap[recvProc] = renumber
1862 subPointMap[recvProc] = subsetter.pointMap();
1863 subPatchMap[recvProc] = subsetter.patchMap();
1866 // Subset the boundary fields (owner/neighbour/processor)
1867 labelList procSourceFace;
1868 labelList procSourceProc;
1869 labelList procSourcePatch;
1870 labelList procSourceNewNbrProc;
1874 subsetter.subMesh(),
1875 subsetter.faceMap(), // from subMesh to mesh
1876 subsetter.cellMap(), // ,, ,,
1878 distribution, // old mesh distribution
1879 mesh_.faceOwner(), // old owner
1880 mesh_.faceNeighbour(),
1881 mesh_.nInternalFaces(),
1891 procSourceNewNbrProc
1896 // Send to neighbour
1900 subsetter.subMesh(),
1909 procSourceNewNbrProc,
1912 sendFields<volScalarField>(recvProc, volScalars, subsetter, str);
1913 sendFields<volVectorField>(recvProc, volVectors, subsetter, str);
1914 sendFields<volSphericalTensorField>
1921 sendFields<volSymmTensorField>
1928 sendFields<volTensorField>(recvProc, volTensors, subsetter, str);
1930 sendFields<surfaceScalarField>
1937 sendFields<surfaceVectorField>
1944 sendFields<surfaceSphericalTensorField>
1951 sendFields<surfaceSymmTensorField>
1958 sendFields<surfaceTensorField>
1969 // Start sending&receiving from buffers
1970 pBufs.finishedSends();
1973 // Subset the part that stays
1974 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
1977 // Save old mesh maps before changing mesh
1978 const labelList oldFaceOwner(mesh_.faceOwner());
1979 const labelList oldFaceNeighbour(mesh_.faceNeighbour());
1980 const label oldInternalFaces = mesh_.nInternalFaces();
1983 autoPtr<mapPolyMesh> subMap
1987 select(false, distribution, Pstream::myProcNo()),
1992 // Addressing from subsetted mesh
1993 subCellMap[Pstream::myProcNo()] = subMap().cellMap();
1994 subFaceMap[Pstream::myProcNo()] = renumber
1999 subPointMap[Pstream::myProcNo()] = subMap().pointMap();
2000 subPatchMap[Pstream::myProcNo()] = identity(patches.size());
2002 // Initialize all addressing into current mesh
2003 constructCellMap[Pstream::myProcNo()] = identity(mesh_.nCells());
2004 constructFaceMap[Pstream::myProcNo()] = identity(mesh_.nFaces());
2005 constructPointMap[Pstream::myProcNo()] = identity(mesh_.nPoints());
2006 constructPatchMap[Pstream::myProcNo()] = identity(patches.size());
2008 // Subset the mesh data: neighbourCell/neighbourProc
2010 labelList domainSourceFace;
2011 labelList domainSourceProc;
2012 labelList domainSourcePatch;
2013 labelList domainSourceNewNbrProc;
2018 subMap().faceMap(), // from new to original mesh
2021 distribution, // distribution before subsetting
2022 oldFaceOwner, // owner before subsetting
2023 oldFaceNeighbour, // neighbour ,,
2024 oldInternalFaces, // nInternalFaces ,,
2034 domainSourceNewNbrProc
2037 sourceFace.transfer(domainSourceFace);
2038 sourceProc.transfer(domainSourceProc);
2039 sourcePatch.transfer(domainSourcePatch);
2040 sourceNewNbrProc.transfer(domainSourceNewNbrProc);
2047 Pout<< nl << "STARTING MESH:" << endl;
2048 printMeshInfo(mesh_);
2049 printFieldInfo<volScalarField>(mesh_);
2050 printFieldInfo<volVectorField>(mesh_);
2051 printFieldInfo<volSphericalTensorField>(mesh_);
2052 printFieldInfo<volSymmTensorField>(mesh_);
2053 printFieldInfo<volTensorField>(mesh_);
2054 printFieldInfo<surfaceScalarField>(mesh_);
2055 printFieldInfo<surfaceVectorField>(mesh_);
2056 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2057 printFieldInfo<surfaceSymmTensorField>(mesh_);
2058 printFieldInfo<surfaceTensorField>(mesh_);
2064 // Receive and add what was sent
2065 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2067 forAll(nSendCells, sendProc)
2069 // Did processor sendProc send anything to me?
2072 sendProc != Pstream::myProcNo()
2073 && nSendCells[sendProc][Pstream::myProcNo()] > 0
2079 << "RECEIVING FROM DOMAIN " << sendProc
2080 << " cells to receive:"
2081 << nSendCells[sendProc][Pstream::myProcNo()]
2086 // Pstream for receiving mesh and fields
2087 UIPstream str(sendProc, pBufs);
2090 // Receive from sendProc
2091 labelList domainSourceFace;
2092 labelList domainSourceProc;
2093 labelList domainSourcePatch;
2094 labelList domainSourceNewNbrProc;
2096 autoPtr<fvMesh> domainMeshPtr;
2097 PtrList<volScalarField> vsf;
2098 PtrList<volVectorField> vvf;
2099 PtrList<volSphericalTensorField> vsptf;
2100 PtrList<volSymmTensorField> vsytf;
2101 PtrList<volTensorField> vtf;
2102 PtrList<surfaceScalarField> ssf;
2103 PtrList<surfaceVectorField> svf;
2104 PtrList<surfaceSphericalTensorField> ssptf;
2105 PtrList<surfaceSymmTensorField> ssytf;
2106 PtrList<surfaceTensorField> stf;
2108 // Opposite of sendMesh
2110 domainMeshPtr = receiveMesh
2117 const_cast<Time&>(mesh_.time()),
2121 domainSourceNewNbrProc,
2124 fvMesh& domainMesh = domainMeshPtr();
2125 // Force construction of various on mesh.
2126 //(void)domainMesh.globalData();
2129 // Receive fields. Read as single dictionary because
2130 // of problems reading consecutive fields from single stream.
2131 dictionary fieldDicts(str);
2133 receiveFields<volScalarField>
2139 fieldDicts.subDict(volScalarField::typeName)
2141 receiveFields<volVectorField>
2147 fieldDicts.subDict(volVectorField::typeName)
2149 receiveFields<volSphericalTensorField>
2155 fieldDicts.subDict(volSphericalTensorField::typeName)
2157 receiveFields<volSymmTensorField>
2163 fieldDicts.subDict(volSymmTensorField::typeName)
2165 receiveFields<volTensorField>
2171 fieldDicts.subDict(volTensorField::typeName)
2174 receiveFields<surfaceScalarField>
2180 fieldDicts.subDict(surfaceScalarField::typeName)
2182 receiveFields<surfaceVectorField>
2188 fieldDicts.subDict(surfaceVectorField::typeName)
2190 receiveFields<surfaceSphericalTensorField>
2196 fieldDicts.subDict(surfaceSphericalTensorField::typeName)
2198 receiveFields<surfaceSymmTensorField>
2204 fieldDicts.subDict(surfaceSymmTensorField::typeName)
2206 receiveFields<surfaceTensorField>
2212 fieldDicts.subDict(surfaceTensorField::typeName)
2215 const fvMesh& domainMesh = domainMeshPtr();
2218 constructCellMap[sendProc] = identity(domainMesh.nCells());
2219 constructFaceMap[sendProc] = identity(domainMesh.nFaces());
2220 constructPointMap[sendProc] = identity(domainMesh.nPoints());
2221 constructPatchMap[sendProc] =
2222 identity(domainMesh.boundaryMesh().size());
2228 Pout<< nl << "RECEIVED MESH FROM:" << sendProc << endl;
2229 printMeshInfo(domainMesh);
2230 printFieldInfo<volScalarField>(domainMesh);
2231 printFieldInfo<volVectorField>(domainMesh);
2232 printFieldInfo<volSphericalTensorField>(domainMesh);
2233 printFieldInfo<volSymmTensorField>(domainMesh);
2234 printFieldInfo<volTensorField>(domainMesh);
2235 printFieldInfo<surfaceScalarField>(domainMesh);
2236 printFieldInfo<surfaceVectorField>(domainMesh);
2237 printFieldInfo<surfaceSphericalTensorField>(domainMesh);
2238 printFieldInfo<surfaceSymmTensorField>(domainMesh);
2239 printFieldInfo<surfaceTensorField>(domainMesh);
2243 // Now this mesh we received (from sendProc) needs to be merged
2244 // with the current mesh. On the current mesh we have for all
2245 // boundaryfaces the original face and processor. See if we can
2246 // match these up to the received domainSourceFace and
2247 // domainSourceProc.
2248 labelList masterCoupledFaces;
2249 labelList slaveCoupledFaces;
2268 // Generate additional coupling info (points, edges) from
2270 faceCoupleInfo couples
2276 mergeTol_, // merge tolerance
2277 true, // faces align
2278 true, // couples are ordered already
2283 // Add domainMesh to mesh
2284 // ~~~~~~~~~~~~~~~~~~~~~~
2286 autoPtr<mapAddedPolyMesh> map = fvMeshAdder::add
2291 false // no parallel comms
2294 // Update mesh data: sourceFace,sourceProc for added
2297 sourceFace = mapBoundaryData
2302 domainMesh.nInternalFaces(),
2305 sourceProc = mapBoundaryData
2310 domainMesh.nInternalFaces(),
2313 sourcePatch = mapBoundaryData
2318 domainMesh.nInternalFaces(),
2321 sourceNewNbrProc = mapBoundaryData
2326 domainMesh.nInternalFaces(),
2327 domainSourceNewNbrProc
2330 // Update all addressing so xxProcAddressing points to correct item
2332 const labelList& oldCellMap = map().oldCellMap();
2333 const labelList& oldFaceMap = map().oldFaceMap();
2334 const labelList& oldPointMap = map().oldPointMap();
2335 const labelList& oldPatchMap = map().oldPatchMap();
2337 forAll(constructPatchMap, procI)
2339 if (procI != sendProc && constructPatchMap[procI].size())
2341 // Processor already in mesh (either myProcNo or received)
2342 inplaceRenumber(oldCellMap, constructCellMap[procI]);
2343 inplaceRenumber(oldFaceMap, constructFaceMap[procI]);
2344 inplaceRenumber(oldPointMap, constructPointMap[procI]);
2345 inplaceRenumber(oldPatchMap, constructPatchMap[procI]);
2350 inplaceRenumber(map().addedCellMap(), constructCellMap[sendProc]);
2351 inplaceRenumber(map().addedFaceMap(), constructFaceMap[sendProc]);
2352 inplaceRenumber(map().addedPointMap(), constructPointMap[sendProc]);
2353 inplaceRenumber(map().addedPatchMap(), constructPatchMap[sendProc]);
2357 Pout<< nl << "MERGED MESH FROM:" << sendProc << endl;
2358 printMeshInfo(mesh_);
2359 printFieldInfo<volScalarField>(mesh_);
2360 printFieldInfo<volVectorField>(mesh_);
2361 printFieldInfo<volSphericalTensorField>(mesh_);
2362 printFieldInfo<volSymmTensorField>(mesh_);
2363 printFieldInfo<volTensorField>(mesh_);
2364 printFieldInfo<surfaceScalarField>(mesh_);
2365 printFieldInfo<surfaceVectorField>(mesh_);
2366 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2367 printFieldInfo<surfaceSymmTensorField>(mesh_);
2368 printFieldInfo<surfaceTensorField>(mesh_);
2378 Pout<< nl << "REDISTRIBUTED MESH:" << endl;
2379 printMeshInfo(mesh_);
2380 printFieldInfo<volScalarField>(mesh_);
2381 printFieldInfo<volVectorField>(mesh_);
2382 printFieldInfo<volSphericalTensorField>(mesh_);
2383 printFieldInfo<volSymmTensorField>(mesh_);
2384 printFieldInfo<volTensorField>(mesh_);
2385 printFieldInfo<surfaceScalarField>(mesh_);
2386 printFieldInfo<surfaceVectorField>(mesh_);
2387 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2388 printFieldInfo<surfaceSymmTensorField>(mesh_);
2389 printFieldInfo<surfaceTensorField>(mesh_);
2395 // Add processorPatches
2396 // ~~~~~~~~~~~~~~~~~~~~
2398 // Per neighbour processor, per originating patch, the patchID
2399 // For faces resulting from internal faces or normal processor patches
2400 // the originating patch is -1. For cyclics this is the cyclic patchID.
2401 List<Map<label> > procPatchID;
2403 // Add processor and processorCyclic patches.
2404 addProcPatches(sourceNewNbrProc, sourcePatch, procPatchID);
2406 // Put faces into correct patch. Note that we now have proper
2407 // processorPolyPatches again so repatching will take care of coupled face
2410 // Get boundary faces to be repatched. Is -1 or new patchID
2411 labelList newPatchID
2421 // Change patches. Since this might change ordering of coupled faces
2422 // we also need to adapt our constructMaps.
2423 repatch(newPatchID, constructFaceMap);
2425 // See if any geometrically shared points need to be merged. Note: does
2427 mergeSharedPoints(constructPointMap);
2429 // Bit of hack: processorFvPatchField does not get reset since created
2430 // from nothing so explicitly reset.
2431 initPatchFields<volScalarField, processorFvPatchField<scalar> >
2433 pTraits<scalar>::zero
2435 initPatchFields<volVectorField, processorFvPatchField<vector> >
2437 pTraits<vector>::zero
2441 volSphericalTensorField,
2442 processorFvPatchField<sphericalTensor>
2445 pTraits<sphericalTensor>::zero
2447 initPatchFields<volSymmTensorField, processorFvPatchField<symmTensor> >
2449 pTraits<symmTensor>::zero
2451 initPatchFields<volTensorField, processorFvPatchField<tensor> >
2453 pTraits<tensor>::zero
2455 initPatchFields<surfaceScalarField, processorFvsPatchField<scalar> >
2457 pTraits<scalar>::zero
2459 initPatchFields<surfaceVectorField, processorFvsPatchField<vector> >
2461 pTraits<vector>::zero
2465 surfaceSphericalTensorField,
2466 processorFvsPatchField<sphericalTensor>
2469 pTraits<sphericalTensor>::zero
2473 surfaceSymmTensorField,
2474 processorFvsPatchField<symmTensor>
2477 pTraits<symmTensor>::zero
2479 initPatchFields<surfaceTensorField, processorFvsPatchField<tensor> >
2481 pTraits<tensor>::zero
2485 mesh_.setInstance(mesh_.time().timeName());
2491 Pout<< nl << "FINAL MESH:" << endl;
2492 printMeshInfo(mesh_);
2493 printFieldInfo<volScalarField>(mesh_);
2494 printFieldInfo<volVectorField>(mesh_);
2495 printFieldInfo<volSphericalTensorField>(mesh_);
2496 printFieldInfo<volSymmTensorField>(mesh_);
2497 printFieldInfo<volTensorField>(mesh_);
2498 printFieldInfo<surfaceScalarField>(mesh_);
2499 printFieldInfo<surfaceVectorField>(mesh_);
2500 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2501 printFieldInfo<surfaceSymmTensorField>(mesh_);
2502 printFieldInfo<surfaceTensorField>(mesh_);
2506 // Collect all maps and return
2507 return autoPtr<mapDistributePolyMesh>
2509 new mapDistributePolyMesh
2516 oldPatchStarts.xfer(),
2517 oldPatchNMeshPoints.xfer(),
2524 constructPointMap.xfer(),
2525 constructFaceMap.xfer(),
2526 constructCellMap.xfer(),
2527 constructPatchMap.xfer()
2533 // ************************************************************************* //