1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
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 "CompactListList_dev.H"
27 #include "fvMeshDistribute.H"
28 #include "PstreamCombineReduceOps.H"
29 #include "fvMeshAdder.H"
30 #include "faceCoupleInfo.H"
31 #include "processorFvPatchField.H"
32 #include "processorFvsPatchField.H"
33 #include "polyTopoChange.H"
34 #include "removeCells.H"
35 #include "polyModifyFace.H"
36 #include "polyRemovePoint.H"
37 #include "mergePoints.H"
38 #include "mapDistributePolyMesh.H"
39 #include "surfaceFields.H"
40 #include "syncTools.H"
42 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 defineTypeNameAndDebug(Foam::fvMeshDistribute, 0);
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
49 Foam::labelList Foam::fvMeshDistribute::select
51 const bool selectEqual,
52 const labelList& values,
60 if (selectEqual == (values[i] == value))
71 if (selectEqual == (values[i] == value))
80 // Check all procs have same names and in exactly same order.
81 void Foam::fvMeshDistribute::checkEqualWordList
87 List<wordList> allNames(Pstream::nProcs());
88 allNames[Pstream::myProcNo()] = lst;
89 Pstream::gatherList(allNames);
90 Pstream::scatterList(allNames);
92 for (label procI = 1; procI < Pstream::nProcs(); procI++)
94 if (allNames[procI] != allNames[0])
96 FatalErrorIn("fvMeshDistribute::checkEqualWordList(..)")
97 << "When checking for equal " << msg.c_str() << " :" << endl
98 << "processor0 has:" << allNames[0] << endl
99 << "processor" << procI << " has:" << allNames[procI] << endl
100 << msg.c_str() << " need to be synchronised on all processors."
107 Foam::wordList Foam::fvMeshDistribute::mergeWordList(const wordList& procNames)
109 List<wordList> allNames(Pstream::nProcs());
110 allNames[Pstream::myProcNo()] = procNames;
111 Pstream::gatherList(allNames);
112 Pstream::scatterList(allNames);
114 HashSet<word> mergedNames;
115 forAll(allNames, procI)
117 forAll(allNames[procI], i)
119 mergedNames.insert(allNames[procI][i]);
122 return mergedNames.toc();
126 // Print some info on mesh.
127 void Foam::fvMeshDistribute::printMeshInfo(const fvMesh& mesh)
129 Pout<< "Primitives:" << nl
130 << " points :" << mesh.nPoints() << nl
131 << " internalFaces:" << mesh.nInternalFaces() << nl
132 << " faces :" << mesh.nFaces() << nl
133 << " cells :" << mesh.nCells() << nl;
135 const fvBoundaryMesh& patches = mesh.boundary();
137 Pout<< "Patches:" << endl;
138 forAll(patches, patchI)
140 const polyPatch& pp = patches[patchI].patch();
142 Pout<< " " << patchI << " name:" << pp.name()
143 << " size:" << pp.size()
144 << " start:" << pp.start()
145 << " type:" << pp.type()
149 if (mesh.pointZones().size())
151 Pout<< "PointZones:" << endl;
152 forAll(mesh.pointZones(), zoneI)
154 const pointZone& pz = mesh.pointZones()[zoneI];
155 Pout<< " " << zoneI << " name:" << pz.name()
156 << " size:" << pz.size()
160 if (mesh.faceZones().size())
162 Pout<< "FaceZones:" << endl;
163 forAll(mesh.faceZones(), zoneI)
165 const faceZone& fz = mesh.faceZones()[zoneI];
166 Pout<< " " << zoneI << " name:" << fz.name()
167 << " size:" << fz.size()
171 if (mesh.cellZones().size())
173 Pout<< "CellZones:" << endl;
174 forAll(mesh.cellZones(), zoneI)
176 const cellZone& cz = mesh.cellZones()[zoneI];
177 Pout<< " " << zoneI << " name:" << cz.name()
178 << " size:" << cz.size()
185 void Foam::fvMeshDistribute::printCoupleInfo
187 const primitiveMesh& mesh,
188 const labelList& sourceFace,
189 const labelList& sourceProc,
190 const labelList& sourceNewProc
194 << "Current coupling info:"
197 forAll(sourceFace, bFaceI)
199 label meshFaceI = mesh.nInternalFaces() + bFaceI;
201 Pout<< " meshFace:" << meshFaceI
202 << " fc:" << mesh.faceCentres()[meshFaceI]
203 << " connects to proc:" << sourceProc[bFaceI]
204 << "/face:" << sourceFace[bFaceI]
205 << " which will move to proc:" << sourceNewProc[bFaceI]
211 // Finds (non-empty) patch that exposed internal and proc faces can be put into.
212 Foam::label Foam::fvMeshDistribute::findNonEmptyPatch() const
214 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
216 label nonEmptyPatchI = -1;
218 forAllReverse(patches, patchI)
220 const polyPatch& pp = patches[patchI];
222 if (!isA<emptyPolyPatch>(pp) && !pp.coupled())
224 nonEmptyPatchI = patchI;
229 if (nonEmptyPatchI == -1)
231 FatalErrorIn("fvMeshDistribute::findNonEmptyPatch() const")
232 << "Cannot find a patch which is neither of type empty nor"
233 << " coupled in patches " << patches.names() << endl
234 << "There has to be at least one such patch for"
235 << " distribution to work" << abort(FatalError);
240 Pout<< "findNonEmptyPatch : using patch " << nonEmptyPatchI
241 << " name:" << patches[nonEmptyPatchI].name()
242 << " type:" << patches[nonEmptyPatchI].type()
243 << " to put exposed faces into." << endl;
247 // Do additional test for processor patches intermingled with non-proc
249 label procPatchI = -1;
251 forAll(patches, patchI)
253 if (isA<processorPolyPatch>(patches[patchI]))
257 else if (procPatchI != -1)
259 FatalErrorIn("fvMeshDistribute::findNonEmptyPatch() const")
260 << "Processor patches should be at end of patch list."
262 << "Have processor patch " << procPatchI
263 << " followed by non-processor patch " << patchI
264 << " in patches " << patches.names()
265 << abort(FatalError);
269 return nonEmptyPatchI;
273 // Appends processorPolyPatch. Returns patchID.
274 Foam::label Foam::fvMeshDistribute::addProcPatch
276 const word& patchName,
280 // Clear local fields and e.g. polyMesh globalMeshData.
284 polyBoundaryMesh& polyPatches =
285 const_cast<polyBoundaryMesh&>(mesh_.boundaryMesh());
286 fvBoundaryMesh& fvPatches = const_cast<fvBoundaryMesh&>(mesh_.boundary());
288 if (polyPatches.findPatchID(patchName) != -1)
290 FatalErrorIn("fvMeshDistribute::addProcPatch(const word&, const label)")
291 << "Cannot create patch " << patchName << " since already exists."
293 << "Current patch names:" << polyPatches.names()
302 label sz = polyPatches.size();
305 polyPatches.setSize(sz+1);
309 new processorPolyPatch
315 mesh_.boundaryMesh(),
320 fvPatches.setSize(sz+1);
326 polyPatches[sz], // point to newly added polyPatch
335 // Deletes last patch
336 void Foam::fvMeshDistribute::deleteTrailingPatch()
338 // Clear local fields and e.g. polyMesh globalMeshData.
341 polyBoundaryMesh& polyPatches =
342 const_cast<polyBoundaryMesh&>(mesh_.boundaryMesh());
343 fvBoundaryMesh& fvPatches = const_cast<fvBoundaryMesh&>(mesh_.boundary());
345 if (polyPatches.empty())
347 FatalErrorIn("fvMeshDistribute::deleteTrailingPatch(fvMesh&)")
348 << "No patches in mesh"
349 << abort(FatalError);
352 label sz = polyPatches.size();
354 label nFaces = polyPatches[sz-1].size();
356 // Remove last polyPatch
359 Pout<< "deleteTrailingPatch : Removing patch " << sz-1
360 << " : " << polyPatches[sz-1].name() << " size:" << nFaces << endl;
365 FatalErrorIn("fvMeshDistribute::deleteTrailingPatch()")
366 << "There are still " << nFaces << " faces in patch to be deleted "
367 << sz-1 << ' ' << polyPatches[sz-1].name()
368 << abort(FatalError);
371 // Remove actual patch
372 polyPatches.setSize(sz-1);
373 fvPatches.setSize(sz-1);
377 // Delete all processor patches. Move any processor faces into the last
378 // non-processor patch.
379 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::deleteProcPatches
381 const label destinationPatch
384 // New patchID per boundary faces to be repatched. Is -1 (no change)
386 labelList newPatchID(mesh_.nFaces() - mesh_.nInternalFaces(), -1);
388 label nProcPatches = 0;
390 forAll(mesh_.boundaryMesh(), patchI)
392 const polyPatch& pp = mesh_.boundaryMesh()[patchI];
394 if (isA<processorPolyPatch>(pp))
398 Pout<< "Moving all faces of patch " << pp.name()
399 << " into patch " << destinationPatch
403 label offset = pp.start() - mesh_.nInternalFaces();
407 newPatchID[offset+i] = destinationPatch;
414 // Note: order of boundary faces been kept the same since the
415 // destinationPatch is at the end and we have visited the patches in
416 // incremental order.
417 labelListList dummyFaceMaps;
418 autoPtr<mapPolyMesh> map = repatch(newPatchID, dummyFaceMaps);
421 // Delete (now empty) processor patches.
422 forAllReverse(mesh_.boundaryMesh(), patchI)
424 const polyPatch& pp = mesh_.boundaryMesh()[patchI];
426 if (isA<processorPolyPatch>(pp))
428 deleteTrailingPatch();
429 deleteTrailingPatchFields<volScalarField>();
430 deleteTrailingPatchFields<volVectorField>();
431 deleteTrailingPatchFields<volSphericalTensorField>();
432 deleteTrailingPatchFields<volSymmTensorField>();
433 deleteTrailingPatchFields<volTensorField>();
435 deleteTrailingPatchFields<surfaceScalarField>();
436 deleteTrailingPatchFields<surfaceVectorField>();
437 deleteTrailingPatchFields<surfaceSphericalTensorField>();
438 deleteTrailingPatchFields<surfaceSymmTensorField>();
439 deleteTrailingPatchFields<surfaceTensorField>();
448 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::repatch
450 const labelList& newPatchID, // per boundary face -1 or new patchID
451 labelListList& constructFaceMap
454 polyTopoChange meshMod(mesh_);
456 forAll(newPatchID, bFaceI)
458 if (newPatchID[bFaceI] != -1)
460 label faceI = mesh_.nInternalFaces() + bFaceI;
462 label zoneID = mesh_.faceZones().whichZone(faceI);
463 bool zoneFlip = false;
467 const faceZone& fZone = mesh_.faceZones()[zoneID];
468 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
475 mesh_.faces()[faceI], // modified face
476 faceI, // label of face
477 mesh_.faceOwner()[faceI], // owner
480 newPatchID[bFaceI], // patch for face
481 false, // remove from zone
482 zoneID, // zone for face
483 zoneFlip // face flip in zone
490 // Do mapping of fields from one patchField to the other ourselves since
491 // is currently not supported by updateMesh.
493 // Store boundary fields (we only do this for surfaceFields)
494 PtrList<FieldField<fvsPatchField, scalar> > sFlds;
495 saveBoundaryFields<scalar, surfaceMesh>(sFlds);
496 PtrList<FieldField<fvsPatchField, vector> > vFlds;
497 saveBoundaryFields<vector, surfaceMesh>(vFlds);
498 PtrList<FieldField<fvsPatchField, sphericalTensor> > sptFlds;
499 saveBoundaryFields<sphericalTensor, surfaceMesh>(sptFlds);
500 PtrList<FieldField<fvsPatchField, symmTensor> > sytFlds;
501 saveBoundaryFields<symmTensor, surfaceMesh>(sytFlds);
502 PtrList<FieldField<fvsPatchField, tensor> > tFlds;
503 saveBoundaryFields<tensor, surfaceMesh>(tFlds);
505 // Change the mesh (no inflation). Note: parallel comms allowed.
506 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
508 // Update fields. No inflation, parallel sync.
509 mesh_.updateMesh(map);
511 // Map patch fields using stored boundary fields. Note: assumes order
512 // of fields has not changed in object registry!
513 mapBoundaryFields<scalar, surfaceMesh>(map, sFlds);
514 mapBoundaryFields<vector, surfaceMesh>(map, vFlds);
515 mapBoundaryFields<sphericalTensor, surfaceMesh>(map, sptFlds);
516 mapBoundaryFields<symmTensor, surfaceMesh>(map, sytFlds);
517 mapBoundaryFields<tensor, surfaceMesh>(map, tFlds);
520 // Move mesh (since morphing does not do this)
521 if (map().hasMotionPoints())
523 mesh_.movePoints(map().preMotionPoints());
526 // Adapt constructMaps.
530 label index = findIndex(map().reverseFaceMap(), -1);
536 "fvMeshDistribute::repatch(const labelList&, labelListList&)"
537 ) << "reverseFaceMap contains -1 at index:"
539 << "This means that the repatch operation was not just"
540 << " a shuffle?" << abort(FatalError);
544 forAll(constructFaceMap, procI)
546 inplaceRenumber(map().reverseFaceMap(), constructFaceMap[procI]);
554 // Detect shared points. Need processor patches to be present.
555 // Background: when adding bits of mesh one can get points which
556 // share the same position but are only detectable to be topologically
557 // the same point when doing parallel analysis. This routine will
558 // merge those points.
559 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::mergeSharedPoints
561 labelListList& constructPointMap
564 // Find out which sets of points get merged and create a map from
565 // mesh point to unique point.
566 Map<label> pointToMaster
568 fvMeshAdder::findSharedPoints
575 if (returnReduce(pointToMaster.size(), sumOp<label>()) == 0)
577 return autoPtr<mapPolyMesh>(NULL);
580 polyTopoChange meshMod(mesh_);
582 fvMeshAdder::mergePoints(mesh_, pointToMaster, meshMod);
584 // Change the mesh (no inflation). Note: parallel comms allowed.
585 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
587 // Update fields. No inflation, parallel sync.
588 mesh_.updateMesh(map);
590 // Adapt constructMaps for merged points.
591 forAll(constructPointMap, procI)
593 labelList& constructMap = constructPointMap[procI];
595 forAll(constructMap, i)
597 label oldPointI = constructMap[i];
599 label newPointI = map().reversePointMap()[oldPointI];
603 constructMap[i] = -newPointI-2;
605 else if (newPointI >= 0)
607 constructMap[i] = newPointI;
611 FatalErrorIn("fvMeshDistribute::mergeSharedPoints()")
612 << "Problem. oldPointI:" << oldPointI
613 << " newPointI:" << newPointI << abort(FatalError);
621 // Construct the local environment of all boundary faces.
622 void Foam::fvMeshDistribute::getNeighbourData
624 const labelList& distribution,
625 labelList& sourceFace,
626 labelList& sourceProc,
627 labelList& sourceNewProc
630 label nBnd = mesh_.nFaces() - mesh_.nInternalFaces();
631 sourceFace.setSize(nBnd);
632 sourceProc.setSize(nBnd);
633 sourceNewProc.setSize(nBnd);
635 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
637 // Get neighbouring meshFace labels and new processor of coupled boundaries.
638 labelList nbrFaces(nBnd, -1);
639 labelList nbrNewProc(nBnd, -1);
641 forAll(patches, patchI)
643 const polyPatch& pp = patches[patchI];
645 if (isA<processorPolyPatch>(pp))
647 label offset = pp.start() - mesh_.nInternalFaces();
649 // Mesh labels of faces on this side
652 label bndI = offset + i;
653 nbrFaces[bndI] = pp.start()+i;
656 // Which processor they will end up on
657 SubList<label>(nbrNewProc, pp.size(), offset).assign
659 UIndirectList<label>(distribution, pp.faceCells())()
665 // Exchange the boundary data
666 syncTools::swapBoundaryFaceList(mesh_, nbrFaces, false);
667 syncTools::swapBoundaryFaceList(mesh_, nbrNewProc, false);
670 forAll(patches, patchI)
672 const polyPatch& pp = patches[patchI];
673 label offset = pp.start() - mesh_.nInternalFaces();
675 if (isA<processorPolyPatch>(pp))
677 const processorPolyPatch& procPatch =
678 refCast<const processorPolyPatch>(pp);
680 // Check which of the two faces we store.
682 if (Pstream::myProcNo() < procPatch.neighbProcNo())
684 // Use my local face labels
687 label bndI = offset + i;
688 sourceFace[bndI] = pp.start()+i;
689 sourceProc[bndI] = Pstream::myProcNo();
690 sourceNewProc[bndI] = nbrNewProc[bndI];
695 // Use my neighbours face labels
698 label bndI = offset + i;
699 sourceFace[bndI] = nbrFaces[bndI];
700 sourceProc[bndI] = procPatch.neighbProcNo();
701 sourceNewProc[bndI] = nbrNewProc[bndI];
707 // Normal (physical) boundary
710 label bndI = offset + i;
711 sourceFace[bndI] = patchI;
712 sourceProc[bndI] = -1;
713 sourceNewProc[bndI] = -1;
720 // Subset the neighbourCell/neighbourProc fields
721 void Foam::fvMeshDistribute::subsetBoundaryData
724 const labelList& faceMap,
725 const labelList& cellMap,
727 const labelList& oldDistribution,
728 const labelList& oldFaceOwner,
729 const labelList& oldFaceNeighbour,
730 const label oldInternalFaces,
732 const labelList& sourceFace,
733 const labelList& sourceProc,
734 const labelList& sourceNewProc,
738 labelList& subNewProc
741 subFace.setSize(mesh.nFaces() - mesh.nInternalFaces());
742 subProc.setSize(mesh.nFaces() - mesh.nInternalFaces());
743 subNewProc.setSize(mesh.nFaces() - mesh.nInternalFaces());
745 forAll(subFace, newBFaceI)
747 label newFaceI = newBFaceI + mesh.nInternalFaces();
749 label oldFaceI = faceMap[newFaceI];
751 // Was oldFaceI internal face? If so which side did we get.
752 if (oldFaceI < oldInternalFaces)
754 subFace[newBFaceI] = oldFaceI;
755 subProc[newBFaceI] = Pstream::myProcNo();
757 label oldOwn = oldFaceOwner[oldFaceI];
758 label oldNei = oldFaceNeighbour[oldFaceI];
760 if (oldOwn == cellMap[mesh.faceOwner()[newFaceI]])
762 // We kept the owner side. Where does the neighbour move to?
763 subNewProc[newBFaceI] = oldDistribution[oldNei];
767 // We kept the neighbour side.
768 subNewProc[newBFaceI] = oldDistribution[oldOwn];
773 // Was boundary face. Take over boundary information
774 label oldBFaceI = oldFaceI - oldInternalFaces;
776 subFace[newBFaceI] = sourceFace[oldBFaceI];
777 subProc[newBFaceI] = sourceProc[oldBFaceI];
778 subNewProc[newBFaceI] = sourceNewProc[oldBFaceI];
784 // Find cells on mesh whose faceID/procID match the neighbour cell/proc of
785 // domainMesh. Store the matching face.
786 void Foam::fvMeshDistribute::findCouples
788 const primitiveMesh& mesh,
789 const labelList& sourceFace,
790 const labelList& sourceProc,
793 const primitiveMesh& domainMesh,
794 const labelList& domainFace,
795 const labelList& domainProc,
797 labelList& masterCoupledFaces,
798 labelList& slaveCoupledFaces
801 // Store domain neighbour as map so we can easily look for pair
802 // with same face+proc.
803 HashTable<label, labelPair, labelPair::Hash<> > map(domainFace.size());
805 forAll(domainFace, bFaceI)
807 map.insert(labelPair(domainFace[bFaceI], domainProc[bFaceI]), bFaceI);
811 // Try to match mesh data.
813 masterCoupledFaces.setSize(domainFace.size());
814 slaveCoupledFaces.setSize(domainFace.size());
817 forAll(sourceFace, bFaceI)
819 if (sourceProc[bFaceI] != -1)
821 labelPair myData(sourceFace[bFaceI], sourceProc[bFaceI]);
823 HashTable<label, labelPair, labelPair::Hash<> >::const_iterator
824 iter = map.find(myData);
826 if (iter != map.end())
828 label nbrBFaceI = iter();
830 masterCoupledFaces[coupledI] = mesh.nInternalFaces() + bFaceI;
831 slaveCoupledFaces[coupledI] =
832 domainMesh.nInternalFaces()
840 masterCoupledFaces.setSize(coupledI);
841 slaveCoupledFaces.setSize(coupledI);
845 Pout<< "findCouples : found " << coupledI
846 << " faces that will be stitched" << nl << endl;
851 // Map data on boundary faces to new mesh (resulting from adding two meshes)
852 Foam::labelList Foam::fvMeshDistribute::mapBoundaryData
854 const primitiveMesh& mesh, // mesh after adding
855 const mapAddedPolyMesh& map,
856 const labelList& boundaryData0, // mesh before adding
857 const label nInternalFaces1,
858 const labelList& boundaryData1 // added mesh
861 labelList newBoundaryData(mesh.nFaces() - mesh.nInternalFaces());
863 forAll(boundaryData0, oldBFaceI)
865 label newFaceI = map.oldFaceMap()[oldBFaceI + map.nOldInternalFaces()];
867 // Face still exists (is necessary?) and still boundary face
868 if (newFaceI >= 0 && newFaceI >= mesh.nInternalFaces())
870 newBoundaryData[newFaceI - mesh.nInternalFaces()] =
871 boundaryData0[oldBFaceI];
875 forAll(boundaryData1, addedBFaceI)
877 label newFaceI = map.addedFaceMap()[addedBFaceI + nInternalFaces1];
879 if (newFaceI >= 0 && newFaceI >= mesh.nInternalFaces())
881 newBoundaryData[newFaceI - mesh.nInternalFaces()] =
882 boundaryData1[addedBFaceI];
886 return newBoundaryData;
890 // Remove cells. Add all exposed faces to patch oldInternalPatchI
891 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::doRemoveCells
893 const labelList& cellsToRemove,
894 const label oldInternalPatchI
897 // Mesh change engine
898 polyTopoChange meshMod(mesh_);
900 // Cell removal topo engine. Do NOT synchronize parallel since
901 // we are doing a local cell removal.
902 removeCells cellRemover(mesh_, false);
904 // Get all exposed faces
905 labelList exposedFaces(cellRemover.getExposedFaces(cellsToRemove));
907 // Insert the topo changes
908 cellRemover.setRefinement
912 labelList(exposedFaces.size(), oldInternalPatchI), // patch for exposed
917 // Change the mesh. No inflation. Note: no parallel comms allowed.
918 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, false);
921 mesh_.updateMesh(map);
923 // Move mesh (since morphing does not do this)
924 if (map().hasMotionPoints())
926 mesh_.movePoints(map().preMotionPoints());
933 // Delete and add processor patches. Changes mesh and returns per neighbour proc
934 // the processor patchID.
935 void Foam::fvMeshDistribute::addProcPatches
937 const labelList& neighbourNewProc, // processor that neighbour is on
938 labelList& procPatchID
941 // Now use the neighbourFace/Proc to repatch the mesh. These two lists
942 // contain for all current boundary faces the global patchID (for non-proc
943 // patch) or the processor.
945 labelList procPatchSizes(Pstream::nProcs(), 0);
947 forAll(neighbourNewProc, bFaceI)
949 if (neighbourNewProc[bFaceI] != -1)
951 procPatchSizes[neighbourNewProc[bFaceI]]++;
955 // Per neighbour processor the label of the processor patch
956 procPatchID.setSize(Pstream::nProcs());
958 forAll(procPatchSizes, procI)
960 if (procPatchSizes[procI] > 0)
962 const word patchName =
964 + name(Pstream::myProcNo())
969 procPatchID[procI] = addProcPatch(patchName, procI);
970 addPatchFields<volScalarField>
972 processorFvPatchField<scalar>::typeName
974 addPatchFields<volVectorField>
976 processorFvPatchField<vector>::typeName
978 addPatchFields<volSphericalTensorField>
980 processorFvPatchField<sphericalTensor>::typeName
982 addPatchFields<volSymmTensorField>
984 processorFvPatchField<symmTensor>::typeName
986 addPatchFields<volTensorField>
988 processorFvPatchField<tensor>::typeName
991 addPatchFields<surfaceScalarField>
993 processorFvPatchField<scalar>::typeName
995 addPatchFields<surfaceVectorField>
997 processorFvPatchField<vector>::typeName
999 addPatchFields<surfaceSphericalTensorField>
1001 processorFvPatchField<sphericalTensor>::typeName
1003 addPatchFields<surfaceSymmTensorField>
1005 processorFvPatchField<symmTensor>::typeName
1007 addPatchFields<surfaceTensorField>
1009 processorFvPatchField<tensor>::typeName
1014 procPatchID[procI] = -1;
1020 // Get boundary faces to be repatched. Is -1 or new patchID
1021 Foam::labelList Foam::fvMeshDistribute::getProcBoundaryPatch
1023 const labelList& neighbourNewProc, // new processor per boundary face
1024 const labelList& procPatchID // patchID
1027 labelList patchIDs(neighbourNewProc);
1029 forAll(neighbourNewProc, bFaceI)
1031 if (neighbourNewProc[bFaceI] != -1)
1033 label nbrProc = neighbourNewProc[bFaceI];
1035 patchIDs[bFaceI] = procPatchID[nbrProc];
1039 patchIDs[bFaceI] = -1;
1046 // Send mesh and coupling data.
1047 void Foam::fvMeshDistribute::sendMesh
1052 const wordList& pointZoneNames,
1053 const wordList& faceZoneNames,
1054 const wordList& cellZoneNames,
1056 const labelList& sourceFace,
1057 const labelList& sourceProc,
1058 const labelList& sourceNewProc,
1064 Pout<< "Sending to domain " << domain << nl
1065 << " nPoints:" << mesh.nPoints() << nl
1066 << " nFaces:" << mesh.nFaces() << nl
1067 << " nCells:" << mesh.nCells() << nl
1068 << " nPatches:" << mesh.boundaryMesh().size() << nl
1072 // Assume sparse, possibly overlapping point zones. Get contents
1073 // in merged-zone indices.
1074 CompactListList_dev<label> zonePoints;
1076 const pointZoneMesh& pointZones = mesh.pointZones();
1078 labelList rowSizes(pointZoneNames.size(), 0);
1080 forAll(pointZoneNames, nameI)
1082 label myZoneID = pointZones.findZoneID(pointZoneNames[nameI]);
1086 rowSizes[nameI] = pointZones[myZoneID].size();
1089 zonePoints.setSize(rowSizes);
1091 forAll(pointZoneNames, nameI)
1093 label myZoneID = pointZones.findZoneID(pointZoneNames[nameI]);
1097 zonePoints[nameI].assign(pointZones[myZoneID]);
1102 // Assume sparse, possibly overlapping face zones
1103 CompactListList_dev<label> zoneFaces;
1104 CompactListList_dev<bool> zoneFaceFlip;
1106 const faceZoneMesh& faceZones = mesh.faceZones();
1108 labelList rowSizes(faceZoneNames.size(), 0);
1110 forAll(faceZoneNames, nameI)
1112 label myZoneID = faceZones.findZoneID(faceZoneNames[nameI]);
1116 rowSizes[nameI] = faceZones[myZoneID].size();
1120 zoneFaces.setSize(rowSizes);
1121 zoneFaceFlip.setSize(rowSizes);
1123 forAll(faceZoneNames, nameI)
1125 label myZoneID = faceZones.findZoneID(faceZoneNames[nameI]);
1129 zoneFaces[nameI].assign(faceZones[myZoneID]);
1130 zoneFaceFlip[nameI].assign(faceZones[myZoneID].flipMap());
1135 // Assume sparse, possibly overlapping cell zones
1136 CompactListList_dev<label> zoneCells;
1138 const cellZoneMesh& cellZones = mesh.cellZones();
1140 labelList rowSizes(cellZoneNames.size(), 0);
1142 forAll(cellZoneNames, nameI)
1144 label myZoneID = cellZones.findZoneID(cellZoneNames[nameI]);
1148 rowSizes[nameI] = cellZones[myZoneID].size();
1152 zoneCells.setSize(rowSizes);
1154 forAll(cellZoneNames, nameI)
1156 label myZoneID = cellZones.findZoneID(cellZoneNames[nameI]);
1160 zoneCells[nameI].assign(cellZones[myZoneID]);
1164 ////- Assume full cell zones
1165 //labelList cellZoneID;
1168 // cellZoneID.setSize(mesh.nCells());
1171 // const cellZoneMesh& cellZones = mesh.cellZones();
1173 // forAll(cellZones, zoneI)
1175 // UIndirectList<label>(cellZoneID, cellZones[zoneI]) = zoneI;
1182 << CompactListList_dev<label, face>(mesh.faces())
1184 << mesh.faceNeighbour()
1185 << mesh.boundaryMesh()
1199 Pout<< "Started sending mesh to domain " << domain
1205 // Receive mesh. Opposite of sendMesh
1206 Foam::autoPtr<Foam::fvMesh> Foam::fvMeshDistribute::receiveMesh
1209 const wordList& pointZoneNames,
1210 const wordList& faceZoneNames,
1211 const wordList& cellZoneNames,
1212 const Time& runTime,
1213 labelList& domainSourceFace,
1214 labelList& domainSourceProc,
1215 labelList& domainSourceNewProc,
1219 pointField domainPoints(fromNbr);
1220 faceList domainFaces = CompactListList_dev<label, face>(fromNbr)();
1221 labelList domainAllOwner(fromNbr);
1222 labelList domainAllNeighbour(fromNbr);
1223 PtrList<entry> patchEntries(fromNbr);
1225 CompactListList_dev<label> zonePoints(fromNbr);
1226 CompactListList_dev<label> zoneFaces(fromNbr);
1227 CompactListList_dev<bool> zoneFaceFlip(fromNbr);
1228 CompactListList_dev<label> zoneCells(fromNbr);
1233 >> domainSourceNewProc;
1236 autoPtr<fvMesh> domainMeshPtr
1242 fvMesh::defaultRegion,
1247 xferMove(domainPoints),
1248 xferMove(domainFaces),
1249 xferMove(domainAllOwner),
1250 xferMove(domainAllNeighbour),
1251 false // no parallel comms
1254 fvMesh& domainMesh = domainMeshPtr();
1256 List<polyPatch*> patches(patchEntries.size());
1258 forAll(patchEntries, patchI)
1260 patches[patchI] = polyPatch::New
1262 patchEntries[patchI].keyword(),
1263 patchEntries[patchI].dict(),
1265 domainMesh.boundaryMesh()
1268 // Add patches; no parallel comms
1269 domainMesh.addFvPatches(patches, false);
1272 List<pointZone*> pZonePtrs(pointZoneNames.size());
1273 forAll(pZonePtrs, i)
1275 pZonePtrs[i] = new pointZone
1280 domainMesh.pointZones()
1284 List<faceZone*> fZonePtrs(faceZoneNames.size());
1285 forAll(fZonePtrs, i)
1287 fZonePtrs[i] = new faceZone
1293 domainMesh.faceZones()
1297 List<cellZone*> cZonePtrs(cellZoneNames.size());
1298 forAll(cZonePtrs, i)
1300 cZonePtrs[i] = new cellZone
1305 domainMesh.cellZones()
1308 domainMesh.addZones(pZonePtrs, fZonePtrs, cZonePtrs);
1310 return domainMeshPtr;
1314 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1316 // Construct from components
1317 Foam::fvMeshDistribute::fvMeshDistribute(fvMesh& mesh, const scalar mergeTol)
1324 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1326 Foam::labelList Foam::fvMeshDistribute::countCells
1328 const labelList& distribution
1331 labelList nCells(Pstream::nProcs(), 0);
1332 forAll(distribution, cellI)
1334 label newProc = distribution[cellI];
1336 if (newProc < 0 || newProc >= Pstream::nProcs())
1338 FatalErrorIn("fvMeshDistribute::distribute(const labelList&)")
1339 << "Distribution should be in range 0.." << Pstream::nProcs()-1
1341 << "At index " << cellI << " distribution:" << newProc
1342 << abort(FatalError);
1350 Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
1352 const labelList& distribution
1355 // Some checks on distribution
1356 if (distribution.size() != mesh_.nCells())
1358 FatalErrorIn("fvMeshDistribute::distribute(const labelList&)")
1359 << "Size of distribution:"
1360 << distribution.size() << " mesh nCells:" << mesh_.nCells()
1361 << abort(FatalError);
1365 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
1367 // Check all processors have same non-proc patches in same order.
1368 if (patches.checkParallelSync(true))
1370 FatalErrorIn("fvMeshDistribute::distribute(const labelList&)")
1371 << "This application requires all non-processor patches"
1372 << " to be present in the same order on all patches" << nl
1373 << "followed by the processor patches (which of course are unique)."
1375 << "Local patches:" << mesh_.boundaryMesh().names()
1376 << abort(FatalError);
1379 // Save some data for mapping later on
1380 const label nOldPoints(mesh_.nPoints());
1381 const label nOldFaces(mesh_.nFaces());
1382 const label nOldCells(mesh_.nCells());
1383 labelList oldPatchStarts(patches.size());
1384 labelList oldPatchNMeshPoints(patches.size());
1385 forAll(patches, patchI)
1387 oldPatchStarts[patchI] = patches[patchI].start();
1388 oldPatchNMeshPoints[patchI] = patches[patchI].nPoints();
1393 // Short circuit trivial case.
1394 if (!Pstream::parRun())
1396 // Collect all maps and return
1397 return autoPtr<mapDistributePolyMesh>
1399 new mapDistributePolyMesh
1406 oldPatchStarts.xfer(),
1407 oldPatchNMeshPoints.xfer(),
1409 labelListList(1, identity(mesh_.nPoints())).xfer(),//subPointMap
1410 labelListList(1, identity(mesh_.nFaces())).xfer(), //subFaceMap
1411 labelListList(1, identity(mesh_.nCells())).xfer(), //subCellMap
1412 labelListList(1, identity(patches.size())).xfer(), //subPatchMap
1414 labelListList(1, identity(mesh_.nPoints())).xfer(),//pointMap
1415 labelListList(1, identity(mesh_.nFaces())).xfer(), //faceMap
1416 labelListList(1, identity(mesh_.nCells())).xfer(), //cellMap
1417 labelListList(1, identity(patches.size())).xfer() //patchMap
1423 // Collect any zone names
1424 const wordList pointZoneNames(mergeWordList(mesh_.pointZones().names()));
1425 const wordList faceZoneNames(mergeWordList(mesh_.faceZones().names()));
1426 const wordList cellZoneNames(mergeWordList(mesh_.cellZones().names()));
1430 // Local environment of all boundary faces
1431 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1433 // A face is uniquely defined by
1437 // To glue the parts of meshes which can get sent from anywhere we
1438 // need to know on boundary faces what the above tuple on both sides is.
1439 // So we need to maintain:
1441 // - original processor id (= trivial)
1442 // For coupled boundaries (where the faces are 'duplicate') we take the
1443 // lowest numbered processor as the data to store.
1445 // Additionally to create the procboundaries we need to know where the owner
1446 // cell on the other side now is: newNeighbourProc.
1449 // physical boundary:
1451 // sourceNewProc = -1
1452 // sourceFace = patchID
1453 // coupled boundary:
1454 // sourceProc = proc
1455 // sourceNewProc = distribution[cell on proc]
1456 // sourceFace = face
1457 labelList sourceFace;
1458 labelList sourceProc;
1459 labelList sourceNewProc;
1460 getNeighbourData(distribution, sourceFace, sourceProc, sourceNewProc);
1463 // Remove meshPhi. Since this would otherwise dissappear anyway
1464 // during topo changes and we have to guarantee that all the fields
1467 mesh_.resetMotion();
1469 // Get data to send. Make sure is synchronised
1470 const wordList volScalars(mesh_.names(volScalarField::typeName));
1471 checkEqualWordList("volScalarFields", volScalars);
1472 const wordList volVectors(mesh_.names(volVectorField::typeName));
1473 checkEqualWordList("volVectorFields", volVectors);
1474 const wordList volSphereTensors
1476 mesh_.names(volSphericalTensorField::typeName)
1478 checkEqualWordList("volSphericalTensorFields", volSphereTensors);
1479 const wordList volSymmTensors(mesh_.names(volSymmTensorField::typeName));
1480 checkEqualWordList("volSymmTensorFields", volSymmTensors);
1481 const wordList volTensors(mesh_.names(volTensorField::typeName));
1482 checkEqualWordList("volTensorField", volTensors);
1484 const wordList surfScalars(mesh_.names(surfaceScalarField::typeName));
1485 checkEqualWordList("surfaceScalarFields", surfScalars);
1486 const wordList surfVectors(mesh_.names(surfaceVectorField::typeName));
1487 checkEqualWordList("surfaceVectorFields", surfVectors);
1488 const wordList surfSphereTensors
1490 mesh_.names(surfaceSphericalTensorField::typeName)
1492 checkEqualWordList("surfaceSphericalTensorFields", surfSphereTensors);
1493 const wordList surfSymmTensors
1495 mesh_.names(surfaceSymmTensorField::typeName)
1497 checkEqualWordList("surfaceSymmTensorFields", surfSymmTensors);
1498 const wordList surfTensors(mesh_.names(surfaceTensorField::typeName));
1499 checkEqualWordList("surfaceTensorFields", surfTensors);
1504 // Find patch to temporarily put exposed and processor faces into.
1505 label oldInternalPatchI = findNonEmptyPatch();
1509 // Delete processor patches, starting from the back. Move all faces into
1510 // oldInternalPatchI.
1511 labelList repatchFaceMap;
1513 autoPtr<mapPolyMesh> repatchMap = deleteProcPatches(oldInternalPatchI);
1515 // Store face map (only face ordering that changed)
1516 repatchFaceMap = repatchMap().faceMap();
1518 // Reorder all boundary face data (sourceProc, sourceFace etc.)
1523 repatchMap().reverseFaceMap(),
1524 mesh_.nFaces() - mesh_.nInternalFaces(),
1525 mesh_.nInternalFaces()
1527 - mesh_.nInternalFaces()
1530 inplaceReorder(bFaceMap, sourceFace);
1531 inplaceReorder(bFaceMap, sourceProc);
1532 inplaceReorder(bFaceMap, sourceNewProc);
1540 Pout<< nl << "MESH WITH PROC PATCHES DELETED:" << endl;
1541 printMeshInfo(mesh_);
1542 printFieldInfo<volScalarField>(mesh_);
1543 printFieldInfo<volVectorField>(mesh_);
1544 printFieldInfo<volSphericalTensorField>(mesh_);
1545 printFieldInfo<volSymmTensorField>(mesh_);
1546 printFieldInfo<volTensorField>(mesh_);
1547 printFieldInfo<surfaceScalarField>(mesh_);
1548 printFieldInfo<surfaceVectorField>(mesh_);
1549 printFieldInfo<surfaceSphericalTensorField>(mesh_);
1550 printFieldInfo<surfaceSymmTensorField>(mesh_);
1551 printFieldInfo<surfaceTensorField>(mesh_);
1557 // Maps from subsetted mesh (that is sent) back to original maps
1558 labelListList subCellMap(Pstream::nProcs());
1559 labelListList subFaceMap(Pstream::nProcs());
1560 labelListList subPointMap(Pstream::nProcs());
1561 labelListList subPatchMap(Pstream::nProcs());
1562 // Maps from subsetted mesh to reconstructed mesh
1563 labelListList constructCellMap(Pstream::nProcs());
1564 labelListList constructFaceMap(Pstream::nProcs());
1565 labelListList constructPointMap(Pstream::nProcs());
1566 labelListList constructPatchMap(Pstream::nProcs());
1571 // Find out schedule
1572 // ~~~~~~~~~~~~~~~~~
1574 labelListList nSendCells(Pstream::nProcs());
1575 nSendCells[Pstream::myProcNo()] = countCells(distribution);
1576 Pstream::gatherList(nSendCells);
1577 Pstream::scatterList(nSendCells);
1581 PtrList<OStringStream> sendStr(Pstream::nProcs());
1584 sendStr.set(i, new OStringStream(IOstream::BINARY));
1586 //PstreamBuffers pBufs(Pstream::nonBlocking);
1589 // What to send to neighbouring domains
1590 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1592 forAll(nSendCells[Pstream::myProcNo()], recvProc)
1596 recvProc != Pstream::myProcNo()
1597 && nSendCells[Pstream::myProcNo()][recvProc] > 0
1605 << "SUBSETTING FOR DOMAIN " << recvProc
1606 << " cells to send:"
1607 << nSendCells[Pstream::myProcNo()][recvProc]
1611 // Pstream for sending mesh and fields
1612 //OPstream str(Pstream::blocking, recvProc);
1613 //UOPstream str(recvProc, pBufs);
1615 // Mesh subsetting engine
1616 fvMeshSubset subsetter(mesh_);
1618 // Subset the cells of the current domain.
1619 subsetter.setLargeCellSubset
1623 oldInternalPatchI, // oldInternalFaces patch
1624 false // no parallel sync
1627 subCellMap[recvProc] = subsetter.cellMap();
1628 subFaceMap[recvProc] = renumber
1633 subPointMap[recvProc] = subsetter.pointMap();
1634 subPatchMap[recvProc] = subsetter.patchMap();
1637 // Subset the boundary fields (owner/neighbour/processor)
1638 labelList procSourceFace;
1639 labelList procSourceProc;
1640 labelList procSourceNewProc;
1644 subsetter.subMesh(),
1645 subsetter.faceMap(), // from subMesh to mesh
1646 subsetter.cellMap(), // ,, ,,
1648 distribution, // old mesh distribution
1649 mesh_.faceOwner(), // old owner
1650 mesh_.faceNeighbour(),
1651 mesh_.nInternalFaces(),
1664 // Send to neighbour
1668 subsetter.subMesh(),
1679 sendFields<volScalarField>
1686 sendFields<volVectorField>
1693 sendFields<volSphericalTensorField>
1700 sendFields<volSymmTensorField>
1707 sendFields<volTensorField>
1715 sendFields<surfaceScalarField>
1722 sendFields<surfaceVectorField>
1729 sendFields<surfaceSphericalTensorField>
1736 sendFields<surfaceSymmTensorField>
1743 sendFields<surfaceTensorField>
1754 // Start sending&receiving from buffers
1755 //pBufs.finishedSends();
1758 PtrList<IStringStream> recvStr(Pstream::nProcs());
1760 List<List<char> > sendBufs(sendStr.size());
1761 forAll(sendStr, procI)
1763 string contents = sendStr[procI].str();
1764 const char* ptr = contents.data();
1766 sendBufs[procI].setSize(contents.size());
1767 forAll(sendBufs[procI], i)
1769 sendBufs[procI][i] = *ptr++;
1771 // Clear OStringStream
1772 sendStr.set(procI, NULL);
1775 // Transfer sendBufs into recvBufs
1776 List<List<char> > recvBufs(Pstream::nProcs());
1777 labelListList sizes(Pstream::nProcs());
1778 exchange<List<char>, char>(sendBufs, recvBufs, sizes);
1780 forAll(recvStr, procI)
1782 string contents(recvBufs[procI].begin(), recvBufs[procI].size());
1786 new IStringStream(contents, IOstream::BINARY)
1792 // Subset the part that stays
1793 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
1796 // Save old mesh maps before changing mesh
1797 const labelList oldFaceOwner(mesh_.faceOwner());
1798 const labelList oldFaceNeighbour(mesh_.faceNeighbour());
1799 const label oldInternalFaces = mesh_.nInternalFaces();
1802 autoPtr<mapPolyMesh> subMap
1806 select(false, distribution, Pstream::myProcNo()),
1811 // Addressing from subsetted mesh
1812 subCellMap[Pstream::myProcNo()] = subMap().cellMap();
1813 subFaceMap[Pstream::myProcNo()] = renumber
1818 subPointMap[Pstream::myProcNo()] = subMap().pointMap();
1819 subPatchMap[Pstream::myProcNo()] = identity(patches.size());
1821 // Initialize all addressing into current mesh
1822 constructCellMap[Pstream::myProcNo()] = identity(mesh_.nCells());
1823 constructFaceMap[Pstream::myProcNo()] = identity(mesh_.nFaces());
1824 constructPointMap[Pstream::myProcNo()] = identity(mesh_.nPoints());
1825 constructPatchMap[Pstream::myProcNo()] = identity(patches.size());
1827 // Subset the mesh data: neighbourCell/neighbourProc
1829 labelList domainSourceFace;
1830 labelList domainSourceProc;
1831 labelList domainSourceNewProc;
1836 subMap().faceMap(), // from new to original mesh
1839 distribution, // distribution before subsetting
1840 oldFaceOwner, // owner before subsetting
1841 oldFaceNeighbour, // neighbour ,,
1842 oldInternalFaces, // nInternalFaces ,,
1853 sourceFace.transfer(domainSourceFace);
1854 sourceProc.transfer(domainSourceProc);
1855 sourceNewProc.transfer(domainSourceNewProc);
1862 Pout<< nl << "STARTING MESH:" << endl;
1863 printMeshInfo(mesh_);
1864 printFieldInfo<volScalarField>(mesh_);
1865 printFieldInfo<volVectorField>(mesh_);
1866 printFieldInfo<volSphericalTensorField>(mesh_);
1867 printFieldInfo<volSymmTensorField>(mesh_);
1868 printFieldInfo<volTensorField>(mesh_);
1869 printFieldInfo<surfaceScalarField>(mesh_);
1870 printFieldInfo<surfaceVectorField>(mesh_);
1871 printFieldInfo<surfaceSphericalTensorField>(mesh_);
1872 printFieldInfo<surfaceSymmTensorField>(mesh_);
1873 printFieldInfo<surfaceTensorField>(mesh_);
1879 // Receive and add what was sent
1880 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1882 forAll(nSendCells, sendProc)
1884 // Did processor sendProc send anything to me?
1887 sendProc != Pstream::myProcNo()
1888 && nSendCells[sendProc][Pstream::myProcNo()] > 0
1894 << "RECEIVING FROM DOMAIN " << sendProc
1895 << " cells to receive:"
1896 << nSendCells[sendProc][Pstream::myProcNo()]
1901 // Pstream for receiving mesh and fields
1902 //UIPstream str(sendProc, pBufs);
1905 // Receive from sendProc
1906 labelList domainSourceFace;
1907 labelList domainSourceProc;
1908 labelList domainSourceNewProc;
1910 autoPtr<fvMesh> domainMeshPtr;
1911 PtrList<volScalarField> vsf;
1912 PtrList<volVectorField> vvf;
1913 PtrList<volSphericalTensorField> vsptf;
1914 PtrList<volSymmTensorField> vsytf;
1915 PtrList<volTensorField> vtf;
1916 PtrList<surfaceScalarField> ssf;
1917 PtrList<surfaceVectorField> svf;
1918 PtrList<surfaceSphericalTensorField> ssptf;
1919 PtrList<surfaceSymmTensorField> ssytf;
1920 PtrList<surfaceTensorField> stf;
1922 // Opposite of sendMesh
1924 domainMeshPtr = receiveMesh
1931 const_cast<Time&>(mesh_.time()),
1934 domainSourceNewProc,
1937 fvMesh& domainMesh = domainMeshPtr();
1939 // Receive fields. Read as single dictionary because
1940 // of problems reading consecutive fields from single stream.
1941 dictionary fieldDicts(recvStr[sendProc]);
1943 receiveFields<volScalarField>
1949 fieldDicts.subDict(volScalarField::typeName)
1951 receiveFields<volVectorField>
1957 fieldDicts.subDict(volVectorField::typeName)
1959 receiveFields<volSphericalTensorField>
1965 fieldDicts.subDict(volSphericalTensorField::typeName)
1967 receiveFields<volSymmTensorField>
1973 fieldDicts.subDict(volSymmTensorField::typeName)
1975 receiveFields<volTensorField>
1981 fieldDicts.subDict(volTensorField::typeName)
1984 receiveFields<surfaceScalarField>
1990 fieldDicts.subDict(surfaceScalarField::typeName)
1992 receiveFields<surfaceVectorField>
1998 fieldDicts.subDict(surfaceVectorField::typeName)
2000 receiveFields<surfaceSphericalTensorField>
2006 fieldDicts.subDict(surfaceSphericalTensorField::typeName)
2008 receiveFields<surfaceSymmTensorField>
2014 fieldDicts.subDict(surfaceSymmTensorField::typeName)
2016 receiveFields<surfaceTensorField>
2022 fieldDicts.subDict(surfaceTensorField::typeName)
2025 const fvMesh& domainMesh = domainMeshPtr();
2028 constructCellMap[sendProc] = identity(domainMesh.nCells());
2029 constructFaceMap[sendProc] = identity(domainMesh.nFaces());
2030 constructPointMap[sendProc] = identity(domainMesh.nPoints());
2031 constructPatchMap[sendProc] =
2032 identity(domainMesh.boundaryMesh().size());
2038 Pout<< nl << "RECEIVED MESH FROM:" << sendProc << endl;
2039 printMeshInfo(domainMesh);
2040 printFieldInfo<volScalarField>(domainMesh);
2041 printFieldInfo<volVectorField>(domainMesh);
2042 printFieldInfo<volSphericalTensorField>(domainMesh);
2043 printFieldInfo<volSymmTensorField>(domainMesh);
2044 printFieldInfo<volTensorField>(domainMesh);
2045 printFieldInfo<surfaceScalarField>(domainMesh);
2046 printFieldInfo<surfaceVectorField>(domainMesh);
2047 printFieldInfo<surfaceSphericalTensorField>(domainMesh);
2048 printFieldInfo<surfaceSymmTensorField>(domainMesh);
2049 printFieldInfo<surfaceTensorField>(domainMesh);
2053 // Now this mesh we received (from sendProc) needs to be merged
2054 // with the current mesh. On the current mesh we have for all
2055 // boundaryfaces the original face and processor. See if we can
2056 // match these up to the received domainSourceFace and
2057 // domainSourceProc.
2058 labelList masterCoupledFaces;
2059 labelList slaveCoupledFaces;
2076 // Generate additional coupling info (points, edges) from
2078 faceCoupleInfo couples
2084 mergeTol_, // merge tolerance
2085 true, // faces align
2086 true, // couples are ordered already
2091 // Add domainMesh to mesh
2092 // ~~~~~~~~~~~~~~~~~~~~~~
2094 autoPtr<mapAddedPolyMesh> map = fvMeshAdder::add
2099 false // no parallel comms
2102 // Update mesh data: sourceFace,sourceProc for added
2111 domainMesh.nInternalFaces(),
2120 domainMesh.nInternalFaces(),
2129 domainMesh.nInternalFaces(),
2133 // Update all addressing so xxProcAddressing points to correct item
2135 const labelList& oldCellMap = map().oldCellMap();
2136 const labelList& oldFaceMap = map().oldFaceMap();
2137 const labelList& oldPointMap = map().oldPointMap();
2138 const labelList& oldPatchMap = map().oldPatchMap();
2140 forAll(constructPatchMap, procI)
2142 if (procI != sendProc && constructPatchMap[procI].size())
2144 // Processor already in mesh (either myProcNo or received)
2145 inplaceRenumber(oldCellMap, constructCellMap[procI]);
2146 inplaceRenumber(oldFaceMap, constructFaceMap[procI]);
2147 inplaceRenumber(oldPointMap, constructPointMap[procI]);
2148 inplaceRenumber(oldPatchMap, constructPatchMap[procI]);
2153 inplaceRenumber(map().addedCellMap(), constructCellMap[sendProc]);
2154 inplaceRenumber(map().addedFaceMap(), constructFaceMap[sendProc]);
2155 inplaceRenumber(map().addedPointMap(), constructPointMap[sendProc]);
2156 inplaceRenumber(map().addedPatchMap(), constructPatchMap[sendProc]);
2160 Pout<< nl << "MERGED MESH FROM:" << sendProc << endl;
2161 printMeshInfo(mesh_);
2162 printFieldInfo<volScalarField>(mesh_);
2163 printFieldInfo<volVectorField>(mesh_);
2164 printFieldInfo<volSphericalTensorField>(mesh_);
2165 printFieldInfo<volSymmTensorField>(mesh_);
2166 printFieldInfo<volTensorField>(mesh_);
2167 printFieldInfo<surfaceScalarField>(mesh_);
2168 printFieldInfo<surfaceVectorField>(mesh_);
2169 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2170 printFieldInfo<surfaceSymmTensorField>(mesh_);
2171 printFieldInfo<surfaceTensorField>(mesh_);
2181 Pout<< nl << "REDISTRIBUTED MESH:" << endl;
2182 printMeshInfo(mesh_);
2183 printFieldInfo<volScalarField>(mesh_);
2184 printFieldInfo<volVectorField>(mesh_);
2185 printFieldInfo<volSphericalTensorField>(mesh_);
2186 printFieldInfo<volSymmTensorField>(mesh_);
2187 printFieldInfo<volTensorField>(mesh_);
2188 printFieldInfo<surfaceScalarField>(mesh_);
2189 printFieldInfo<surfaceVectorField>(mesh_);
2190 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2191 printFieldInfo<surfaceSymmTensorField>(mesh_);
2192 printFieldInfo<surfaceTensorField>(mesh_);
2198 // Add processorPatches
2199 // ~~~~~~~~~~~~~~~~~~~~
2201 // Per neighbour processor the patchID to it (or -1).
2202 labelList procPatchID;
2204 // Add processor patches.
2205 addProcPatches(sourceNewProc, procPatchID);
2207 // Put faces into correct patch. Note that we now have proper
2208 // processorPolyPatches again so repatching will take care of coupled face
2211 // Get boundary faces to be repatched. Is -1 or new patchID
2212 labelList newPatchID
2214 getProcBoundaryPatch
2221 // Change patches. Since this might change ordering of coupled faces
2222 // we also need to adapt our constructMaps.
2223 repatch(newPatchID, constructFaceMap);
2225 // See if any geometrically shared points need to be merged. Note: does
2227 mergeSharedPoints(constructPointMap);
2229 // Bit of hack: processorFvPatchField does not get reset since created
2230 // from nothing so explicitly reset.
2231 initPatchFields<volScalarField, processorFvPatchField<scalar> >
2233 pTraits<scalar>::zero
2235 initPatchFields<volVectorField, processorFvPatchField<vector> >
2237 pTraits<vector>::zero
2241 volSphericalTensorField,
2242 processorFvPatchField<sphericalTensor>
2245 pTraits<sphericalTensor>::zero
2247 initPatchFields<volSymmTensorField, processorFvPatchField<symmTensor> >
2249 pTraits<symmTensor>::zero
2251 initPatchFields<volTensorField, processorFvPatchField<tensor> >
2253 pTraits<tensor>::zero
2255 initPatchFields<surfaceScalarField, processorFvsPatchField<scalar> >
2257 pTraits<scalar>::zero
2259 initPatchFields<surfaceVectorField, processorFvsPatchField<vector> >
2261 pTraits<vector>::zero
2265 surfaceSphericalTensorField,
2266 processorFvsPatchField<sphericalTensor>
2269 pTraits<sphericalTensor>::zero
2273 surfaceSymmTensorField,
2274 processorFvsPatchField<symmTensor>
2277 pTraits<symmTensor>::zero
2279 initPatchFields<surfaceTensorField, processorFvsPatchField<tensor> >
2281 pTraits<tensor>::zero
2285 mesh_.setInstance(mesh_.time().timeName());
2291 Pout<< nl << "FINAL MESH:" << endl;
2292 printMeshInfo(mesh_);
2293 printFieldInfo<volScalarField>(mesh_);
2294 printFieldInfo<volVectorField>(mesh_);
2295 printFieldInfo<volSphericalTensorField>(mesh_);
2296 printFieldInfo<volSymmTensorField>(mesh_);
2297 printFieldInfo<volTensorField>(mesh_);
2298 printFieldInfo<surfaceScalarField>(mesh_);
2299 printFieldInfo<surfaceVectorField>(mesh_);
2300 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2301 printFieldInfo<surfaceSymmTensorField>(mesh_);
2302 printFieldInfo<surfaceTensorField>(mesh_);
2306 // Collect all maps and return
2307 return autoPtr<mapDistributePolyMesh>
2309 new mapDistributePolyMesh
2317 oldPatchNMeshPoints,
2328 true // reuse storage
2334 // ************************************************************************* //