1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "CompactListList_dev.H"
28 #include "fvMeshDistribute.H"
29 #include "PstreamCombineReduceOps.H"
30 #include "fvMeshAdder.H"
31 #include "faceCoupleInfo.H"
32 #include "processorFvPatchField.H"
33 #include "processorFvsPatchField.H"
34 #include "directTopoChange.H"
35 #include "removeCells.H"
36 #include "polyModifyFace.H"
37 #include "polyRemovePoint.H"
38 #include "mergePoints.H"
39 #include "mapDistributePolyMesh.H"
40 #include "surfaceFields.H"
41 #include "syncTools.H"
43 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45 defineTypeNameAndDebug(Foam::fvMeshDistribute, 0);
48 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
50 Foam::labelList Foam::fvMeshDistribute::select
52 const bool selectEqual,
53 const labelList& values,
61 if (selectEqual == (values[i] == value))
72 if (selectEqual == (values[i] == value))
81 // Check all procs have same names and in exactly same order.
82 void Foam::fvMeshDistribute::checkEqualWordList
88 List<wordList> allNames(Pstream::nProcs());
89 allNames[Pstream::myProcNo()] = lst;
90 Pstream::gatherList(allNames);
91 Pstream::scatterList(allNames);
93 for (label procI = 1; procI < Pstream::nProcs(); procI++)
95 if (allNames[procI] != allNames[0])
97 FatalErrorIn("fvMeshDistribute::checkEqualWordList(..)")
98 << "When checking for equal " << msg.c_str() << " :" << endl
99 << "processor0 has:" << allNames[0] << endl
100 << "processor" << procI << " has:" << allNames[procI] << endl
101 << msg.c_str() << " need to be synchronised on all processors."
108 Foam::wordList Foam::fvMeshDistribute::mergeWordList(const wordList& procNames)
110 List<wordList> allNames(Pstream::nProcs());
111 allNames[Pstream::myProcNo()] = procNames;
112 Pstream::gatherList(allNames);
113 Pstream::scatterList(allNames);
115 HashSet<word> mergedNames;
116 forAll(allNames, procI)
118 forAll(allNames[procI], i)
120 mergedNames.insert(allNames[procI][i]);
123 return mergedNames.toc();
127 // Print some info on mesh.
128 void Foam::fvMeshDistribute::printMeshInfo(const fvMesh& mesh)
130 Pout<< "Primitives:" << nl
131 << " points :" << mesh.nPoints() << nl
132 << " internalFaces:" << mesh.nInternalFaces() << nl
133 << " faces :" << mesh.nFaces() << nl
134 << " cells :" << mesh.nCells() << nl;
136 const fvBoundaryMesh& patches = mesh.boundary();
138 Pout<< "Patches:" << endl;
139 forAll(patches, patchI)
141 const polyPatch& pp = patches[patchI].patch();
143 Pout<< " " << patchI << " name:" << pp.name()
144 << " size:" << pp.size()
145 << " start:" << pp.start()
146 << " type:" << pp.type()
150 if (mesh.pointZones().size())
152 Pout<< "PointZones:" << endl;
153 forAll(mesh.pointZones(), zoneI)
155 const pointZone& pz = mesh.pointZones()[zoneI];
156 Pout<< " " << zoneI << " name:" << pz.name()
157 << " size:" << pz.size()
161 if (mesh.faceZones().size())
163 Pout<< "FaceZones:" << endl;
164 forAll(mesh.faceZones(), zoneI)
166 const faceZone& fz = mesh.faceZones()[zoneI];
167 Pout<< " " << zoneI << " name:" << fz.name()
168 << " size:" << fz.size()
172 if (mesh.cellZones().size())
174 Pout<< "CellZones:" << endl;
175 forAll(mesh.cellZones(), zoneI)
177 const cellZone& cz = mesh.cellZones()[zoneI];
178 Pout<< " " << zoneI << " name:" << cz.name()
179 << " size:" << cz.size()
186 void Foam::fvMeshDistribute::printCoupleInfo
188 const primitiveMesh& mesh,
189 const labelList& sourceFace,
190 const labelList& sourceProc,
191 const labelList& sourceNewProc
195 << "Current coupling info:"
198 forAll(sourceFace, bFaceI)
200 label meshFaceI = mesh.nInternalFaces() + bFaceI;
202 Pout<< " meshFace:" << meshFaceI
203 << " fc:" << mesh.faceCentres()[meshFaceI]
204 << " connects to proc:" << sourceProc[bFaceI]
205 << "/face:" << sourceFace[bFaceI]
206 << " which will move to proc:" << sourceNewProc[bFaceI]
212 // Finds (non-empty) patch that exposed internal and proc faces can be put into
213 Foam::label Foam::fvMeshDistribute::findNonEmptyPatch() const
215 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
217 label nonEmptyPatchI = -1;
219 forAllReverse(patches, patchI)
221 const polyPatch& pp = patches[patchI];
223 if (!isA<emptyPolyPatch>(pp) && !pp.coupled())
225 nonEmptyPatchI = patchI;
230 if (nonEmptyPatchI == -1)
232 FatalErrorIn("fvMeshDistribute::findNonEmptyPatch() const")
233 << "Cannot find a patch which is neither of type empty nor"
234 << " coupled in patches " << patches.names() << endl
235 << "There has to be at least one such patch for"
236 << " distribution to work" << abort(FatalError);
241 Pout<< "findNonEmptyPatch : using patch " << nonEmptyPatchI
242 << " name:" << patches[nonEmptyPatchI].name()
243 << " type:" << patches[nonEmptyPatchI].type()
244 << " to put exposed faces into." << endl;
248 // Do additional test for processor patches intermingled with non-proc
250 label procPatchI = -1;
252 forAll(patches, patchI)
254 if (isA<processorPolyPatch>(patches[patchI]))
258 else if (procPatchI != -1)
260 FatalErrorIn("fvMeshDistribute::findNonEmptyPatch() const")
261 << "Processor patches should be at end of patch list."
263 << "Have processor patch " << procPatchI
264 << " followed by non-processor patch " << patchI
265 << " in patches " << patches.names()
266 << abort(FatalError);
270 return nonEmptyPatchI;
274 // Appends processorPolyPatch. Returns patchID.
275 Foam::label Foam::fvMeshDistribute::addProcPatch
277 const word& patchName,
281 // Clear local fields and e.g. polyMesh globalMeshData.
285 polyBoundaryMesh& polyPatches =
286 const_cast<polyBoundaryMesh&>(mesh_.boundaryMesh());
287 fvBoundaryMesh& fvPatches = const_cast<fvBoundaryMesh&>(mesh_.boundary());
289 if (polyPatches.findPatchID(patchName) != -1)
293 "fvMeshDistribute::addProcPatch(const word&, const label)"
294 ) << "Cannot create patch " << patchName
295 << " since it already exists." << nl
296 << "Current patch names:" << polyPatches.names()
305 label sz = polyPatches.size();
308 polyPatches.setSize(sz+1);
312 new processorPolyPatch
318 mesh_.boundaryMesh(),
323 fvPatches.setSize(sz+1);
329 polyPatches[sz], // point to newly added polyPatch
338 // Deletes last patch
339 void Foam::fvMeshDistribute::deleteTrailingPatch()
341 // Clear local fields and e.g. polyMesh globalMeshData.
344 polyBoundaryMesh& polyPatches =
345 const_cast<polyBoundaryMesh&>(mesh_.boundaryMesh());
346 fvBoundaryMesh& fvPatches = const_cast<fvBoundaryMesh&>(mesh_.boundary());
348 if (polyPatches.empty())
350 FatalErrorIn("fvMeshDistribute::deleteTrailingPatch(fvMesh&)")
351 << "No patches in mesh"
352 << abort(FatalError);
355 label sz = polyPatches.size();
357 label nFaces = polyPatches[sz-1].size();
359 // Remove last polyPatch
362 Pout<< "deleteTrailingPatch : Removing patch " << sz-1
363 << " : " << polyPatches[sz-1].name() << " size:" << nFaces << endl;
368 FatalErrorIn("fvMeshDistribute::deleteTrailingPatch()")
369 << "There are still " << nFaces << " faces in patch to be deleted "
370 << sz-1 << ' ' << polyPatches[sz-1].name()
371 << abort(FatalError);
374 // Remove actual patch
375 polyPatches.setSize(sz-1);
376 fvPatches.setSize(sz-1);
380 // Delete all processor patches. Move any processor faces into the last
381 // non-processor patch.
382 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::deleteProcPatches
384 const label destinationPatch
387 // New patchID per boundary faces to be repatched. Is -1 (no change)
389 labelList newPatchID(mesh_.nFaces() - mesh_.nInternalFaces(), -1);
391 label nProcPatches = 0;
393 forAll(mesh_.boundaryMesh(), patchI)
395 const polyPatch& pp = mesh_.boundaryMesh()[patchI];
397 if (isA<processorPolyPatch>(pp))
401 Pout<< "Moving all faces of patch " << pp.name()
402 << " into patch " << destinationPatch
406 label offset = pp.start() - mesh_.nInternalFaces();
410 newPatchID[offset+i] = destinationPatch;
417 // Note: order of boundary faces been kept the same since the
418 // destinationPatch is at the end and we have visited the patches in
419 // incremental order.
420 labelListList dummyFaceMaps;
421 autoPtr<mapPolyMesh> map = repatch(newPatchID, dummyFaceMaps);
424 // Delete (now empty) processor patches.
425 forAllReverse(mesh_.boundaryMesh(), patchI)
427 const polyPatch& pp = mesh_.boundaryMesh()[patchI];
429 if (isA<processorPolyPatch>(pp))
431 deleteTrailingPatch();
432 deleteTrailingPatchFields<volScalarField>();
433 deleteTrailingPatchFields<volVectorField>();
434 deleteTrailingPatchFields<volSphericalTensorField>();
435 deleteTrailingPatchFields<volSymmTensorField>();
436 deleteTrailingPatchFields<volTensorField>();
438 deleteTrailingPatchFields<surfaceScalarField>();
439 deleteTrailingPatchFields<surfaceVectorField>();
440 deleteTrailingPatchFields<surfaceSphericalTensorField>();
441 deleteTrailingPatchFields<surfaceSymmTensorField>();
442 deleteTrailingPatchFields<surfaceTensorField>();
451 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::repatch
453 const labelList& newPatchID, // per boundary face -1 or new patchID
454 labelListList& constructFaceMap
457 directTopoChange meshMod(mesh_);
459 forAll(newPatchID, bFaceI)
461 if (newPatchID[bFaceI] != -1)
463 label faceI = mesh_.nInternalFaces() + bFaceI;
465 label zoneID = mesh_.faceZones().whichZone(faceI);
466 bool zoneFlip = false;
470 const faceZone& fZone = mesh_.faceZones()[zoneID];
471 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
478 mesh_.faces()[faceI], // modified face
479 faceI, // label of face
480 mesh_.faceOwner()[faceI], // owner
483 newPatchID[bFaceI], // patch for face
484 false, // remove from zone
485 zoneID, // zone for face
486 zoneFlip // face flip in zone
493 // Do mapping of fields from one patchField to the other ourselves since
494 // is currently not supported by updateMesh.
496 // Store boundary fields (we only do this for surfaceFields)
497 PtrList<FieldField<fvsPatchField, scalar> > sFlds;
498 saveBoundaryFields<scalar, surfaceMesh>(sFlds);
499 PtrList<FieldField<fvsPatchField, vector> > vFlds;
500 saveBoundaryFields<vector, surfaceMesh>(vFlds);
501 PtrList<FieldField<fvsPatchField, sphericalTensor> > sptFlds;
502 saveBoundaryFields<sphericalTensor, surfaceMesh>(sptFlds);
503 PtrList<FieldField<fvsPatchField, symmTensor> > sytFlds;
504 saveBoundaryFields<symmTensor, surfaceMesh>(sytFlds);
505 PtrList<FieldField<fvsPatchField, tensor> > tFlds;
506 saveBoundaryFields<tensor, surfaceMesh>(tFlds);
508 // Change the mesh (no inflation). Note: parallel comms allowed.
509 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
511 // Update fields. No inflation, parallel sync.
512 mesh_.updateMesh(map);
514 // Map patch fields using stored boundary fields. Note: assumes order
515 // of fields has not changed in object registry!
516 mapBoundaryFields<scalar, surfaceMesh>(map, sFlds);
517 mapBoundaryFields<vector, surfaceMesh>(map, vFlds);
518 mapBoundaryFields<sphericalTensor, surfaceMesh>(map, sptFlds);
519 mapBoundaryFields<symmTensor, surfaceMesh>(map, sytFlds);
520 mapBoundaryFields<tensor, surfaceMesh>(map, tFlds);
523 // Move mesh (since morphing does not do this)
524 if (map().hasMotionPoints())
526 mesh_.movePoints(map().preMotionPoints());
529 // Adapt constructMaps.
533 label index = findIndex(map().reverseFaceMap(), -1);
539 "fvMeshDistribute::repatch(const labelList&, labelListList&)"
540 ) << "reverseFaceMap contains -1 at index:"
542 << "This means that the repatch operation was not just"
543 << " a shuffle?" << abort(FatalError);
547 forAll(constructFaceMap, procI)
549 inplaceRenumber(map().reverseFaceMap(), constructFaceMap[procI]);
557 // Detect shared points. Need processor patches to be present.
558 // Background: when adding bits of mesh one can get points which
559 // share the same position but are only detectable to be topologically
560 // the same point when doing parallel analysis. This routine will
561 // merge those points.
562 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::mergeSharedPoints
564 labelListList& constructPointMap
567 // Find out which sets of points get merged and create a map from
568 // mesh point to unique point.
569 Map<label> pointToMaster
571 fvMeshAdder::findSharedPoints
578 if (returnReduce(pointToMaster.size(), sumOp<label>()) == 0)
580 return autoPtr<mapPolyMesh>(NULL);
583 directTopoChange meshMod(mesh_);
585 fvMeshAdder::mergePoints(mesh_, pointToMaster, meshMod);
587 // Change the mesh (no inflation). Note: parallel comms allowed.
588 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
590 // Update fields. No inflation, parallel sync.
591 mesh_.updateMesh(map);
593 // Adapt constructMaps for merged points.
594 forAll(constructPointMap, procI)
596 labelList& constructMap = constructPointMap[procI];
598 forAll(constructMap, i)
600 label oldPointI = constructMap[i];
602 label newPointI = map().reversePointMap()[oldPointI];
606 constructMap[i] = -newPointI-2;
608 else if (newPointI >= 0)
610 constructMap[i] = newPointI;
614 FatalErrorIn("fvMeshDistribute::mergeSharedPoints()")
615 << "Problem. oldPointI:" << oldPointI
616 << " newPointI:" << newPointI << abort(FatalError);
624 // Construct the local environment of all boundary faces.
625 void Foam::fvMeshDistribute::getNeighbourData
627 const labelList& distribution,
628 labelList& sourceFace,
629 labelList& sourceProc,
630 labelList& sourceNewProc
633 label nBnd = mesh_.nFaces() - mesh_.nInternalFaces();
634 sourceFace.setSize(nBnd);
635 sourceProc.setSize(nBnd);
636 sourceNewProc.setSize(nBnd);
638 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
640 // Get neighbouring meshFace labels and new processor of coupled boundaries
641 labelList nbrFaces(nBnd, -1);
642 labelList nbrNewProc(nBnd, -1);
644 forAll(patches, patchI)
646 const polyPatch& pp = patches[patchI];
648 if (isA<processorPolyPatch>(pp))
650 label offset = pp.start() - mesh_.nInternalFaces();
652 // Mesh labels of faces on this side
655 label bndI = offset + i;
656 nbrFaces[bndI] = pp.start()+i;
659 // Which processor they will end up on
660 SubList<label>(nbrNewProc, pp.size(), offset).assign
662 UIndirectList<label>(distribution, pp.faceCells())()
668 // Exchange the boundary data
669 syncTools::swapBoundaryFaceList(mesh_, nbrFaces, false);
670 syncTools::swapBoundaryFaceList(mesh_, nbrNewProc, false);
673 forAll(patches, patchI)
675 const polyPatch& pp = patches[patchI];
676 label offset = pp.start() - mesh_.nInternalFaces();
678 if (isA<processorPolyPatch>(pp))
680 const processorPolyPatch& procPatch =
681 refCast<const processorPolyPatch>(pp);
683 // Check which of the two faces we store.
685 if (Pstream::myProcNo() < procPatch.neighbProcNo())
687 // Use my local face labels
690 label bndI = offset + i;
691 sourceFace[bndI] = pp.start()+i;
692 sourceProc[bndI] = Pstream::myProcNo();
693 sourceNewProc[bndI] = nbrNewProc[bndI];
698 // Use my neighbours face labels
701 label bndI = offset + i;
702 sourceFace[bndI] = nbrFaces[bndI];
703 sourceProc[bndI] = procPatch.neighbProcNo();
704 sourceNewProc[bndI] = nbrNewProc[bndI];
710 // Normal (physical) boundary
713 label bndI = offset + i;
714 sourceFace[bndI] = patchI;
715 sourceProc[bndI] = -1;
716 sourceNewProc[bndI] = -1;
723 // Subset the neighbourCell/neighbourProc fields
724 void Foam::fvMeshDistribute::subsetBoundaryData
727 const labelList& faceMap,
728 const labelList& cellMap,
730 const labelList& oldDistribution,
731 const labelList& oldFaceOwner,
732 const labelList& oldFaceNeighbour,
733 const label oldInternalFaces,
735 const labelList& sourceFace,
736 const labelList& sourceProc,
737 const labelList& sourceNewProc,
741 labelList& subNewProc
744 subFace.setSize(mesh.nFaces() - mesh.nInternalFaces());
745 subProc.setSize(mesh.nFaces() - mesh.nInternalFaces());
746 subNewProc.setSize(mesh.nFaces() - mesh.nInternalFaces());
748 forAll(subFace, newBFaceI)
750 label newFaceI = newBFaceI + mesh.nInternalFaces();
752 label oldFaceI = faceMap[newFaceI];
754 // Was oldFaceI internal face? If so which side did we get.
755 if (oldFaceI < oldInternalFaces)
757 subFace[newBFaceI] = oldFaceI;
758 subProc[newBFaceI] = Pstream::myProcNo();
760 label oldOwn = oldFaceOwner[oldFaceI];
761 label oldNei = oldFaceNeighbour[oldFaceI];
763 if (oldOwn == cellMap[mesh.faceOwner()[newFaceI]])
765 // We kept the owner side. Where does the neighbour move to?
766 subNewProc[newBFaceI] = oldDistribution[oldNei];
770 // We kept the neighbour side.
771 subNewProc[newBFaceI] = oldDistribution[oldOwn];
776 // Was boundary face. Take over boundary information
777 label oldBFaceI = oldFaceI - oldInternalFaces;
779 subFace[newBFaceI] = sourceFace[oldBFaceI];
780 subProc[newBFaceI] = sourceProc[oldBFaceI];
781 subNewProc[newBFaceI] = sourceNewProc[oldBFaceI];
787 // Find cells on mesh whose faceID/procID match the neighbour cell/proc of
788 // domainMesh. Store the matching face.
789 void Foam::fvMeshDistribute::findCouples
791 const primitiveMesh& mesh,
792 const labelList& sourceFace,
793 const labelList& sourceProc,
796 const primitiveMesh& domainMesh,
797 const labelList& domainFace,
798 const labelList& domainProc,
800 labelList& masterCoupledFaces,
801 labelList& slaveCoupledFaces
804 // Store domain neighbour as map so we can easily look for pair
805 // with same face+proc.
806 HashTable<label, labelPair, labelPair::Hash<> > map(domainFace.size());
808 forAll(domainFace, bFaceI)
810 map.insert(labelPair(domainFace[bFaceI], domainProc[bFaceI]), bFaceI);
814 // Try to match mesh data.
816 masterCoupledFaces.setSize(domainFace.size());
817 slaveCoupledFaces.setSize(domainFace.size());
820 forAll(sourceFace, bFaceI)
822 if (sourceProc[bFaceI] != -1)
824 labelPair myData(sourceFace[bFaceI], sourceProc[bFaceI]);
826 HashTable<label, labelPair, labelPair::Hash<> >::const_iterator
827 iter = map.find(myData);
829 if (iter != map.end())
831 label nbrBFaceI = iter();
833 masterCoupledFaces[coupledI] = mesh.nInternalFaces() + bFaceI;
834 slaveCoupledFaces[coupledI] =
835 domainMesh.nInternalFaces()
843 masterCoupledFaces.setSize(coupledI);
844 slaveCoupledFaces.setSize(coupledI);
848 Pout<< "findCouples : found " << coupledI
849 << " faces that will be stitched" << nl << endl;
854 // Map data on boundary faces to new mesh (resulting from adding two meshes)
855 Foam::labelList Foam::fvMeshDistribute::mapBoundaryData
857 const primitiveMesh& mesh, // mesh after adding
858 const mapAddedPolyMesh& map,
859 const labelList& boundaryData0, // mesh before adding
860 const label nInternalFaces1,
861 const labelList& boundaryData1 // added mesh
864 labelList newBoundaryData(mesh.nFaces() - mesh.nInternalFaces());
866 forAll(boundaryData0, oldBFaceI)
868 label newFaceI = map.oldFaceMap()[oldBFaceI + map.nOldInternalFaces()];
870 // Face still exists (is necessary?) and still boundary face
871 if (newFaceI >= 0 && newFaceI >= mesh.nInternalFaces())
873 newBoundaryData[newFaceI - mesh.nInternalFaces()] =
874 boundaryData0[oldBFaceI];
878 forAll(boundaryData1, addedBFaceI)
880 label newFaceI = map.addedFaceMap()[addedBFaceI + nInternalFaces1];
882 if (newFaceI >= 0 && newFaceI >= mesh.nInternalFaces())
884 newBoundaryData[newFaceI - mesh.nInternalFaces()] =
885 boundaryData1[addedBFaceI];
889 return newBoundaryData;
893 // Remove cells. Add all exposed faces to patch oldInternalPatchI
894 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::doRemoveCells
896 const labelList& cellsToRemove,
897 const label oldInternalPatchI
900 // Mesh change engine
901 directTopoChange meshMod(mesh_);
903 // Cell removal topo engine. Do NOT synchronize parallel since
904 // we are doing a local cell removal.
905 removeCells cellRemover(mesh_, false);
907 // Get all exposed faces
908 labelList exposedFaces(cellRemover.getExposedFaces(cellsToRemove));
910 // Insert the topo changes
911 cellRemover.setRefinement
915 labelList(exposedFaces.size(), oldInternalPatchI), // patch for exposed
920 // Change the mesh. No inflation. Note: no parallel comms allowed.
921 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, false);
924 mesh_.updateMesh(map);
926 // Move mesh (since morphing does not do this)
927 if (map().hasMotionPoints())
929 mesh_.movePoints(map().preMotionPoints());
936 // Delete and add processor patches. Changes mesh and returns per
937 // neighbour processor the processor patchID.
938 void Foam::fvMeshDistribute::addProcPatches
940 const labelList& neighbourNewProc, // processor that neighbour is on
941 labelList& procPatchID
944 // Now use the neighbourFace/Proc to repatch the mesh. These two lists
945 // contain for all current boundary faces the global patchID (for non-proc
946 // patch) or the processor.
948 labelList procPatchSizes(Pstream::nProcs(), 0);
950 forAll(neighbourNewProc, bFaceI)
952 if (neighbourNewProc[bFaceI] != -1)
954 procPatchSizes[neighbourNewProc[bFaceI]]++;
958 // Per neighbour processor the label of the processor patch
959 procPatchID.setSize(Pstream::nProcs());
961 forAll(procPatchSizes, procI)
963 if (procPatchSizes[procI] > 0)
965 const word patchName =
967 + name(Pstream::myProcNo())
972 procPatchID[procI] = addProcPatch(patchName, procI);
973 addPatchFields<volScalarField>
975 processorFvPatchField<scalar>::typeName
977 addPatchFields<volVectorField>
979 processorFvPatchField<vector>::typeName
981 addPatchFields<volSphericalTensorField>
983 processorFvPatchField<sphericalTensor>::typeName
985 addPatchFields<volSymmTensorField>
987 processorFvPatchField<symmTensor>::typeName
989 addPatchFields<volTensorField>
991 processorFvPatchField<tensor>::typeName
994 addPatchFields<surfaceScalarField>
996 processorFvPatchField<scalar>::typeName
998 addPatchFields<surfaceVectorField>
1000 processorFvPatchField<vector>::typeName
1002 addPatchFields<surfaceSphericalTensorField>
1004 processorFvPatchField<sphericalTensor>::typeName
1006 addPatchFields<surfaceSymmTensorField>
1008 processorFvPatchField<symmTensor>::typeName
1010 addPatchFields<surfaceTensorField>
1012 processorFvPatchField<tensor>::typeName
1017 procPatchID[procI] = -1;
1023 // Get boundary faces to be repatched. Is -1 or new patchID
1024 Foam::labelList Foam::fvMeshDistribute::getProcBoundaryPatch
1026 const labelList& neighbourNewProc, // new processor per boundary face
1027 const labelList& procPatchID // patchID
1030 labelList patchIDs(neighbourNewProc);
1032 forAll(neighbourNewProc, bFaceI)
1034 if (neighbourNewProc[bFaceI] != -1)
1036 label nbrProc = neighbourNewProc[bFaceI];
1038 patchIDs[bFaceI] = procPatchID[nbrProc];
1042 patchIDs[bFaceI] = -1;
1049 // Send mesh and coupling data.
1050 void Foam::fvMeshDistribute::sendMesh
1055 const wordList& pointZoneNames,
1056 const wordList& faceZoneNames,
1057 const wordList& cellZoneNames,
1059 const labelList& sourceFace,
1060 const labelList& sourceProc,
1061 const labelList& sourceNewProc,
1067 Pout<< "Sending to domain " << domain << nl
1068 << " nPoints:" << mesh.nPoints() << nl
1069 << " nFaces:" << mesh.nFaces() << nl
1070 << " nCells:" << mesh.nCells() << nl
1071 << " nPatches:" << mesh.boundaryMesh().size() << nl
1075 // Assume sparse, possibly overlapping point zones. Get contents
1076 // in merged-zone indices.
1077 CompactListList_dev<label> zonePoints;
1079 const pointZoneMesh& pointZones = mesh.pointZones();
1081 labelList rowSizes(pointZoneNames.size(), 0);
1083 forAll(pointZoneNames, nameI)
1085 label myZoneID = pointZones.findZoneID(pointZoneNames[nameI]);
1089 rowSizes[nameI] = pointZones[myZoneID].size();
1092 zonePoints.setSize(rowSizes);
1094 forAll(pointZoneNames, nameI)
1096 label myZoneID = pointZones.findZoneID(pointZoneNames[nameI]);
1100 zonePoints[nameI].assign(pointZones[myZoneID]);
1105 // Assume sparse, possibly overlapping face zones
1106 CompactListList_dev<label> zoneFaces;
1107 CompactListList_dev<bool> zoneFaceFlip;
1109 const faceZoneMesh& faceZones = mesh.faceZones();
1111 labelList rowSizes(faceZoneNames.size(), 0);
1113 forAll(faceZoneNames, nameI)
1115 label myZoneID = faceZones.findZoneID(faceZoneNames[nameI]);
1119 rowSizes[nameI] = faceZones[myZoneID].size();
1123 zoneFaces.setSize(rowSizes);
1124 zoneFaceFlip.setSize(rowSizes);
1126 forAll(faceZoneNames, nameI)
1128 label myZoneID = faceZones.findZoneID(faceZoneNames[nameI]);
1132 zoneFaces[nameI].assign(faceZones[myZoneID]);
1133 zoneFaceFlip[nameI].assign(faceZones[myZoneID].flipMap());
1138 // Assume sparse, possibly overlapping cell zones
1139 CompactListList_dev<label> zoneCells;
1141 const cellZoneMesh& cellZones = mesh.cellZones();
1143 labelList rowSizes(cellZoneNames.size(), 0);
1145 forAll(cellZoneNames, nameI)
1147 label myZoneID = cellZones.findZoneID(cellZoneNames[nameI]);
1151 rowSizes[nameI] = cellZones[myZoneID].size();
1155 zoneCells.setSize(rowSizes);
1157 forAll(cellZoneNames, nameI)
1159 label myZoneID = cellZones.findZoneID(cellZoneNames[nameI]);
1163 zoneCells[nameI].assign(cellZones[myZoneID]);
1167 ////- Assume full cell zones
1168 //labelList cellZoneID;
1171 // cellZoneID.setSize(mesh.nCells());
1174 // const cellZoneMesh& cellZones = mesh.cellZones();
1176 // forAll(cellZones, zoneI)
1178 // UIndirectList<label>(cellZoneID, cellZones[zoneI]) = zoneI;
1185 << CompactListList_dev<label, face>(mesh.faces())
1187 << mesh.faceNeighbour()
1188 << mesh.boundaryMesh()
1202 Pout<< "Started sending mesh to domain " << domain
1208 // Receive mesh. Opposite of sendMesh
1209 Foam::autoPtr<Foam::fvMesh> Foam::fvMeshDistribute::receiveMesh
1212 const wordList& pointZoneNames,
1213 const wordList& faceZoneNames,
1214 const wordList& cellZoneNames,
1215 const Time& runTime,
1216 labelList& domainSourceFace,
1217 labelList& domainSourceProc,
1218 labelList& domainSourceNewProc,
1222 pointField domainPoints(fromNbr);
1223 faceList domainFaces = CompactListList_dev<label, face>(fromNbr)();
1224 labelList domainAllOwner(fromNbr);
1225 labelList domainAllNeighbour(fromNbr);
1226 PtrList<entry> patchEntries(fromNbr);
1228 CompactListList_dev<label> zonePoints(fromNbr);
1229 CompactListList_dev<label> zoneFaces(fromNbr);
1230 CompactListList_dev<bool> zoneFaceFlip(fromNbr);
1231 CompactListList_dev<label> zoneCells(fromNbr);
1236 >> domainSourceNewProc;
1239 autoPtr<fvMesh> domainMeshPtr
1245 fvMesh::defaultRegion,
1250 xferMove(domainPoints),
1251 xferMove(domainFaces),
1252 xferMove(domainAllOwner),
1253 xferMove(domainAllNeighbour),
1254 false // no parallel comms
1257 fvMesh& domainMesh = domainMeshPtr();
1259 List<polyPatch*> patches(patchEntries.size());
1261 forAll(patchEntries, patchI)
1263 patches[patchI] = polyPatch::New
1265 patchEntries[patchI].keyword(),
1266 patchEntries[patchI].dict(),
1268 domainMesh.boundaryMesh()
1271 // Add patches; no parallel comms
1272 domainMesh.addFvPatches(patches, false);
1275 List<pointZone*> pZonePtrs(pointZoneNames.size());
1276 forAll(pZonePtrs, i)
1278 pZonePtrs[i] = new pointZone
1283 domainMesh.pointZones()
1287 List<faceZone*> fZonePtrs(faceZoneNames.size());
1288 forAll(fZonePtrs, i)
1290 fZonePtrs[i] = new faceZone
1296 domainMesh.faceZones()
1300 List<cellZone*> cZonePtrs(cellZoneNames.size());
1301 forAll(cZonePtrs, i)
1303 cZonePtrs[i] = new cellZone
1308 domainMesh.cellZones()
1311 domainMesh.addZones(pZonePtrs, fZonePtrs, cZonePtrs);
1313 return domainMeshPtr;
1317 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1319 // Construct from components
1320 Foam::fvMeshDistribute::fvMeshDistribute(fvMesh& mesh, const scalar mergeTol)
1327 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1329 Foam::labelList Foam::fvMeshDistribute::countCells
1331 const labelList& distribution
1334 labelList nCells(Pstream::nProcs(), 0);
1335 forAll(distribution, cellI)
1337 label newProc = distribution[cellI];
1339 if (newProc < 0 || newProc >= Pstream::nProcs())
1341 FatalErrorIn("fvMeshDistribute::distribute(const labelList&)")
1342 << "Distribution should be in range 0.." << Pstream::nProcs()-1
1344 << "At index " << cellI << " distribution:" << newProc
1345 << abort(FatalError);
1353 Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
1355 const labelList& distribution
1358 // Some checks on distribution
1359 if (distribution.size() != mesh_.nCells())
1361 FatalErrorIn("fvMeshDistribute::distribute(const labelList&)")
1362 << "Size of distribution:"
1363 << distribution.size() << " mesh nCells:" << mesh_.nCells()
1364 << abort(FatalError);
1368 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
1370 // Check all processors have same non-proc patches in same order.
1371 if (patches.checkParallelSync(true))
1373 FatalErrorIn("fvMeshDistribute::distribute(const labelList&)")
1374 << "This application requires all non-processor patches"
1375 << " to be present in the same order on all patches" << nl
1376 << "followed by the processor patches (which are unique)."
1378 << "Local patches:" << mesh_.boundaryMesh().names()
1379 << abort(FatalError);
1382 // Save some data for mapping later on
1383 const label nOldPoints(mesh_.nPoints());
1384 const label nOldFaces(mesh_.nFaces());
1385 const label nOldCells(mesh_.nCells());
1386 labelList oldPatchStarts(patches.size());
1387 labelList oldPatchNMeshPoints(patches.size());
1388 forAll(patches, patchI)
1390 oldPatchStarts[patchI] = patches[patchI].start();
1391 oldPatchNMeshPoints[patchI] = patches[patchI].nPoints();
1396 // Short circuit trivial case.
1397 if (!Pstream::parRun())
1399 // Collect all maps and return
1400 return autoPtr<mapDistributePolyMesh>
1402 new mapDistributePolyMesh
1409 oldPatchStarts.xfer(),
1410 oldPatchNMeshPoints.xfer(),
1412 labelListList(1, identity(mesh_.nPoints())).xfer(),//subPointMap
1413 labelListList(1, identity(mesh_.nFaces())).xfer(), //subFaceMap
1414 labelListList(1, identity(mesh_.nCells())).xfer(), //subCellMap
1415 labelListList(1, identity(patches.size())).xfer(), //subPatchMap
1417 labelListList(1, identity(mesh_.nPoints())).xfer(),//pointMap
1418 labelListList(1, identity(mesh_.nFaces())).xfer(), //faceMap
1419 labelListList(1, identity(mesh_.nCells())).xfer(), //cellMap
1420 labelListList(1, identity(patches.size())).xfer() //patchMap
1426 // Collect any zone names
1427 const wordList pointZoneNames(mergeWordList(mesh_.pointZones().names()));
1428 const wordList faceZoneNames(mergeWordList(mesh_.faceZones().names()));
1429 const wordList cellZoneNames(mergeWordList(mesh_.cellZones().names()));
1433 // Local environment of all boundary faces
1434 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1436 // A face is uniquely defined by
1440 // To glue the parts of meshes which can get sent from anywhere we
1441 // need to know on boundary faces what the above tuple on both sides is.
1442 // So we need to maintain:
1444 // - original processor id (= trivial)
1445 // For coupled boundaries (where the faces are 'duplicate') we take the
1446 // lowest numbered processor as the data to store.
1448 // Additionally to create the procboundaries we need to know where the owner
1449 // cell on the other side now is: newNeighbourProc.
1452 // physical boundary:
1454 // sourceNewProc = -1
1455 // sourceFace = patchID
1456 // coupled boundary:
1457 // sourceProc = proc
1458 // sourceNewProc = distribution[cell on proc]
1459 // sourceFace = face
1460 labelList sourceFace;
1461 labelList sourceProc;
1462 labelList sourceNewProc;
1463 getNeighbourData(distribution, sourceFace, sourceProc, sourceNewProc);
1466 // Remove meshPhi. Since this would otherwise dissappear anyway
1467 // during topo changes and we have to guarantee that all the fields
1470 mesh_.resetMotion();
1472 // Get data to send. Make sure is synchronised
1473 const wordList volScalars(mesh_.names(volScalarField::typeName));
1474 checkEqualWordList("volScalarFields", volScalars);
1475 const wordList volVectors(mesh_.names(volVectorField::typeName));
1476 checkEqualWordList("volVectorFields", volVectors);
1477 const wordList volSphereTensors
1479 mesh_.names(volSphericalTensorField::typeName)
1481 checkEqualWordList("volSphericalTensorFields", volSphereTensors);
1482 const wordList volSymmTensors(mesh_.names(volSymmTensorField::typeName));
1483 checkEqualWordList("volSymmTensorFields", volSymmTensors);
1484 const wordList volTensors(mesh_.names(volTensorField::typeName));
1485 checkEqualWordList("volTensorField", volTensors);
1487 const wordList surfScalars(mesh_.names(surfaceScalarField::typeName));
1488 checkEqualWordList("surfaceScalarFields", surfScalars);
1489 const wordList surfVectors(mesh_.names(surfaceVectorField::typeName));
1490 checkEqualWordList("surfaceVectorFields", surfVectors);
1491 const wordList surfSphereTensors
1493 mesh_.names(surfaceSphericalTensorField::typeName)
1495 checkEqualWordList("surfaceSphericalTensorFields", surfSphereTensors);
1496 const wordList surfSymmTensors
1498 mesh_.names(surfaceSymmTensorField::typeName)
1500 checkEqualWordList("surfaceSymmTensorFields", surfSymmTensors);
1501 const wordList surfTensors(mesh_.names(surfaceTensorField::typeName));
1502 checkEqualWordList("surfaceTensorFields", surfTensors);
1507 // Find patch to temporarily put exposed and processor faces into.
1508 label oldInternalPatchI = findNonEmptyPatch();
1512 // Delete processor patches, starting from the back. Move all faces into
1513 // oldInternalPatchI.
1514 labelList repatchFaceMap;
1516 autoPtr<mapPolyMesh> repatchMap = deleteProcPatches(oldInternalPatchI);
1518 // Store face map (only face ordering that changed)
1519 repatchFaceMap = repatchMap().faceMap();
1521 // Reorder all boundary face data (sourceProc, sourceFace etc.)
1526 repatchMap().reverseFaceMap(),
1527 mesh_.nFaces() - mesh_.nInternalFaces(),
1528 mesh_.nInternalFaces()
1530 - mesh_.nInternalFaces()
1533 inplaceReorder(bFaceMap, sourceFace);
1534 inplaceReorder(bFaceMap, sourceProc);
1535 inplaceReorder(bFaceMap, sourceNewProc);
1543 Pout<< nl << "MESH WITH PROC PATCHES DELETED:" << endl;
1544 printMeshInfo(mesh_);
1545 printFieldInfo<volScalarField>(mesh_);
1546 printFieldInfo<volVectorField>(mesh_);
1547 printFieldInfo<volSphericalTensorField>(mesh_);
1548 printFieldInfo<volSymmTensorField>(mesh_);
1549 printFieldInfo<volTensorField>(mesh_);
1550 printFieldInfo<surfaceScalarField>(mesh_);
1551 printFieldInfo<surfaceVectorField>(mesh_);
1552 printFieldInfo<surfaceSphericalTensorField>(mesh_);
1553 printFieldInfo<surfaceSymmTensorField>(mesh_);
1554 printFieldInfo<surfaceTensorField>(mesh_);
1560 // Maps from subsetted mesh (that is sent) back to original maps
1561 labelListList subCellMap(Pstream::nProcs());
1562 labelListList subFaceMap(Pstream::nProcs());
1563 labelListList subPointMap(Pstream::nProcs());
1564 labelListList subPatchMap(Pstream::nProcs());
1565 // Maps from subsetted mesh to reconstructed mesh
1566 labelListList constructCellMap(Pstream::nProcs());
1567 labelListList constructFaceMap(Pstream::nProcs());
1568 labelListList constructPointMap(Pstream::nProcs());
1569 labelListList constructPatchMap(Pstream::nProcs());
1574 // Find out schedule
1575 // ~~~~~~~~~~~~~~~~~
1577 labelListList nSendCells(Pstream::nProcs());
1578 nSendCells[Pstream::myProcNo()] = countCells(distribution);
1579 Pstream::gatherList(nSendCells);
1580 Pstream::scatterList(nSendCells);
1584 PtrList<OStringStream> sendStr(Pstream::nProcs());
1587 sendStr.set(i, new OStringStream(IOstream::BINARY));
1589 //PstreamBuffers pBufs(Pstream::nonBlocking);
1592 // What to send to neighbouring domains
1593 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1595 forAll(nSendCells[Pstream::myProcNo()], recvProc)
1599 recvProc != Pstream::myProcNo()
1600 && nSendCells[Pstream::myProcNo()][recvProc] > 0
1608 << "SUBSETTING FOR DOMAIN " << recvProc
1609 << " cells to send:"
1610 << nSendCells[Pstream::myProcNo()][recvProc]
1614 // Pstream for sending mesh and fields
1615 //OPstream str(Pstream::blocking, recvProc);
1616 //UOPstream str(recvProc, pBufs);
1618 // Mesh subsetting engine
1619 fvMeshSubset subsetter
1624 mesh_.time().timeName(),
1632 // Subset the cells of the current domain.
1633 subsetter.setLargeCellSubset
1637 oldInternalPatchI, // oldInternalFaces patch
1638 false // no parallel sync
1641 subCellMap[recvProc] = subsetter.cellMap();
1642 subFaceMap[recvProc] = renumber
1647 subPointMap[recvProc] = subsetter.pointMap();
1648 subPatchMap[recvProc] = subsetter.patchMap();
1651 // Subset the boundary fields (owner/neighbour/processor)
1652 labelList procSourceFace;
1653 labelList procSourceProc;
1654 labelList procSourceNewProc;
1658 subsetter.subMesh(),
1659 subsetter.faceMap(), // from subMesh to mesh
1660 subsetter.cellMap(), // ,, ,,
1662 distribution, // old mesh distribution
1663 mesh_.faceOwner(), // old owner
1664 mesh_.faceNeighbour(),
1665 mesh_.nInternalFaces(),
1678 // Send to neighbour
1682 subsetter.subMesh(),
1693 sendFields<volScalarField>
1700 sendFields<volVectorField>
1707 sendFields<volSphericalTensorField>
1714 sendFields<volSymmTensorField>
1721 sendFields<volTensorField>
1729 sendFields<surfaceScalarField>
1736 sendFields<surfaceVectorField>
1743 sendFields<surfaceSphericalTensorField>
1750 sendFields<surfaceSymmTensorField>
1757 sendFields<surfaceTensorField>
1768 // Start sending&receiving from buffers
1769 //pBufs.finishedSends();
1772 PtrList<IStringStream> recvStr(Pstream::nProcs());
1774 List<List<char> > sendBufs(sendStr.size());
1775 forAll(sendStr, procI)
1777 string contents = sendStr[procI].str();
1778 const char* ptr = contents.data();
1780 sendBufs[procI].setSize(contents.size());
1781 forAll(sendBufs[procI], i)
1783 sendBufs[procI][i] = *ptr++;
1785 // Clear OStringStream
1786 sendStr.set(procI, NULL);
1789 // Transfer sendBufs into recvBufs
1790 List<List<char> > recvBufs(Pstream::nProcs());
1791 labelListList sizes(Pstream::nProcs());
1792 exchange<List<char>, char>(sendBufs, recvBufs, sizes);
1794 forAll(recvStr, procI)
1796 string contents(recvBufs[procI].begin(), recvBufs[procI].size());
1800 new IStringStream(contents, IOstream::BINARY)
1806 // Subset the part that stays
1807 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
1810 // Save old mesh maps before changing mesh
1811 const labelList oldFaceOwner(mesh_.faceOwner());
1812 const labelList oldFaceNeighbour(mesh_.faceNeighbour());
1813 const label oldInternalFaces = mesh_.nInternalFaces();
1816 autoPtr<mapPolyMesh> subMap
1820 select(false, distribution, Pstream::myProcNo()),
1825 // Addressing from subsetted mesh
1826 subCellMap[Pstream::myProcNo()] = subMap().cellMap();
1827 subFaceMap[Pstream::myProcNo()] = renumber
1832 subPointMap[Pstream::myProcNo()] = subMap().pointMap();
1833 subPatchMap[Pstream::myProcNo()] = identity(patches.size());
1835 // Initialize all addressing into current mesh
1836 constructCellMap[Pstream::myProcNo()] = identity(mesh_.nCells());
1837 constructFaceMap[Pstream::myProcNo()] = identity(mesh_.nFaces());
1838 constructPointMap[Pstream::myProcNo()] = identity(mesh_.nPoints());
1839 constructPatchMap[Pstream::myProcNo()] = identity(patches.size());
1841 // Subset the mesh data: neighbourCell/neighbourProc
1843 labelList domainSourceFace;
1844 labelList domainSourceProc;
1845 labelList domainSourceNewProc;
1850 subMap().faceMap(), // from new to original mesh
1853 distribution, // distribution before subsetting
1854 oldFaceOwner, // owner before subsetting
1855 oldFaceNeighbour, // neighbour ,,
1856 oldInternalFaces, // nInternalFaces ,,
1867 sourceFace.transfer(domainSourceFace);
1868 sourceProc.transfer(domainSourceProc);
1869 sourceNewProc.transfer(domainSourceNewProc);
1876 Pout<< nl << "STARTING MESH:" << endl;
1877 printMeshInfo(mesh_);
1878 printFieldInfo<volScalarField>(mesh_);
1879 printFieldInfo<volVectorField>(mesh_);
1880 printFieldInfo<volSphericalTensorField>(mesh_);
1881 printFieldInfo<volSymmTensorField>(mesh_);
1882 printFieldInfo<volTensorField>(mesh_);
1883 printFieldInfo<surfaceScalarField>(mesh_);
1884 printFieldInfo<surfaceVectorField>(mesh_);
1885 printFieldInfo<surfaceSphericalTensorField>(mesh_);
1886 printFieldInfo<surfaceSymmTensorField>(mesh_);
1887 printFieldInfo<surfaceTensorField>(mesh_);
1893 // Receive and add what was sent
1894 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1896 forAll(nSendCells, sendProc)
1898 // Did processor sendProc send anything to me?
1901 sendProc != Pstream::myProcNo()
1902 && nSendCells[sendProc][Pstream::myProcNo()] > 0
1908 << "RECEIVING FROM DOMAIN " << sendProc
1909 << " cells to receive:"
1910 << nSendCells[sendProc][Pstream::myProcNo()]
1915 // Pstream for receiving mesh and fields
1916 //UIPstream str(sendProc, pBufs);
1919 // Receive from sendProc
1920 labelList domainSourceFace;
1921 labelList domainSourceProc;
1922 labelList domainSourceNewProc;
1924 autoPtr<fvMesh> domainMeshPtr;
1925 PtrList<volScalarField> vsf;
1926 PtrList<volVectorField> vvf;
1927 PtrList<volSphericalTensorField> vsptf;
1928 PtrList<volSymmTensorField> vsytf;
1929 PtrList<volTensorField> vtf;
1930 PtrList<surfaceScalarField> ssf;
1931 PtrList<surfaceVectorField> svf;
1932 PtrList<surfaceSphericalTensorField> ssptf;
1933 PtrList<surfaceSymmTensorField> ssytf;
1934 PtrList<surfaceTensorField> stf;
1936 // Opposite of sendMesh
1938 domainMeshPtr = receiveMesh
1945 const_cast<Time&>(mesh_.time()),
1948 domainSourceNewProc,
1951 fvMesh& domainMesh = domainMeshPtr();
1953 // Receive fields. Read as single dictionary because
1954 // of problems reading consecutive fields from single stream.
1955 dictionary fieldDicts(recvStr[sendProc]);
1957 receiveFields<volScalarField>
1963 fieldDicts.subDict(volScalarField::typeName)
1965 receiveFields<volVectorField>
1971 fieldDicts.subDict(volVectorField::typeName)
1973 receiveFields<volSphericalTensorField>
1979 fieldDicts.subDict(volSphericalTensorField::typeName)
1981 receiveFields<volSymmTensorField>
1987 fieldDicts.subDict(volSymmTensorField::typeName)
1989 receiveFields<volTensorField>
1995 fieldDicts.subDict(volTensorField::typeName)
1998 receiveFields<surfaceScalarField>
2004 fieldDicts.subDict(surfaceScalarField::typeName)
2006 receiveFields<surfaceVectorField>
2012 fieldDicts.subDict(surfaceVectorField::typeName)
2014 receiveFields<surfaceSphericalTensorField>
2020 fieldDicts.subDict(surfaceSphericalTensorField::typeName)
2022 receiveFields<surfaceSymmTensorField>
2028 fieldDicts.subDict(surfaceSymmTensorField::typeName)
2030 receiveFields<surfaceTensorField>
2036 fieldDicts.subDict(surfaceTensorField::typeName)
2039 const fvMesh& domainMesh = domainMeshPtr();
2042 constructCellMap[sendProc] = identity(domainMesh.nCells());
2043 constructFaceMap[sendProc] = identity(domainMesh.nFaces());
2044 constructPointMap[sendProc] = identity(domainMesh.nPoints());
2045 constructPatchMap[sendProc] =
2046 identity(domainMesh.boundaryMesh().size());
2052 Pout<< nl << "RECEIVED MESH FROM:" << sendProc << endl;
2053 printMeshInfo(domainMesh);
2054 printFieldInfo<volScalarField>(domainMesh);
2055 printFieldInfo<volVectorField>(domainMesh);
2056 printFieldInfo<volSphericalTensorField>(domainMesh);
2057 printFieldInfo<volSymmTensorField>(domainMesh);
2058 printFieldInfo<volTensorField>(domainMesh);
2059 printFieldInfo<surfaceScalarField>(domainMesh);
2060 printFieldInfo<surfaceVectorField>(domainMesh);
2061 printFieldInfo<surfaceSphericalTensorField>(domainMesh);
2062 printFieldInfo<surfaceSymmTensorField>(domainMesh);
2063 printFieldInfo<surfaceTensorField>(domainMesh);
2067 // Now this mesh we received (from sendProc) needs to be merged
2068 // with the current mesh. On the current mesh we have for all
2069 // boundaryfaces the original face and processor. See if we can
2070 // match these up to the received domainSourceFace and
2071 // domainSourceProc.
2072 labelList masterCoupledFaces;
2073 labelList slaveCoupledFaces;
2090 // Generate additional coupling info (points, edges) from
2092 faceCoupleInfo couples
2098 mergeTol_, // merge tolerance
2099 true, // faces align
2100 true, // couples are ordered already
2105 // Add domainMesh to mesh
2106 // ~~~~~~~~~~~~~~~~~~~~~~
2108 autoPtr<mapAddedPolyMesh> map = fvMeshAdder::add
2113 false // no parallel comms
2116 // Update mesh data: sourceFace,sourceProc for added
2125 domainMesh.nInternalFaces(),
2134 domainMesh.nInternalFaces(),
2143 domainMesh.nInternalFaces(),
2147 // Update all addressing so xxProcAddressing points to correct item
2149 const labelList& oldCellMap = map().oldCellMap();
2150 const labelList& oldFaceMap = map().oldFaceMap();
2151 const labelList& oldPointMap = map().oldPointMap();
2152 const labelList& oldPatchMap = map().oldPatchMap();
2154 forAll(constructPatchMap, procI)
2156 if (procI != sendProc && constructPatchMap[procI].size())
2158 // Processor already in mesh (either myProcNo or received)
2159 inplaceRenumber(oldCellMap, constructCellMap[procI]);
2160 inplaceRenumber(oldFaceMap, constructFaceMap[procI]);
2161 inplaceRenumber(oldPointMap, constructPointMap[procI]);
2162 inplaceRenumber(oldPatchMap, constructPatchMap[procI]);
2167 inplaceRenumber(map().addedCellMap(), constructCellMap[sendProc]);
2168 inplaceRenumber(map().addedFaceMap(), constructFaceMap[sendProc]);
2169 inplaceRenumber(map().addedPointMap(), constructPointMap[sendProc]);
2170 inplaceRenumber(map().addedPatchMap(), constructPatchMap[sendProc]);
2174 Pout<< nl << "MERGED MESH FROM:" << sendProc << endl;
2175 printMeshInfo(mesh_);
2176 printFieldInfo<volScalarField>(mesh_);
2177 printFieldInfo<volVectorField>(mesh_);
2178 printFieldInfo<volSphericalTensorField>(mesh_);
2179 printFieldInfo<volSymmTensorField>(mesh_);
2180 printFieldInfo<volTensorField>(mesh_);
2181 printFieldInfo<surfaceScalarField>(mesh_);
2182 printFieldInfo<surfaceVectorField>(mesh_);
2183 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2184 printFieldInfo<surfaceSymmTensorField>(mesh_);
2185 printFieldInfo<surfaceTensorField>(mesh_);
2195 Pout<< nl << "REDISTRIBUTED MESH:" << endl;
2196 printMeshInfo(mesh_);
2197 printFieldInfo<volScalarField>(mesh_);
2198 printFieldInfo<volVectorField>(mesh_);
2199 printFieldInfo<volSphericalTensorField>(mesh_);
2200 printFieldInfo<volSymmTensorField>(mesh_);
2201 printFieldInfo<volTensorField>(mesh_);
2202 printFieldInfo<surfaceScalarField>(mesh_);
2203 printFieldInfo<surfaceVectorField>(mesh_);
2204 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2205 printFieldInfo<surfaceSymmTensorField>(mesh_);
2206 printFieldInfo<surfaceTensorField>(mesh_);
2212 // Add processorPatches
2213 // ~~~~~~~~~~~~~~~~~~~~
2215 // Per neighbour processor the patchID to it (or -1).
2216 labelList procPatchID;
2218 // Add processor patches.
2219 addProcPatches(sourceNewProc, procPatchID);
2221 // Put faces into correct patch. Note that we now have proper
2222 // processorPolyPatches again so repatching will take care of coupled face
2225 // Get boundary faces to be repatched. Is -1 or new patchID
2226 labelList newPatchID
2228 getProcBoundaryPatch
2235 // Change patches. Since this might change ordering of coupled faces
2236 // we also need to adapt our constructMaps.
2237 repatch(newPatchID, constructFaceMap);
2239 // See if any geometrically shared points need to be merged. Note: does
2241 mergeSharedPoints(constructPointMap);
2243 // Bit of hack: processorFvPatchField does not get reset since created
2244 // from nothing so explicitly reset.
2245 initPatchFields<volScalarField, processorFvPatchField<scalar> >
2247 pTraits<scalar>::zero
2249 initPatchFields<volVectorField, processorFvPatchField<vector> >
2251 pTraits<vector>::zero
2255 volSphericalTensorField,
2256 processorFvPatchField<sphericalTensor>
2259 pTraits<sphericalTensor>::zero
2261 initPatchFields<volSymmTensorField, processorFvPatchField<symmTensor> >
2263 pTraits<symmTensor>::zero
2265 initPatchFields<volTensorField, processorFvPatchField<tensor> >
2267 pTraits<tensor>::zero
2269 initPatchFields<surfaceScalarField, processorFvsPatchField<scalar> >
2271 pTraits<scalar>::zero
2273 initPatchFields<surfaceVectorField, processorFvsPatchField<vector> >
2275 pTraits<vector>::zero
2279 surfaceSphericalTensorField,
2280 processorFvsPatchField<sphericalTensor>
2283 pTraits<sphericalTensor>::zero
2287 surfaceSymmTensorField,
2288 processorFvsPatchField<symmTensor>
2291 pTraits<symmTensor>::zero
2293 initPatchFields<surfaceTensorField, processorFvsPatchField<tensor> >
2295 pTraits<tensor>::zero
2299 mesh_.setInstance(mesh_.time().timeName());
2305 Pout<< nl << "FINAL MESH:" << endl;
2306 printMeshInfo(mesh_);
2307 printFieldInfo<volScalarField>(mesh_);
2308 printFieldInfo<volVectorField>(mesh_);
2309 printFieldInfo<volSphericalTensorField>(mesh_);
2310 printFieldInfo<volSymmTensorField>(mesh_);
2311 printFieldInfo<volTensorField>(mesh_);
2312 printFieldInfo<surfaceScalarField>(mesh_);
2313 printFieldInfo<surfaceVectorField>(mesh_);
2314 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2315 printFieldInfo<surfaceSymmTensorField>(mesh_);
2316 printFieldInfo<surfaceTensorField>(mesh_);
2320 // Collect all maps and return
2321 return autoPtr<mapDistributePolyMesh>
2323 new mapDistributePolyMesh
2331 oldPatchNMeshPoints,
2342 true // reuse storage
2348 // ************************************************************************* //