1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 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 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 "fvMeshDistribute.H"
28 #include "ProcessorTopology.H"
29 #include "commSchedule.H"
30 #include "PstreamCombineReduceOps.H"
31 #include "fvMeshAdder.H"
32 #include "faceCoupleInfo.H"
33 #include "processorFvPatchField.H"
34 #include "polyTopoChange.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"
42 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 defineTypeNameAndDebug(Foam::fvMeshDistribute, 0);
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
49 //Foam::List<Foam::labelPair> Foam::fvMeshDistribute::getSchedule
51 // const labelList& distribution
54 // labelList nCellsPerProc(countCells(distribution));
58 // Pout<< "getSchedule : Wanted distribution:" << nCellsPerProc << endl;
61 // // Processors I need to send data to
62 // labelListList mySendProcs(Pstream::nProcs());
65 // label nSendProcs = 0;
66 // forAll(nCellsPerProc, sendProcI)
68 // if (sendProcI != Pstream::myProcNo() && nCellsPerProc[sendProcI] > 0)
75 // mySendProcs[Pstream::myProcNo()].setSize(nSendProcs);
77 // forAll(nCellsPerProc, sendProcI)
79 // if (sendProcI != Pstream::myProcNo() && nCellsPerProc[sendProcI] > 0)
81 // mySendProcs[Pstream::myProcNo()][nSendProcs++] = sendProcI;
86 // Pstream::gatherList(mySendProcs);
87 // Pstream::scatterList(mySendProcs);
89 // // Combine into list (same on all procs) giving sending and receiving
92 // forAll(mySendProcs, procI)
94 // nComms += mySendProcs[procI].size();
97 // List<labelPair> schedule(nComms);
100 // forAll(mySendProcs, procI)
102 // const labelList& sendProcs = mySendProcs[procI];
104 // forAll(sendProcs, i)
106 // schedule[nComms++] = labelPair(procI, sendProcs[i]);
114 Foam::labelList Foam::fvMeshDistribute::select
116 const bool selectEqual,
117 const labelList& values,
125 if (selectEqual == (values[i] == value))
131 labelList indices(n);
136 if (selectEqual == (values[i] == value))
145 // Check all procs have same names and in exactly same order.
146 void Foam::fvMeshDistribute::checkEqualWordList(const wordList& lst)
148 wordList myObjects(lst);
150 // Check that all meshes have same objects
151 Pstream::listCombineGather(myObjects, checkEqualType());
152 // Below scatter only needed to balance sends and receives.
153 Pstream::listCombineScatter(myObjects);
157 Foam::wordList Foam::fvMeshDistribute::mergeWordList(const wordList& procNames)
159 List<wordList> allNames(Pstream::nProcs());
160 allNames[Pstream::myProcNo()] = procNames;
161 Pstream::gatherList(allNames);
162 Pstream::scatterList(allNames);
164 HashSet<word> mergedNames;
165 forAll(allNames, procI)
167 forAll(allNames[procI], i)
169 mergedNames.insert(allNames[procI][i]);
172 return mergedNames.toc();
176 // Print some info on mesh.
177 void Foam::fvMeshDistribute::printMeshInfo(const fvMesh& mesh)
179 Pout<< "Primitives:" << nl
180 << " points :" << mesh.nPoints() << nl
181 << " internalFaces:" << mesh.nInternalFaces() << nl
182 << " faces :" << mesh.nFaces() << nl
183 << " cells :" << mesh.nCells() << nl;
185 const fvBoundaryMesh& patches = mesh.boundary();
187 Pout<< "Patches:" << endl;
188 forAll(patches, patchI)
190 const polyPatch& pp = patches[patchI].patch();
192 Pout<< " " << patchI << " name:" << pp.name()
193 << " size:" << pp.size()
194 << " start:" << pp.start()
195 << " type:" << pp.type()
199 if (mesh.pointZones().size())
201 Pout<< "PointZones:" << endl;
202 forAll(mesh.pointZones(), zoneI)
204 const pointZone& pz = mesh.pointZones()[zoneI];
205 Pout<< " " << zoneI << " name:" << pz.name()
206 << " size:" << pz.size()
210 if (mesh.faceZones().size())
212 Pout<< "FaceZones:" << endl;
213 forAll(mesh.faceZones(), zoneI)
215 const faceZone& fz = mesh.faceZones()[zoneI];
216 Pout<< " " << zoneI << " name:" << fz.name()
217 << " size:" << fz.size()
221 if (mesh.cellZones().size())
223 Pout<< "CellZones:" << endl;
224 forAll(mesh.cellZones(), zoneI)
226 const cellZone& cz = mesh.cellZones()[zoneI];
227 Pout<< " " << zoneI << " name:" << cz.name()
228 << " size:" << cz.size()
235 void Foam::fvMeshDistribute::printCoupleInfo
237 const primitiveMesh& mesh,
238 const labelList& sourceFace,
239 const labelList& sourceProc,
240 const labelList& sourceNewProc
244 << "Current coupling info:"
247 forAll(sourceFace, bFaceI)
249 label meshFaceI = mesh.nInternalFaces() + bFaceI;
251 Pout<< " meshFace:" << meshFaceI
252 << " fc:" << mesh.faceCentres()[meshFaceI]
253 << " connects to proc:" << sourceProc[bFaceI]
254 << "/face:" << sourceFace[bFaceI]
255 << " which will move to proc:" << sourceNewProc[bFaceI]
261 // Finds (non-empty) patch that exposed internal and proc faces can be put into.
262 Foam::label Foam::fvMeshDistribute::findNonEmptyPatch() const
264 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
266 label nonEmptyPatchI = -1;
268 forAllReverse(patches, patchI)
270 const polyPatch& pp = patches[patchI];
272 if (!isA<emptyPolyPatch>(pp) && !pp.coupled())
274 nonEmptyPatchI = patchI;
279 if (nonEmptyPatchI == -1)
281 FatalErrorIn("fvMeshDistribute::findNonEmptyPatch() const")
282 << "Cannot find a patch which is neither of type empty nor"
283 << " coupled in patches " << patches.names() << endl
284 << "There has to be at least one such patch for"
285 << " distribution to work" << abort(FatalError);
290 Pout<< "findNonEmptyPatch : using patch " << nonEmptyPatchI
291 << " name:" << patches[nonEmptyPatchI].name()
292 << " type:" << patches[nonEmptyPatchI].type()
293 << " to put exposed faces into." << endl;
297 // Do additional test for processor patches intermingled with non-proc
299 label procPatchI = -1;
301 forAll(patches, patchI)
303 if (isA<processorPolyPatch>(patches[patchI]))
307 else if (procPatchI != -1)
309 FatalErrorIn("fvMeshDistribute::findNonEmptyPatch() const")
310 << "Processor patches should be at end of patch list."
312 << "Have processor patch " << procPatchI
313 << " followed by non-processor patch " << patchI
314 << " in patches " << patches.names()
315 << abort(FatalError);
319 return nonEmptyPatchI;
323 // Appends processorPolyPatch. Returns patchID.
324 Foam::label Foam::fvMeshDistribute::addProcPatch
326 const word& patchName,
330 // Clear local fields and e.g. polyMesh globalMeshData.
334 polyBoundaryMesh& polyPatches =
335 const_cast<polyBoundaryMesh&>(mesh_.boundaryMesh());
336 fvBoundaryMesh& fvPatches = const_cast<fvBoundaryMesh&>(mesh_.boundary());
338 if (polyPatches.findPatchID(patchName) != -1)
340 FatalErrorIn("fvMeshDistribute::addProcPatch(const word&, const label)")
341 << "Cannot create patch " << patchName << " since already exists."
343 << "Current patch names:" << polyPatches.names()
352 label sz = polyPatches.size();
355 polyPatches.setSize(sz+1);
359 new processorPolyPatch
365 mesh_.boundaryMesh(),
370 fvPatches.setSize(sz+1);
376 polyPatches[sz], // point to newly added polyPatch
385 // Deletes last patch
386 void Foam::fvMeshDistribute::deleteTrailingPatch()
388 // Clear local fields and e.g. polyMesh globalMeshData.
391 polyBoundaryMesh& polyPatches =
392 const_cast<polyBoundaryMesh&>(mesh_.boundaryMesh());
393 fvBoundaryMesh& fvPatches = const_cast<fvBoundaryMesh&>(mesh_.boundary());
395 if (polyPatches.empty())
397 FatalErrorIn("fvMeshDistribute::deleteTrailingPatch(fvMesh&)")
398 << "No patches in mesh"
399 << abort(FatalError);
402 label sz = polyPatches.size();
404 label nFaces = polyPatches[sz-1].size();
406 // Remove last polyPatch
409 Pout<< "deleteTrailingPatch : Removing patch " << sz-1
410 << " : " << polyPatches[sz-1].name() << " size:" << nFaces << endl;
415 FatalErrorIn("fvMeshDistribute::deleteTrailingPatch()")
416 << "There are still " << nFaces << " faces in patch to be deleted "
417 << sz-1 << ' ' << polyPatches[sz-1].name()
418 << abort(FatalError);
421 // Remove actual patch
422 polyPatches.setSize(sz-1);
423 fvPatches.setSize(sz-1);
427 // Delete all processor patches. Move any processor faces into the last
428 // non-processor patch.
429 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::deleteProcPatches
431 const label destinationPatch
434 // New patchID per boundary faces to be repatched. Is -1 (no change)
436 labelList newPatchID(mesh_.nFaces() - mesh_.nInternalFaces(), -1);
438 label nProcPatches = 0;
440 forAll(mesh_.boundaryMesh(), patchI)
442 const polyPatch& pp = mesh_.boundaryMesh()[patchI];
444 if (isA<processorPolyPatch>(pp))
448 Pout<< "Moving all faces of patch " << pp.name()
449 << " into patch " << destinationPatch
453 label offset = pp.start() - mesh_.nInternalFaces();
457 newPatchID[offset+i] = destinationPatch;
464 // Note: order of boundary faces been kept the same since the
465 // destinationPatch is at the end and we have visited the patches in
466 // incremental order.
467 labelListList dummyFaceMaps;
468 autoPtr<mapPolyMesh> map = repatch(newPatchID, dummyFaceMaps);
471 // Delete (now empty) processor patches.
472 forAllReverse(mesh_.boundaryMesh(), patchI)
474 const polyPatch& pp = mesh_.boundaryMesh()[patchI];
476 if (isA<processorPolyPatch>(pp))
478 deleteTrailingPatch();
479 deleteTrailingPatchFields<volScalarField>();
480 deleteTrailingPatchFields<volVectorField>();
481 deleteTrailingPatchFields<volSphericalTensorField>();
482 deleteTrailingPatchFields<volSymmTensorField>();
483 deleteTrailingPatchFields<volTensorField>();
485 deleteTrailingPatchFields<surfaceScalarField>();
486 deleteTrailingPatchFields<surfaceVectorField>();
487 deleteTrailingPatchFields<surfaceSphericalTensorField>();
488 deleteTrailingPatchFields<surfaceSymmTensorField>();
489 deleteTrailingPatchFields<surfaceTensorField>();
498 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::repatch
500 const labelList& newPatchID, // per boundary face -1 or new patchID
501 labelListList& constructFaceMap
504 polyTopoChange meshMod(mesh_);
506 forAll(newPatchID, bFaceI)
508 if (newPatchID[bFaceI] != -1)
510 label faceI = mesh_.nInternalFaces() + bFaceI;
512 label zoneID = mesh_.faceZones().whichZone(faceI);
513 bool zoneFlip = false;
517 const faceZone& fZone = mesh_.faceZones()[zoneID];
518 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
525 mesh_.faces()[faceI], // modified face
526 faceI, // label of face
527 mesh_.faceOwner()[faceI], // owner
530 newPatchID[bFaceI], // patch for face
531 false, // remove from zone
532 zoneID, // zone for face
533 zoneFlip // face flip in zone
540 // Do mapping of fields from one patchField to the other ourselves since
541 // is currently not supported by updateMesh.
543 // Store boundary fields (we only do this for surfaceFields)
544 PtrList<FieldField<fvsPatchField, scalar> > sFlds;
545 saveBoundaryFields<scalar, surfaceMesh>(sFlds);
546 PtrList<FieldField<fvsPatchField, vector> > vFlds;
547 saveBoundaryFields<vector, surfaceMesh>(vFlds);
548 PtrList<FieldField<fvsPatchField, sphericalTensor> > sptFlds;
549 saveBoundaryFields<sphericalTensor, surfaceMesh>(sptFlds);
550 PtrList<FieldField<fvsPatchField, symmTensor> > sytFlds;
551 saveBoundaryFields<symmTensor, surfaceMesh>(sytFlds);
552 PtrList<FieldField<fvsPatchField, tensor> > tFlds;
553 saveBoundaryFields<tensor, surfaceMesh>(tFlds);
555 // Change the mesh (no inflation). Note: parallel comms allowed.
556 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
558 // Update fields. No inflation, parallel sync.
559 mesh_.updateMesh(map);
561 // Map patch fields using stored boundary fields. Note: assumes order
562 // of fields has not changed in object registry!
563 mapBoundaryFields<scalar, surfaceMesh>(map, sFlds);
564 mapBoundaryFields<vector, surfaceMesh>(map, vFlds);
565 mapBoundaryFields<sphericalTensor, surfaceMesh>(map, sptFlds);
566 mapBoundaryFields<symmTensor, surfaceMesh>(map, sytFlds);
567 mapBoundaryFields<tensor, surfaceMesh>(map, tFlds);
570 // Move mesh (since morphing does not do this)
571 if (map().hasMotionPoints())
573 mesh_.movePoints(map().preMotionPoints());
576 // Adapt constructMaps.
580 label index = findIndex(map().reverseFaceMap(), -1);
586 "fvMeshDistribute::repatch(const labelList&, labelListList&)"
587 ) << "reverseFaceMap contains -1 at index:"
589 << "This means that the repatch operation was not just"
590 << " a shuffle?" << abort(FatalError);
594 forAll(constructFaceMap, procI)
596 inplaceRenumber(map().reverseFaceMap(), constructFaceMap[procI]);
604 // Detect shared points. Need processor patches to be present.
605 // Background: when adding bits of mesh one can get points which
606 // share the same position but are only detectable to be topologically
607 // the same point when doing parallel analysis. This routine will
608 // merge those points.
609 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::mergeSharedPoints
611 labelListList& constructPointMap
614 // Find out which sets of points get merged and create a map from
615 // mesh point to unique point.
616 Map<label> pointToMaster
618 fvMeshAdder::findSharedPoints
625 if (returnReduce(pointToMaster.size(), sumOp<label>()) == 0)
627 return autoPtr<mapPolyMesh>(NULL);
630 polyTopoChange meshMod(mesh_);
632 fvMeshAdder::mergePoints(mesh_, pointToMaster, meshMod);
634 // Change the mesh (no inflation). Note: parallel comms allowed.
635 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
637 // Update fields. No inflation, parallel sync.
638 mesh_.updateMesh(map);
640 // Adapt constructMaps for merged points.
641 forAll(constructPointMap, procI)
643 labelList& constructMap = constructPointMap[procI];
645 forAll(constructMap, i)
647 label oldPointI = constructMap[i];
649 label newPointI = map().reversePointMap()[oldPointI];
653 constructMap[i] = -newPointI-2;
655 else if (newPointI >= 0)
657 constructMap[i] = newPointI;
661 FatalErrorIn("fvMeshDistribute::mergeSharedPoints()")
662 << "Problem. oldPointI:" << oldPointI
663 << " newPointI:" << newPointI << abort(FatalError);
666 //- old: use pointToMaster map.
667 //forAll(constructMap, i)
669 // label oldPointI = constructMap[i];
671 // // See if merged into other point
672 // Map<label>::const_iterator iter = pointToMaster.find(oldPointI);
674 // if (iter != pointToMaster.end())
676 // oldPointI = iter();
679 // constructMap[i] = map().reversePointMap()[oldPointI];
686 // Construct the local environment of all boundary faces.
687 void Foam::fvMeshDistribute::getNeighbourData
689 const labelList& distribution,
690 labelList& sourceFace,
691 labelList& sourceProc,
692 labelList& sourceNewProc
695 sourceFace.setSize(mesh_.nFaces() - mesh_.nInternalFaces());
696 sourceProc.setSize(sourceFace.size());
697 sourceNewProc.setSize(sourceFace.size());
699 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
701 // Send meshFace labels of processor patches and destination processor.
702 forAll(patches, patchI)
704 const polyPatch& pp = patches[patchI];
706 if (isA<processorPolyPatch>(pp))
708 const processorPolyPatch& procPatch =
709 refCast<const processorPolyPatch>(pp);
711 // Labels of faces on this side
712 labelList meshFaceLabels(pp.size());
713 forAll(meshFaceLabels, i)
715 meshFaceLabels[i] = pp.start()+i;
718 // Which processor they will end up on
719 const labelList newProc
721 UIndirectList<label>(distribution, pp.faceCells())
724 OPstream toNeighbour(Pstream::blocking, procPatch.neighbProcNo());
726 toNeighbour << meshFaceLabels << newProc;
730 // Receive meshFace labels and destination processors of processor faces.
731 forAll(patches, patchI)
733 const polyPatch& pp = patches[patchI];
735 label offset = pp.start() - mesh_.nInternalFaces();
737 if (isA<processorPolyPatch>(pp))
739 const processorPolyPatch& procPatch =
740 refCast<const processorPolyPatch>(pp);
743 IPstream fromNeighbour(Pstream::blocking, procPatch.neighbProcNo());
744 labelList nbrFaces(fromNeighbour);
745 labelList nbrNewProc(fromNeighbour);
747 // Check which of the two faces we store.
749 if (Pstream::myProcNo() < procPatch.neighbProcNo())
751 // Use my local face labels
754 sourceFace[offset + i] = pp.start()+i;
755 sourceProc[offset + i] = Pstream::myProcNo();
756 sourceNewProc[offset + i] = nbrNewProc[i];
761 // Use my neighbours face labels
764 sourceFace[offset + i] = nbrFaces[i];
765 sourceProc[offset + i] = procPatch.neighbProcNo();
766 sourceNewProc[offset + i] = nbrNewProc[i];
772 // Normal (physical) boundary
775 sourceFace[offset + i] = patchI;
776 sourceProc[offset + i] = -1;
777 sourceNewProc[offset + i] = -1;
784 // Subset the neighbourCell/neighbourProc fields
785 void Foam::fvMeshDistribute::subsetBoundaryData
788 const labelList& faceMap,
789 const labelList& cellMap,
791 const labelList& oldDistribution,
792 const labelList& oldFaceOwner,
793 const labelList& oldFaceNeighbour,
794 const label oldInternalFaces,
796 const labelList& sourceFace,
797 const labelList& sourceProc,
798 const labelList& sourceNewProc,
802 labelList& subNewProc
805 subFace.setSize(mesh.nFaces() - mesh.nInternalFaces());
806 subProc.setSize(mesh.nFaces() - mesh.nInternalFaces());
807 subNewProc.setSize(mesh.nFaces() - mesh.nInternalFaces());
809 forAll(subFace, newBFaceI)
811 label newFaceI = newBFaceI + mesh.nInternalFaces();
813 label oldFaceI = faceMap[newFaceI];
815 // Was oldFaceI internal face? If so which side did we get.
816 if (oldFaceI < oldInternalFaces)
818 subFace[newBFaceI] = oldFaceI;
819 subProc[newBFaceI] = Pstream::myProcNo();
821 label oldOwn = oldFaceOwner[oldFaceI];
822 label oldNei = oldFaceNeighbour[oldFaceI];
824 if (oldOwn == cellMap[mesh.faceOwner()[newFaceI]])
826 // We kept the owner side. Where does the neighbour move to?
827 subNewProc[newBFaceI] = oldDistribution[oldNei];
831 // We kept the neighbour side.
832 subNewProc[newBFaceI] = oldDistribution[oldOwn];
837 // Was boundary face. Take over boundary information
838 label oldBFaceI = oldFaceI - oldInternalFaces;
840 subFace[newBFaceI] = sourceFace[oldBFaceI];
841 subProc[newBFaceI] = sourceProc[oldBFaceI];
842 subNewProc[newBFaceI] = sourceNewProc[oldBFaceI];
848 // Find cells on mesh whose faceID/procID match the neighbour cell/proc of
849 // domainMesh. Store the matching face.
850 void Foam::fvMeshDistribute::findCouples
852 const primitiveMesh& mesh,
853 const labelList& sourceFace,
854 const labelList& sourceProc,
857 const primitiveMesh& domainMesh,
858 const labelList& domainFace,
859 const labelList& domainProc,
861 labelList& masterCoupledFaces,
862 labelList& slaveCoupledFaces
865 // Store domain neighbour as map so we can easily look for pair
866 // with same face+proc.
867 HashTable<label, labelPair, labelPair::Hash<> > map(domainFace.size());
869 forAll(domainFace, bFaceI)
871 map.insert(labelPair(domainFace[bFaceI], domainProc[bFaceI]), bFaceI);
875 // Try to match mesh data.
877 masterCoupledFaces.setSize(domainFace.size());
878 slaveCoupledFaces.setSize(domainFace.size());
881 forAll(sourceFace, bFaceI)
883 if (sourceProc[bFaceI] != -1)
885 labelPair myData(sourceFace[bFaceI], sourceProc[bFaceI]);
887 HashTable<label, labelPair, labelPair::Hash<> >::const_iterator
888 iter = map.find(myData);
890 if (iter != map.end())
892 label nbrBFaceI = iter();
894 masterCoupledFaces[coupledI] = mesh.nInternalFaces() + bFaceI;
895 slaveCoupledFaces[coupledI] =
896 domainMesh.nInternalFaces()
904 masterCoupledFaces.setSize(coupledI);
905 slaveCoupledFaces.setSize(coupledI);
909 Pout<< "findCouples : found " << coupledI
910 << " faces that will be stitched" << nl << endl;
915 // Map data on boundary faces to new mesh (resulting from adding two meshes)
916 Foam::labelList Foam::fvMeshDistribute::mapBoundaryData
918 const primitiveMesh& mesh, // mesh after adding
919 const mapAddedPolyMesh& map,
920 const labelList& boundaryData0, // mesh before adding
921 const label nInternalFaces1,
922 const labelList& boundaryData1 // added mesh
925 labelList newBoundaryData(mesh.nFaces() - mesh.nInternalFaces());
927 forAll(boundaryData0, oldBFaceI)
929 label newFaceI = map.oldFaceMap()[oldBFaceI + map.nOldInternalFaces()];
931 // Face still exists (is necessary?) and still boundary face
932 if (newFaceI >= 0 && newFaceI >= mesh.nInternalFaces())
934 newBoundaryData[newFaceI - mesh.nInternalFaces()] =
935 boundaryData0[oldBFaceI];
939 forAll(boundaryData1, addedBFaceI)
941 label newFaceI = map.addedFaceMap()[addedBFaceI + nInternalFaces1];
943 if (newFaceI >= 0 && newFaceI >= mesh.nInternalFaces())
945 newBoundaryData[newFaceI - mesh.nInternalFaces()] =
946 boundaryData1[addedBFaceI];
950 return newBoundaryData;
954 // Remove cells. Add all exposed faces to patch oldInternalPatchI
955 Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::doRemoveCells
957 const labelList& cellsToRemove,
958 const label oldInternalPatchI
961 // Mesh change engine
962 polyTopoChange meshMod(mesh_);
964 // Cell removal topo engine. Do NOT synchronize parallel since
965 // we are doing a local cell removal.
966 removeCells cellRemover(mesh_, false);
968 // Get all exposed faces
969 labelList exposedFaces(cellRemover.getExposedFaces(cellsToRemove));
971 // Insert the topo changes
972 cellRemover.setRefinement
976 labelList(exposedFaces.size(), oldInternalPatchI), // patch for exposed
981 // Change the mesh. No inflation. Note: no parallel comms allowed.
982 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, false);
985 mesh_.updateMesh(map);
987 // Move mesh (since morphing does not do this)
988 if (map().hasMotionPoints())
990 mesh_.movePoints(map().preMotionPoints());
997 // Delete and add processor patches. Changes mesh and returns per neighbour proc
998 // the processor patchID.
999 void Foam::fvMeshDistribute::addProcPatches
1001 const labelList& neighbourNewProc, // processor that neighbour is on
1002 labelList& procPatchID
1005 // Now use the neighbourFace/Proc to repatch the mesh. These two lists
1006 // contain for all current boundary faces the global patchID (for non-proc
1007 // patch) or the processor.
1009 labelList procPatchSizes(Pstream::nProcs(), 0);
1011 forAll(neighbourNewProc, bFaceI)
1013 if (neighbourNewProc[bFaceI] != -1)
1015 procPatchSizes[neighbourNewProc[bFaceI]]++;
1019 // Per neighbour processor the label of the processor patch
1020 procPatchID.setSize(Pstream::nProcs());
1022 forAll(procPatchSizes, procI)
1024 if (procPatchSizes[procI] > 0)
1026 const word patchName =
1028 + name(Pstream::myProcNo())
1033 procPatchID[procI] = addProcPatch(patchName, procI);
1034 addPatchFields<volScalarField>
1036 processorFvPatchField<scalar>::typeName
1038 addPatchFields<volVectorField>
1040 processorFvPatchField<vector>::typeName
1042 addPatchFields<volSphericalTensorField>
1044 processorFvPatchField<sphericalTensor>::typeName
1046 addPatchFields<volSymmTensorField>
1048 processorFvPatchField<symmTensor>::typeName
1050 addPatchFields<volTensorField>
1052 processorFvPatchField<tensor>::typeName
1055 addPatchFields<surfaceScalarField>
1057 processorFvPatchField<scalar>::typeName
1059 addPatchFields<surfaceVectorField>
1061 processorFvPatchField<vector>::typeName
1063 addPatchFields<surfaceSphericalTensorField>
1065 processorFvPatchField<sphericalTensor>::typeName
1067 addPatchFields<surfaceSymmTensorField>
1069 processorFvPatchField<symmTensor>::typeName
1071 addPatchFields<surfaceTensorField>
1073 processorFvPatchField<tensor>::typeName
1078 procPatchID[procI] = -1;
1084 // Get boundary faces to be repatched. Is -1 or new patchID
1085 Foam::labelList Foam::fvMeshDistribute::getProcBoundaryPatch
1087 const labelList& neighbourNewProc, // new processor per boundary face
1088 const labelList& procPatchID // patchID
1091 labelList patchIDs(neighbourNewProc);
1093 forAll(neighbourNewProc, bFaceI)
1095 if (neighbourNewProc[bFaceI] != -1)
1097 label nbrProc = neighbourNewProc[bFaceI];
1099 patchIDs[bFaceI] = procPatchID[nbrProc];
1103 patchIDs[bFaceI] = -1;
1110 // Send mesh and coupling data.
1111 void Foam::fvMeshDistribute::sendMesh
1116 const wordList& pointZoneNames,
1117 const wordList& faceZoneNames,
1118 const wordList& cellZoneNames,
1120 const labelList& sourceFace,
1121 const labelList& sourceProc,
1122 const labelList& sourceNewProc
1127 Pout<< "Sending to domain " << domain << nl
1128 << " nPoints:" << mesh.nPoints() << nl
1129 << " nFaces:" << mesh.nFaces() << nl
1130 << " nCells:" << mesh.nCells() << nl
1131 << " nPatches:" << mesh.boundaryMesh().size() << nl
1135 // Assume sparse point zones. Get contents in merged-zone indices.
1136 labelListList zonePoints(pointZoneNames.size());
1138 const pointZoneMesh& pointZones = mesh.pointZones();
1140 forAll(pointZoneNames, nameI)
1142 label myZoneID = pointZones.findZoneID(pointZoneNames[nameI]);
1146 zonePoints[nameI] = pointZones[myZoneID];
1151 // Assume sparse face zones
1152 labelListList zoneFaces(faceZoneNames.size());
1153 boolListList zoneFaceFlip(faceZoneNames.size());
1155 const faceZoneMesh& faceZones = mesh.faceZones();
1157 forAll(faceZoneNames, nameI)
1159 label myZoneID = faceZones.findZoneID(faceZoneNames[nameI]);
1163 zoneFaces[nameI] = faceZones[myZoneID];
1164 zoneFaceFlip[nameI] = faceZones[myZoneID].flipMap();
1169 // Assume sparse cell zones
1170 labelListList zoneCells(cellZoneNames.size());
1172 const cellZoneMesh& cellZones = mesh.cellZones();
1174 forAll(cellZoneNames, nameI)
1176 label myZoneID = cellZones.findZoneID(cellZoneNames[nameI]);
1180 zoneCells[nameI] = cellZones[myZoneID];
1184 ////- Assume full cell zones
1185 //labelList cellZoneID;
1188 // cellZoneID.setSize(mesh.nCells());
1191 // const cellZoneMesh& cellZones = mesh.cellZones();
1193 // forAll(cellZones, zoneI)
1195 // UIndirectList<label>(cellZoneID, cellZones[zoneI]) = zoneI;
1200 OPstream toDomain(Pstream::blocking, domain);
1205 << mesh.faceNeighbour()
1206 << mesh.boundaryMesh()
1219 // Receive mesh. Opposite of sendMesh
1220 Foam::autoPtr<Foam::fvMesh> Foam::fvMeshDistribute::receiveMesh
1223 const wordList& pointZoneNames,
1224 const wordList& faceZoneNames,
1225 const wordList& cellZoneNames,
1226 const Time& runTime,
1227 labelList& domainSourceFace,
1228 labelList& domainSourceProc,
1229 labelList& domainSourceNewProc
1232 IPstream fromNbr(Pstream::blocking, domain);
1234 pointField domainPoints(fromNbr);
1235 faceList domainFaces(fromNbr);
1236 labelList domainAllOwner(fromNbr);
1237 labelList domainAllNeighbour(fromNbr);
1238 PtrList<entry> patchEntries(fromNbr);
1240 labelListList zonePoints(fromNbr);
1241 labelListList zoneFaces(fromNbr);
1242 boolListList zoneFaceFlip(fromNbr);
1243 labelListList zoneCells(fromNbr);
1248 >> domainSourceNewProc;
1251 autoPtr<fvMesh> domainMeshPtr
1257 fvMesh::defaultRegion,
1262 xferMove(domainPoints),
1263 xferMove(domainFaces),
1264 xferMove(domainAllOwner),
1265 xferMove(domainAllNeighbour),
1266 false // no parallel comms
1269 fvMesh& domainMesh = domainMeshPtr();
1271 List<polyPatch*> patches(patchEntries.size());
1273 forAll(patchEntries, patchI)
1275 patches[patchI] = polyPatch::New
1277 patchEntries[patchI].keyword(),
1278 patchEntries[patchI].dict(),
1280 domainMesh.boundaryMesh()
1283 // Add patches; no parallel comms
1284 domainMesh.addFvPatches(patches, false);
1287 List<pointZone*> pZonePtrs(pointZoneNames.size());
1288 forAll(pZonePtrs, i)
1290 pZonePtrs[i] = new pointZone
1295 domainMesh.pointZones()
1299 List<faceZone*> fZonePtrs(faceZoneNames.size());
1300 forAll(fZonePtrs, i)
1302 fZonePtrs[i] = new faceZone
1308 domainMesh.faceZones()
1312 List<cellZone*> cZonePtrs(cellZoneNames.size());
1313 forAll(cZonePtrs, i)
1315 cZonePtrs[i] = new cellZone
1320 domainMesh.cellZones()
1323 domainMesh.addZones(pZonePtrs, fZonePtrs, cZonePtrs);
1325 return domainMeshPtr;
1329 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1331 // Construct from components
1332 Foam::fvMeshDistribute::fvMeshDistribute(fvMesh& mesh, const scalar mergeTol)
1339 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1341 Foam::labelList Foam::fvMeshDistribute::countCells
1343 const labelList& distribution
1346 labelList nCells(Pstream::nProcs(), 0);
1347 forAll(distribution, cellI)
1349 label newProc = distribution[cellI];
1351 if (newProc < 0 || newProc >= Pstream::nProcs())
1353 FatalErrorIn("fvMeshDistribute::distribute(const labelList&)")
1354 << "Distribution should be in range 0.." << Pstream::nProcs()-1
1356 << "At index " << cellI << " distribution:" << newProc
1357 << abort(FatalError);
1365 Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
1367 const labelList& distribution
1370 // Some checks on distribution
1371 if (distribution.size() != mesh_.nCells())
1373 FatalErrorIn("fvMeshDistribute::distribute(const labelList&)")
1374 << "Size of distribution:"
1375 << distribution.size() << " mesh nCells:" << mesh_.nCells()
1376 << abort(FatalError);
1380 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
1382 // Check all processors have same non-proc patches in same order.
1383 if (patches.checkParallelSync(true))
1385 FatalErrorIn("fvMeshDistribute::distribute(const labelList&)")
1386 << "This application requires all non-processor patches"
1387 << " to be present in the same order on all patches" << nl
1388 << "followed by the processor patches (which of course are unique)."
1390 << "Local patches:" << mesh_.boundaryMesh().names()
1391 << abort(FatalError);
1394 // Save some data for mapping later on
1395 const label nOldPoints(mesh_.nPoints());
1396 const label nOldFaces(mesh_.nFaces());
1397 const label nOldCells(mesh_.nCells());
1398 labelList oldPatchStarts(patches.size());
1399 labelList oldPatchNMeshPoints(patches.size());
1400 forAll(patches, patchI)
1402 oldPatchStarts[patchI] = patches[patchI].start();
1403 oldPatchNMeshPoints[patchI] = patches[patchI].nPoints();
1408 // Short circuit trivial case.
1409 if (!Pstream::parRun())
1411 // Collect all maps and return
1412 return autoPtr<mapDistributePolyMesh>
1414 new mapDistributePolyMesh
1422 oldPatchNMeshPoints,
1424 labelListList(1, identity(mesh_.nPoints())),//subPointMap
1425 labelListList(1, identity(mesh_.nFaces())), //subFaceMap
1426 labelListList(1, identity(mesh_.nCells())), //subCellMap
1427 labelListList(1, identity(patches.size())), //subPatchMap
1429 labelListList(1, identity(mesh_.nPoints())),//constructPointMap
1430 labelListList(1, identity(mesh_.nFaces())), //constructFaceMap
1431 labelListList(1, identity(mesh_.nCells())), //constructCellMap
1432 labelListList(1, identity(patches.size())) //constructPatchMap
1438 // Collect any zone names
1439 const wordList pointZoneNames(mergeWordList(mesh_.pointZones().names()));
1440 const wordList faceZoneNames(mergeWordList(mesh_.faceZones().names()));
1441 const wordList cellZoneNames(mergeWordList(mesh_.cellZones().names()));
1444 // Local environment of all boundary faces
1445 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1447 // A face is uniquely defined by
1451 // To glue the parts of meshes which can get sent from anywhere we
1452 // need to know on boundary faces what the above tuple on both sides is.
1453 // So we need to maintain:
1455 // - original processor id (= trivial)
1456 // For coupled boundaries (where the faces are 'duplicate') we take the
1457 // lowest numbered processor as the data to store.
1459 // Additionally to create the procboundaries we need to know where the owner
1460 // cell on the other side now is: newNeighbourProc.
1463 // physical boundary:
1465 // sourceNewProc = -1
1466 // sourceFace = patchID
1467 // coupled boundary:
1468 // sourceProc = proc
1469 // sourceNewProc = distribution[cell on proc]
1470 // sourceFace = face
1471 labelList sourceFace;
1472 labelList sourceProc;
1473 labelList sourceNewProc;
1474 getNeighbourData(distribution, sourceFace, sourceProc, sourceNewProc);
1477 // Remove meshPhi. Since this would otherwise dissappear anyway
1478 // during topo changes and we have to guarantee that all the fields
1481 mesh_.resetMotion();
1483 const wordList volScalars(mesh_.names(volScalarField::typeName));
1484 checkEqualWordList(volScalars);
1485 const wordList volVectors(mesh_.names(volVectorField::typeName));
1486 checkEqualWordList(volVectors);
1487 const wordList volSphereTensors
1489 mesh_.names(volSphericalTensorField::typeName)
1491 checkEqualWordList(volSphereTensors);
1492 const wordList volSymmTensors(mesh_.names(volSymmTensorField::typeName));
1493 checkEqualWordList(volSymmTensors);
1494 const wordList volTensors(mesh_.names(volTensorField::typeName));
1495 checkEqualWordList(volTensors);
1497 const wordList surfScalars(mesh_.names(surfaceScalarField::typeName));
1498 checkEqualWordList(surfScalars);
1499 const wordList surfVectors(mesh_.names(surfaceVectorField::typeName));
1500 checkEqualWordList(surfVectors);
1501 const wordList surfSphereTensors
1503 mesh_.names(surfaceSphericalTensorField::typeName)
1505 checkEqualWordList(surfSphereTensors);
1506 const wordList surfSymmTensors
1508 mesh_.names(surfaceSymmTensorField::typeName)
1510 checkEqualWordList(surfSymmTensors);
1511 const wordList surfTensors(mesh_.names(surfaceTensorField::typeName));
1512 checkEqualWordList(surfTensors);
1515 // Find patch to temporarily put exposed and processor faces into.
1516 label oldInternalPatchI = findNonEmptyPatch();
1520 // Delete processor patches, starting from the back. Move all faces into
1521 // oldInternalPatchI.
1522 labelList repatchFaceMap;
1524 autoPtr<mapPolyMesh> repatchMap = deleteProcPatches(oldInternalPatchI);
1526 // Store face map (only face ordering that changed)
1527 repatchFaceMap = repatchMap().faceMap();
1529 // Reorder all boundary face data (sourceProc, sourceFace etc.)
1534 repatchMap().reverseFaceMap(),
1535 mesh_.nFaces() - mesh_.nInternalFaces(),
1536 mesh_.nInternalFaces()
1538 - mesh_.nInternalFaces()
1541 inplaceReorder(bFaceMap, sourceFace);
1542 inplaceReorder(bFaceMap, sourceProc);
1543 inplaceReorder(bFaceMap, sourceNewProc);
1551 Pout<< nl << "MESH WITH PROC PATCHES DELETED:" << endl;
1552 printMeshInfo(mesh_);
1553 printFieldInfo<volScalarField>(mesh_);
1554 printFieldInfo<volVectorField>(mesh_);
1555 printFieldInfo<volSphericalTensorField>(mesh_);
1556 printFieldInfo<volSymmTensorField>(mesh_);
1557 printFieldInfo<volTensorField>(mesh_);
1558 printFieldInfo<surfaceScalarField>(mesh_);
1559 printFieldInfo<surfaceVectorField>(mesh_);
1560 printFieldInfo<surfaceSphericalTensorField>(mesh_);
1561 printFieldInfo<surfaceSymmTensorField>(mesh_);
1562 printFieldInfo<surfaceTensorField>(mesh_);
1568 // Maps from subsetted mesh (that is sent) back to original maps
1569 labelListList subCellMap(Pstream::nProcs());
1570 labelListList subFaceMap(Pstream::nProcs());
1571 labelListList subPointMap(Pstream::nProcs());
1572 labelListList subPatchMap(Pstream::nProcs());
1573 // Maps from subsetted mesh to reconstructed mesh
1574 labelListList constructCellMap(Pstream::nProcs());
1575 labelListList constructFaceMap(Pstream::nProcs());
1576 labelListList constructPointMap(Pstream::nProcs());
1577 labelListList constructPatchMap(Pstream::nProcs());
1582 // Find out schedule
1583 // ~~~~~~~~~~~~~~~~~
1585 labelListList nSendCells(Pstream::nProcs());
1586 nSendCells[Pstream::myProcNo()] = countCells(distribution);
1587 Pstream::gatherList(nSendCells);
1588 Pstream::scatterList(nSendCells);
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 // Mesh subsetting engine
1615 fvMeshSubset subsetter(mesh_);
1617 // Subset the cells of the current domain.
1618 subsetter.setLargeCellSubset
1622 oldInternalPatchI, // oldInternalFaces patch
1623 false // no parallel sync
1626 subCellMap[recvProc] = subsetter.cellMap();
1627 subFaceMap[recvProc] = renumber
1632 subPointMap[recvProc] = subsetter.pointMap();
1633 subPatchMap[recvProc] = subsetter.patchMap();
1636 // Subset the boundary fields (owner/neighbour/processor)
1637 labelList procSourceFace;
1638 labelList procSourceProc;
1639 labelList procSourceNewProc;
1643 subsetter.subMesh(),
1644 subsetter.faceMap(), // from subMesh to mesh
1645 subsetter.cellMap(), // ,, ,,
1647 distribution, // old mesh distribution
1648 mesh_.faceOwner(), // old owner
1649 mesh_.faceNeighbour(),
1650 mesh_.nInternalFaces(),
1661 // Send to neighbour
1665 subsetter.subMesh(),
1675 sendFields<volScalarField>(recvProc, volScalars, subsetter);
1676 sendFields<volVectorField>(recvProc, volVectors, subsetter);
1677 sendFields<volSphericalTensorField>
1683 sendFields<volSymmTensorField>
1689 sendFields<volTensorField>(recvProc, volTensors, subsetter);
1691 sendFields<surfaceScalarField>(recvProc, surfScalars, subsetter);
1692 sendFields<surfaceVectorField>(recvProc, surfVectors, subsetter);
1693 sendFields<surfaceSphericalTensorField>
1699 sendFields<surfaceSymmTensorField>
1705 sendFields<surfaceTensorField>(recvProc, surfTensors, subsetter);
1711 // Subset the part that stays
1712 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
1715 // Save old mesh maps before changing mesh
1716 const labelList oldFaceOwner(mesh_.faceOwner());
1717 const labelList oldFaceNeighbour(mesh_.faceNeighbour());
1718 const label oldInternalFaces = mesh_.nInternalFaces();
1721 autoPtr<mapPolyMesh> subMap
1725 select(false, distribution, Pstream::myProcNo()),
1730 // Addressing from subsetted mesh
1731 subCellMap[Pstream::myProcNo()] = subMap().cellMap();
1732 subFaceMap[Pstream::myProcNo()] = renumber
1737 subPointMap[Pstream::myProcNo()] = subMap().pointMap();
1738 subPatchMap[Pstream::myProcNo()] = identity(patches.size());
1740 // Initialize all addressing into current mesh
1741 constructCellMap[Pstream::myProcNo()] = identity(mesh_.nCells());
1742 constructFaceMap[Pstream::myProcNo()] = identity(mesh_.nFaces());
1743 constructPointMap[Pstream::myProcNo()] = identity(mesh_.nPoints());
1744 constructPatchMap[Pstream::myProcNo()] = identity(patches.size());
1746 // Subset the mesh data: neighbourCell/neighbourProc
1748 labelList domainSourceFace;
1749 labelList domainSourceProc;
1750 labelList domainSourceNewProc;
1755 subMap().faceMap(), // from new to original mesh
1758 distribution, // distribution before subsetting
1759 oldFaceOwner, // owner before subsetting
1760 oldFaceNeighbour, // neighbour ,,
1761 oldInternalFaces, // nInternalFaces ,,
1772 sourceFace.transfer(domainSourceFace);
1773 sourceProc.transfer(domainSourceProc);
1774 sourceNewProc.transfer(domainSourceNewProc);
1781 Pout<< nl << "STARTING MESH:" << endl;
1782 printMeshInfo(mesh_);
1783 printFieldInfo<volScalarField>(mesh_);
1784 printFieldInfo<volVectorField>(mesh_);
1785 printFieldInfo<volSphericalTensorField>(mesh_);
1786 printFieldInfo<volSymmTensorField>(mesh_);
1787 printFieldInfo<volTensorField>(mesh_);
1788 printFieldInfo<surfaceScalarField>(mesh_);
1789 printFieldInfo<surfaceVectorField>(mesh_);
1790 printFieldInfo<surfaceSphericalTensorField>(mesh_);
1791 printFieldInfo<surfaceSymmTensorField>(mesh_);
1792 printFieldInfo<surfaceTensorField>(mesh_);
1798 // Receive and add what was sent
1799 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1801 forAll(nSendCells, sendProc)
1803 // Did processor sendProc send anything to me?
1806 sendProc != Pstream::myProcNo()
1807 && nSendCells[sendProc][Pstream::myProcNo()] > 0
1813 << "RECEIVING FROM DOMAIN " << sendProc
1814 << " cells to receive:"
1815 << nSendCells[sendProc][Pstream::myProcNo()]
1819 // Receive from sendProc
1820 labelList domainSourceFace;
1821 labelList domainSourceProc;
1822 labelList domainSourceNewProc;
1824 // Opposite of sendMesh
1825 autoPtr<fvMesh> domainMeshPtr = receiveMesh
1832 const_cast<Time&>(mesh_.time()),
1837 fvMesh& domainMesh = domainMeshPtr();
1840 PtrList<volScalarField> vsf;
1841 receiveFields<volScalarField>
1849 PtrList<volVectorField> vvf;
1850 receiveFields<volVectorField>
1857 PtrList<volSphericalTensorField> vsptf;
1858 receiveFields<volSphericalTensorField>
1865 PtrList<volSymmTensorField> vsytf;
1866 receiveFields<volSymmTensorField>
1873 PtrList<volTensorField> vtf;
1874 receiveFields<volTensorField>
1882 PtrList<surfaceScalarField> ssf;
1883 receiveFields<surfaceScalarField>
1890 PtrList<surfaceVectorField> svf;
1891 receiveFields<surfaceVectorField>
1898 PtrList<surfaceSphericalTensorField> ssptf;
1899 receiveFields<surfaceSphericalTensorField>
1906 PtrList<surfaceSymmTensorField> ssytf;
1907 receiveFields<surfaceSymmTensorField>
1914 PtrList<surfaceTensorField> stf;
1915 receiveFields<surfaceTensorField>
1924 constructCellMap[sendProc] = identity(domainMesh.nCells());
1925 constructFaceMap[sendProc] = identity(domainMesh.nFaces());
1926 constructPointMap[sendProc] = identity(domainMesh.nPoints());
1927 constructPatchMap[sendProc] =
1928 identity(domainMesh.boundaryMesh().size());
1934 Pout<< nl << "RECEIVED MESH FROM:" << sendProc << endl;
1935 printMeshInfo(domainMesh);
1936 printFieldInfo<volScalarField>(domainMesh);
1937 printFieldInfo<volVectorField>(domainMesh);
1938 printFieldInfo<volSphericalTensorField>(domainMesh);
1939 printFieldInfo<volSymmTensorField>(domainMesh);
1940 printFieldInfo<volTensorField>(domainMesh);
1941 printFieldInfo<surfaceScalarField>(domainMesh);
1942 printFieldInfo<surfaceVectorField>(domainMesh);
1943 printFieldInfo<surfaceSphericalTensorField>(domainMesh);
1944 printFieldInfo<surfaceSymmTensorField>(domainMesh);
1945 printFieldInfo<surfaceTensorField>(domainMesh);
1949 // Now this mesh we received (from sendProc) needs to be merged
1950 // with the current mesh. On the current mesh we have for all
1951 // boundaryfaces the original face and processor. See if we can
1952 // match these up to the received domainSourceFace and
1953 // domainSourceProc.
1954 labelList masterCoupledFaces;
1955 labelList slaveCoupledFaces;
1972 // Generate additional coupling info (points, edges) from
1974 faceCoupleInfo couples
1980 mergeTol_, // merge tolerance
1981 true, // faces align
1982 true, // couples are ordered already
1987 // Add domainMesh to mesh
1988 // ~~~~~~~~~~~~~~~~~~~~~~
1990 autoPtr<mapAddedPolyMesh> map = fvMeshAdder::add
1995 false // no parallel comms
1998 // Update mesh data: sourceFace,sourceProc for added
2007 domainMesh.nInternalFaces(),
2016 domainMesh.nInternalFaces(),
2025 domainMesh.nInternalFaces(),
2029 // Update all addressing so xxProcAddressing points to correct item
2031 const labelList& oldCellMap = map().oldCellMap();
2032 const labelList& oldFaceMap = map().oldFaceMap();
2033 const labelList& oldPointMap = map().oldPointMap();
2034 const labelList& oldPatchMap = map().oldPatchMap();
2036 forAll(constructPatchMap, procI)
2038 if (procI != sendProc && constructPatchMap[procI].size())
2040 // Processor already in mesh (either myProcNo or received)
2041 inplaceRenumber(oldCellMap, constructCellMap[procI]);
2042 inplaceRenumber(oldFaceMap, constructFaceMap[procI]);
2043 inplaceRenumber(oldPointMap, constructPointMap[procI]);
2044 inplaceRenumber(oldPatchMap, constructPatchMap[procI]);
2049 inplaceRenumber(map().addedCellMap(), constructCellMap[sendProc]);
2050 inplaceRenumber(map().addedFaceMap(), constructFaceMap[sendProc]);
2051 inplaceRenumber(map().addedPointMap(), constructPointMap[sendProc]);
2052 inplaceRenumber(map().addedPatchMap(), constructPatchMap[sendProc]);
2056 Pout<< nl << "MERGED MESH FROM:" << sendProc << endl;
2057 printMeshInfo(mesh_);
2058 printFieldInfo<volScalarField>(mesh_);
2059 printFieldInfo<volVectorField>(mesh_);
2060 printFieldInfo<volSphericalTensorField>(mesh_);
2061 printFieldInfo<volSymmTensorField>(mesh_);
2062 printFieldInfo<volTensorField>(mesh_);
2063 printFieldInfo<surfaceScalarField>(mesh_);
2064 printFieldInfo<surfaceVectorField>(mesh_);
2065 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2066 printFieldInfo<surfaceSymmTensorField>(mesh_);
2067 printFieldInfo<surfaceTensorField>(mesh_);
2077 Pout<< nl << "REDISTRIBUTED MESH:" << endl;
2078 printMeshInfo(mesh_);
2079 printFieldInfo<volScalarField>(mesh_);
2080 printFieldInfo<volVectorField>(mesh_);
2081 printFieldInfo<volSphericalTensorField>(mesh_);
2082 printFieldInfo<volSymmTensorField>(mesh_);
2083 printFieldInfo<volTensorField>(mesh_);
2084 printFieldInfo<surfaceScalarField>(mesh_);
2085 printFieldInfo<surfaceVectorField>(mesh_);
2086 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2087 printFieldInfo<surfaceSymmTensorField>(mesh_);
2088 printFieldInfo<surfaceTensorField>(mesh_);
2094 // Add processorPatches
2095 // ~~~~~~~~~~~~~~~~~~~~
2097 // Per neighbour processor the patchID to it (or -1).
2098 labelList procPatchID;
2100 // Add processor patches.
2101 addProcPatches(sourceNewProc, procPatchID);
2103 // Put faces into correct patch. Note that we now have proper
2104 // processorPolyPatches again so repatching will take care of coupled face
2107 // Get boundary faces to be repatched. Is -1 or new patchID
2108 labelList newPatchID
2110 getProcBoundaryPatch
2117 // Change patches. Since this might change ordering of coupled faces
2118 // we also need to adapt our constructMaps.
2119 repatch(newPatchID, constructFaceMap);
2121 // See if any geometrically shared points need to be merged. Note: does
2123 mergeSharedPoints(constructPointMap);
2125 // Bit of hack: processorFvPatchField does not get reset since created
2126 // from nothing so explicitly reset.
2127 initPatchFields<volScalarField>
2129 processorFvPatchField<scalar>::typeName,
2130 pTraits<scalar>::zero
2132 initPatchFields<volVectorField>
2134 processorFvPatchField<vector>::typeName,
2135 pTraits<vector>::zero
2137 initPatchFields<volSphericalTensorField>
2139 processorFvPatchField<sphericalTensor>::typeName,
2140 pTraits<sphericalTensor>::zero
2142 initPatchFields<volSymmTensorField>
2144 processorFvPatchField<symmTensor>::typeName,
2145 pTraits<symmTensor>::zero
2147 initPatchFields<volTensorField>
2149 processorFvPatchField<tensor>::typeName,
2150 pTraits<tensor>::zero
2152 initPatchFields<surfaceScalarField>
2154 processorFvPatchField<scalar>::typeName,
2155 pTraits<scalar>::zero
2157 initPatchFields<surfaceVectorField>
2159 processorFvPatchField<vector>::typeName,
2160 pTraits<vector>::zero
2162 initPatchFields<surfaceSphericalTensorField>
2164 processorFvPatchField<sphericalTensor>::typeName,
2165 pTraits<sphericalTensor>::zero
2167 initPatchFields<surfaceSymmTensorField>
2169 processorFvPatchField<symmTensor>::typeName,
2170 pTraits<symmTensor>::zero
2172 initPatchFields<surfaceTensorField>
2174 processorFvPatchField<tensor>::typeName,
2175 pTraits<tensor>::zero
2179 mesh_.setInstance(mesh_.time().timeName());
2185 Pout<< nl << "FINAL MESH:" << endl;
2186 printMeshInfo(mesh_);
2187 printFieldInfo<volScalarField>(mesh_);
2188 printFieldInfo<volVectorField>(mesh_);
2189 printFieldInfo<volSphericalTensorField>(mesh_);
2190 printFieldInfo<volSymmTensorField>(mesh_);
2191 printFieldInfo<volTensorField>(mesh_);
2192 printFieldInfo<surfaceScalarField>(mesh_);
2193 printFieldInfo<surfaceVectorField>(mesh_);
2194 printFieldInfo<surfaceSphericalTensorField>(mesh_);
2195 printFieldInfo<surfaceSymmTensorField>(mesh_);
2196 printFieldInfo<surfaceTensorField>(mesh_);
2200 // Collect all maps and return
2201 return autoPtr<mapDistributePolyMesh>
2203 new mapDistributePolyMesh
2211 oldPatchNMeshPoints,
2222 true // reuse storage
2228 // ************************************************************************* //