diff --git a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.C b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.C index a413e8037e..81bf9400b3 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.C +++ b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.C @@ -561,6 +561,17 @@ Foam::labelList Foam::polyBoundaryMesh::patchSizes() const } +Foam::List Foam::polyBoundaryMesh::patchRanges() const +{ + return + PtrListOps::get + ( + *this, + [](const polyPatch& p) { return p.range(); } + ); +} + + Foam::label Foam::polyBoundaryMesh::start() const { return mesh_.nInternalFaces(); diff --git a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H index 8f7e9c86b8..c3d0b0f4b5 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H +++ b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2018-2020 OpenCFD Ltd. + Copyright (C) 2018-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -174,6 +174,9 @@ public: //- Return a list of patch sizes labelList patchSizes() const; + //- Return a list of patch ranges + List patchRanges() const; + //- The start label of the boundary faces in the polyMesh face list // Same as mesh.nInternalFaces() label start() const; diff --git a/src/dynamicMesh/fvMeshAdder/fvMeshAdder.C b/src/dynamicMesh/fvMeshAdder/fvMeshAdder.C index cdb2f25b55..db8400b0e4 100644 --- a/src/dynamicMesh/fvMeshAdder/fvMeshAdder.C +++ b/src/dynamicMesh/fvMeshAdder/fvMeshAdder.C @@ -6,6 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation + Copyright (C) 2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -28,6 +29,7 @@ License #include "fvMesh.H" #include "fvMeshAdder.H" #include "faceCoupleInfo.H" +#include "polyTopoChange.H" /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */ @@ -50,8 +52,8 @@ Foam::labelList Foam::fvMeshAdder::calcPatchMap { labelList newToOld(newPatch.size(), unmappedValue); - label newStart = newPatch.start(); - label newSize = newPatch.size(); + const label newStart = newPatch.start(); + const label newSize = newPatch.size(); for (label i = 0; i < oldSize; i++) { @@ -129,4 +131,335 @@ Foam::autoPtr Foam::fvMeshAdder::add } +Foam::autoPtr Foam::fvMeshAdder::add +( + const label myProci, // index of mesh to modify + UPtrList& fvMeshes, + const labelList& oldFaceOwner, // face owner for myProci mesh + + // Coupling info + const labelListList& localBoundaryFace, + const labelListList& remoteFaceProc, + const labelListList& remoteBoundaryFace, + + labelListList& constructPatchMap, + labelListList& constructCellMap, + labelListList& constructFaceMap, + labelListList& constructPointMap +) +{ + // Do in-place addition. Modifies fvMeshes[myProci] + + UPtrList meshes(fvMeshes.size()); + forAll(fvMeshes, proci) + { + if (fvMeshes.set(proci)) + { + meshes.set(proci, &fvMeshes[proci]); + } + } + + + // All matched faces assumed to have vertex0 matched + labelListList remoteFaceStart(meshes.size()); + forAll(localBoundaryFace, proci) + { + const labelList& procFaces = localBoundaryFace[proci]; + remoteFaceStart[proci].setSize(procFaces.size(), 0); + } + + // Assume all meshes have same global patches + labelListList patchMap(meshes.size()); + labelListList pointZoneMap(meshes.size()); + labelListList faceZoneMap(meshes.size()); + labelListList cellZoneMap(meshes.size()); + forAll(meshes, proci) + { + if (meshes.set(proci)) + { + const polyMesh& mesh = meshes[proci]; + patchMap[proci] = identity(mesh.boundaryMesh().nNonProcessor()); + pointZoneMap[proci] = identity(mesh.pointZones().size()); + faceZoneMap[proci] = identity(mesh.faceZones().size()); + cellZoneMap[proci] = identity(mesh.cellZones().size()); + } + } + + + // Swap myProci to 0th element + if (myProci != 0) + { + polyMesh* pm0 = meshes.get(0); + polyMesh* pmi = meshes.get(myProci); + meshes.set(0, pmi); + meshes.set(myProci, pm0); + + fvMesh* fvm0 = fvMeshes.get(0); + fvMesh* fvmi = fvMeshes.get(myProci); + fvMeshes.set(0, fvmi); + fvMeshes.set(myProci, fvm0); + + //Pout<< "swapped from 0 to " << myProci << endl; + //forAll(meshes, meshi) + //{ + // Pout<< "meshi:" << meshi << endl; + // if (meshes.set(meshi)) + // { + // Pout<< " nCells:" << meshes[meshi].nCells() << endl; + // } + //} + + + // Swap (and renumber) patch face information + labelListList& lbf = const_cast(localBoundaryFace); + std::swap(lbf[0], lbf[myProci]); + + labelListList& rfp = const_cast(remoteFaceProc); + std::swap(rfp[0], rfp[myProci]); + forAll(rfp, proci) + { + for (label& proc : rfp[proci]) + { + if (proc == 0) proc = myProci; + else if (proc == myProci) proc = 0; + } + } + labelListList& rbf = const_cast(remoteBoundaryFace); + std::swap(rbf[0], rbf[myProci]); + + labelListList& rfs = const_cast(remoteFaceStart); + std::swap(rfs[0], rfs[myProci]); + + // Swap optional renumbering maps + std::swap(patchMap[0], patchMap[myProci]); + std::swap(pointZoneMap[0], pointZoneMap[myProci]); + std::swap(faceZoneMap[0], faceZoneMap[myProci]); + std::swap(cellZoneMap[0], cellZoneMap[myProci]); + } + + polyTopoChange meshMod(meshes[0].boundaryMesh().size(), true); + // Collect statistics for sizing + label nCells = 0; + label nFaces = 0; + label nPoints = 0; + forAll(meshes, proci) + { + if (meshes.set(proci)) + { + const polyMesh& mesh = meshes[proci]; + nCells += mesh.nCells(); + nFaces += mesh.nFaces(); + nPoints += mesh.nPoints(); + } + } + meshMod.setCapacity(nPoints, nFaces, nCells); + + // Add all cells in meshes' order + polyMeshAdder::add + ( + meshes, + patchMap, + + // Information on (one-to-one) boundary faces to stitch + localBoundaryFace, + remoteFaceProc, + remoteBoundaryFace, + remoteFaceStart, + + pointZoneMap, + faceZoneMap, + cellZoneMap, + + meshMod, + + constructCellMap, + constructFaceMap, + constructPointMap + ); + + // Replace mesh + autoPtr mapPtr + ( + meshMod.changeMesh + ( + fvMeshes[0], // note: still swapped to position 0 + false // no inflation + ) + ); + + // Update fields. Note that this tries to interpolate from the mesh + // before adding all the remote meshes so is quite wrong. + //fvMeshes[0.updateMesh(mapPtr()); + // Update polyMesh but not fvMesh to avoid mapping all the fields + fvMeshes[0].polyMesh::updateMesh(mapPtr()); + + // Now reverseFaceMap contains from order in which face was added + // to mesh face (after e.g. upper-triangular ordering) + + // Renumber output of any mesh ordering done by changeMesh + for (labelList& cellMap : constructCellMap) + { + inplaceRenumber(mapPtr().reverseCellMap(), cellMap); + } + for (labelList& faceMap : constructFaceMap) + { + inplaceRenumber(mapPtr().reverseFaceMap(), faceMap); + } + for (labelList& pointMap : constructPointMap) + { + inplaceRenumber(mapPtr().reversePointMap(), pointMap); + } + + // constructPatchMap is patchMap with -1 for the removed + // patches + forAll(meshes, meshi) + { + if (meshes.set(meshi)) + { + constructPatchMap[meshi] = patchMap[meshi]; + } + } + + // Map all fields + fvMeshAdder::MapVolFields + ( + fvMeshes, + mapPtr().oldPatchStarts(), + mapPtr().oldPatchSizes(), + patchMap, + constructCellMap, + constructFaceMap, + constructPointMap + ); + fvMeshAdder::MapVolFields + ( + fvMeshes, + mapPtr().oldPatchStarts(), + mapPtr().oldPatchSizes(), + patchMap, + constructCellMap, + constructFaceMap, + constructPointMap + ); + fvMeshAdder::MapVolFields + ( + fvMeshes, + mapPtr().oldPatchStarts(), + mapPtr().oldPatchSizes(), + patchMap, + constructCellMap, + constructFaceMap, + constructPointMap + ); + fvMeshAdder::MapVolFields + ( + fvMeshes, + mapPtr().oldPatchStarts(), + mapPtr().oldPatchSizes(), + patchMap, + constructCellMap, + constructFaceMap, + constructPointMap + ); + fvMeshAdder::MapVolFields + ( + fvMeshes, + mapPtr().oldPatchStarts(), + mapPtr().oldPatchSizes(), + patchMap, + constructCellMap, + constructFaceMap, + constructPointMap + ); + fvMeshAdder::MapSurfaceFields + ( + fvMeshes, + oldFaceOwner, + mapPtr().oldPatchStarts(), + mapPtr().oldPatchSizes(), + patchMap, + constructCellMap, + constructFaceMap, + constructPointMap + ); + fvMeshAdder::MapSurfaceFields + ( + fvMeshes, + oldFaceOwner, + mapPtr().oldPatchStarts(), + mapPtr().oldPatchSizes(), + patchMap, + constructCellMap, + constructFaceMap, + constructPointMap + ); + fvMeshAdder::MapSurfaceFields + ( + fvMeshes, + oldFaceOwner, + mapPtr().oldPatchStarts(), + mapPtr().oldPatchSizes(), + patchMap, + constructCellMap, + constructFaceMap, + constructPointMap + ); + fvMeshAdder::MapSurfaceFields + ( + fvMeshes, + oldFaceOwner, + mapPtr().oldPatchStarts(), + mapPtr().oldPatchSizes(), + patchMap, + constructCellMap, + constructFaceMap, + constructPointMap + ); + fvMeshAdder::MapSurfaceFields + ( + fvMeshes, + oldFaceOwner, + mapPtr().oldPatchStarts(), + mapPtr().oldPatchSizes(), + patchMap, + constructCellMap, + constructFaceMap, + constructPointMap + ); + + + // Swap returned data back to processor order + if (myProci != 0) + { + fvMesh* fvm0 = fvMeshes.get(0); + fvMesh* fvmi = fvMeshes.get(myProci); + fvMeshes.set(0, fvmi); + fvMeshes.set(myProci, fvm0); + + // Swap (and renumber) patch face information + labelListList& lbf = const_cast(localBoundaryFace); + std::swap(lbf[0], lbf[myProci]); + labelListList& rfp = const_cast(remoteFaceProc); + std::swap(rfp[0], rfp[myProci]); + forAll(rfp, proci) + { + for (label& proc : rfp[proci]) + { + if (proc == 0) proc = myProci; + else if (proc == myProci) proc = 0; + } + } + labelListList& rbf = const_cast(remoteBoundaryFace); + std::swap(rbf[0], rbf[myProci]); + + std::swap(constructPatchMap[0], constructPatchMap[myProci]); + std::swap(constructCellMap[0], constructCellMap[myProci]); + std::swap(constructFaceMap[0], constructFaceMap[myProci]); + std::swap(constructPointMap[0], constructPointMap[myProci]); + } + + return mapPtr; +} + + // ************************************************************************* // diff --git a/src/dynamicMesh/fvMeshAdder/fvMeshAdder.H b/src/dynamicMesh/fvMeshAdder/fvMeshAdder.H index 0c10219b89..30c459466f 100644 --- a/src/dynamicMesh/fvMeshAdder/fvMeshAdder.H +++ b/src/dynamicMesh/fvMeshAdder/fvMeshAdder.H @@ -6,6 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation + Copyright (C) 2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -164,6 +165,109 @@ public: const fvMesh& mesh, const fvMesh& meshToAdd ); + + + // Multi-mesh merging. Expects same patches (apart from processor + // patches). Adds to element 0 of flds, meshes + + //- In-place add to fvMeshes[myProci]. Stitch boundary faces. + static autoPtr add + ( + const label myProci, // index of mesh to modify (== mesh_) + UPtrList& fvMeshes, + const labelList& oldFaceOwner, // face owner for myProci mesh + + // Coupling info + const labelListList& localBoundaryFace, + const labelListList& remoteFaceProc, + const labelListList& remoteBoundaryFace, + + labelListList& constructPatchMap, + labelListList& constructCellMap, + labelListList& constructFaceMap, + labelListList& constructPointMap + ); + + //- Update single dimensionedField. + template + static void MapDimField + ( + UPtrList>& flds, + const labelListList& cellProcAddressing, + const bool fullyMapped + ); + + //- Update single volField. + template + static void MapVolField + ( + UPtrList>& flds, + const labelList& oldPatchStarts0, + const labelList& oldPatchSizes0, + const labelListList& patchProcAddressing, + const labelListList& cellProcAddressing, + const labelListList& faceProcAddressing, + const bool fullyMapped + ); + + //- Update single surfaceField. + template + static void MapSurfaceField + ( + UPtrList>&, + const labelList& oldFaceOwner0, + const labelList& oldPatchStarts0, + const labelList& oldPatchSizes0, + const labelListList& patchProcAddressing, + const labelListList& cellProcAddressing, + const labelListList& faceProcAddressing, + const bool fullyMapped + ); + + + //- Map all dimensionedField of Type. + // Optionally override mapping detection + // of unmapped values (e.g. used in fvMeshDistribute since it + // fixes up mapping itself) + template + static void MapDimFields + ( + const UPtrList& meshes, + const labelListList& cellProcAddressing, + const bool fullyMapped = false + ); + + //- Map all volFields of Type. + // Optionally override mapping detection + // of unmapped values (e.g. used in fvMeshDistribute since it + // fixes up mapping itself) + template + static void MapVolFields + ( + const UPtrList& meshes, + const labelList& oldPatchStarts0, + const labelList& oldPatchSizes0, + const labelListList& patchProcAddressing, + const labelListList& cellProcAddressing, + const labelListList& faceProcAddressing, + const labelListList& pointProcAddressing, + const bool fullyMapped = false + ); + + //- Map all surfaceFields of Type + template + static void MapSurfaceFields + ( + const UPtrList& meshes, + const labelList& oldFaceOwner0, + const labelList& oldPatchStarts0, + const labelList& oldPatchSizes0, + const labelListList& patchProcAddressing, + const labelListList& cellProcAddressing, + const labelListList& faceProcAddressing, + const labelListList& pointProcAddressing, + const bool fullyMapped = false + ); }; diff --git a/src/dynamicMesh/fvMeshAdder/fvMeshAdderTemplates.C b/src/dynamicMesh/fvMeshAdder/fvMeshAdderTemplates.C index f7ad465343..45db30ae6d 100644 --- a/src/dynamicMesh/fvMeshAdder/fvMeshAdderTemplates.C +++ b/src/dynamicMesh/fvMeshAdder/fvMeshAdderTemplates.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2015-2019 OpenCFD Ltd. + Copyright (C) 2015-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -50,7 +50,7 @@ void Foam::fvMeshAdder::MapVolField { // Store old internal field - Field oldInternalField(fld.primitiveField()); + const Field oldInternalField(fld.primitiveField()); // Modify internal field Field& intFld = fld.primitiveFieldRef(); @@ -127,7 +127,7 @@ void Foam::fvMeshAdder::MapVolField forAll(oldPatchMap, patchi) { - label newPatchi = oldPatchMap[patchi]; + const label newPatchi = oldPatchMap[patchi]; if (newPatchi != -1) { @@ -185,7 +185,7 @@ void Foam::fvMeshAdder::MapVolField // Add addedMesh patches forAll(addedPatchMap, patchi) { - label newPatchi = addedPatchMap[patchi]; + const label newPatchi = addedPatchMap[patchi]; if (newPatchi != -1) { @@ -344,7 +344,7 @@ void Foam::fvMeshAdder::MapSurfaceField // Store old internal field { - Field oldField(fld); + const Field oldField(fld); // Modify internal field Field& intFld = fld.primitiveFieldRef(); @@ -390,7 +390,7 @@ void Foam::fvMeshAdder::MapSurfaceField forAll(oldPatchMap, patchi) { - label newPatchi = oldPatchMap[patchi]; + const label newPatchi = oldPatchMap[patchi]; if (newPatchi != -1) { @@ -439,7 +439,7 @@ void Foam::fvMeshAdder::MapSurfaceField forAll(oldPatchMap, patchi) { - label newPatchi = oldPatchMap[patchi]; + const label newPatchi = oldPatchMap[patchi]; if (newPatchi != -1) { @@ -497,7 +497,7 @@ void Foam::fvMeshAdder::MapSurfaceField // Add addedMesh patches forAll(addedPatchMap, patchi) { - label newPatchi = addedPatchMap[patchi]; + const label newPatchi = addedPatchMap[patchi]; if (newPatchi != -1) { @@ -648,7 +648,7 @@ void Foam::fvMeshAdder::MapDimField const fvMesh& mesh = fld.mesh(); // Store old field - Field oldField(fld); + const Field oldField(fld); fld.setSize(mesh.nCells()); @@ -704,4 +704,588 @@ void Foam::fvMeshAdder::MapDimFields } +//- Multi-mesh mapping + +template +void Foam::fvMeshAdder::MapDimField +( + UPtrList>& flds, + const labelListList& cellProcAddressing, + const bool fullyMapped +) +{ + // Add fields to fields[0] after adding the meshes to meshes[0]. + // Mesh[0] is the sum of all meshes. Fields are not yet mapped. + + if (flds.size() == 0 || !flds.set(0)) + { + FatalErrorInFunction << "Not valid field at element 0" + << " in field list of size " << flds.size() << exit(FatalError); + } + + + // Internal field + // ~~~~~~~~~~~~~~ + + { + // Store old internal field + const Field oldInternalField(flds[0].primitiveField()); + + // Modify internal field + Field& intFld = flds[0].primitiveFieldRef(); + + // Set to new mesh size + intFld.setSize(flds[0].mesh().nCells()); + // Add fld0 + intFld.rmap(oldInternalField, cellProcAddressing[0]); + + for (label meshi = 1; meshi < flds.size(); meshi++) + { + if (flds.set(meshi)) + { + const Field& addFld = flds[meshi].primitiveFieldRef(); + intFld.rmap(addFld, cellProcAddressing[meshi]); + } + } + } +} + + +template +void Foam::fvMeshAdder::MapVolField +( + UPtrList>& flds, + const labelList& oldPatchStarts0, + const labelList& oldPatchSizes0, + const labelListList& patchProcAddressing, + const labelListList& cellProcAddressing, + const labelListList& faceProcAddressing, + const bool fullyMapped +) +{ + // Add fields to fields[0] after adding the meshes to meshes[0]. + // Mesh[0] is the sum of all meshes. Fields are not yet mapped. + + if (flds.size() == 0 || !flds.set(0)) + { + FatalErrorInFunction << "Not valid field at element 0" + << " in field list of size " << flds.size() << exit(FatalError); + } + + + // Internal field + // ~~~~~~~~~~~~~~ + + { + // Store old internal field + const Field oldInternalField(flds[0].primitiveField()); + + // Modify internal field + Field& intFld = flds[0].primitiveFieldRef(); + + // Set to new mesh size + intFld.setSize(flds[0].mesh().nCells()); + // Add fld0 + intFld.rmap(oldInternalField, cellProcAddressing[0]); + + for (label meshi = 1; meshi < flds.size(); meshi++) + { + if (flds.set(meshi)) + { + const Field& addFld = flds[meshi].primitiveFieldRef(); + intFld.rmap(addFld, cellProcAddressing[meshi]); + } + } + } + + + // Patch fields from old mesh + // ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + auto& bfld0 = flds[0].boundaryFieldRef(); + //Pout<< " Adding patchfields for field " << flds[0].name() << endl; + forAll(bfld0, patchi) + { + //Pout<< " patch:" << patchi + // << " patch:" << flds[0].mesh().boundaryMesh()[patchi].name() + // << " size:" << flds[0].mesh().boundaryMesh()[patchi].size() + // << endl; + //Pout<< " patchField:" << bfld0[patchi].size() + // << endl; + + labelList newToOld + ( + calcPatchMap + ( + oldPatchStarts0[patchi], + oldPatchSizes0[patchi], + faceProcAddressing[0], + bfld0[patchi].patch().patch(), + -1 // unmapped value + ) + ); + + directFvPatchFieldMapper patchMapper(newToOld); + + // Override mapping (for use in e.g. fvMeshDistribute where + // it sorts mapping out itself) + if (fullyMapped) + { + patchMapper.hasUnmapped() = false; + } + + bfld0[patchi].autoMap(patchMapper); + } + + for (label meshi = 1; meshi < flds.size(); meshi++) + { + if (flds.set(meshi)) + { + const auto& bfld = flds[meshi].boundaryFieldRef(); + + const labelList& patchMap = patchProcAddressing[meshi]; + + forAll(patchMap, oldPatchi) + { + const auto& fvp = bfld[oldPatchi].patch(); + const label newPatchi = patchMap[oldPatchi]; + + //Pout<< " oldPatch:" << oldPatchi + // << " newPatch:" << newPatchi << endl; + + if (newPatchi >= 0 && newPatchi < bfld0.size()) + { + const auto& fvp0 = bfld0[newPatchi].patch(); + labelList addedToNew(bfld[oldPatchi].size(), -1); + forAll(addedToNew, i) + { + const label newFacei = + faceProcAddressing[meshi][fvp.start()+i]; + const label patchFacei = newFacei-fvp0.start(); + if + ( + patchFacei >= 0 + && patchFacei < fvp0.size() + ) + { + addedToNew[i] = patchFacei; + } + } + + bfld0[newPatchi].rmap(bfld[oldPatchi], addedToNew); + } + else + { + WarningInFunction << "Ignoring old patch " + << bfld[oldPatchi].patch().name() << " on field " + << flds[meshi].name() << endl; //exit(FatalError); + } + } + } + } +} + + +template +void Foam::fvMeshAdder::MapSurfaceField +( + UPtrList>& flds, + const labelList& oldFaceOwner0, + const labelList& oldPatchStarts0, + const labelList& oldPatchSizes0, + const labelListList& patchProcAddressing, + const labelListList& cellProcAddressing, + const labelListList& faceProcAddressing, + const bool fullyMapped +) +{ + // Add fields to fields[0] after adding the meshes to meshes[0]. + // Mesh[0] is the sum of all meshes. Fields are not yet mapped. + + if (flds.size() == 0 || !flds.set(0)) + { + FatalErrorInFunction << "Not valid field at element 0" + << " in field list of size " << flds.size() << exit(FatalError); + } + + const fvMesh& mesh0 = flds[0].mesh(); + + + // Internal field + // ~~~~~~~~~~~~~~ + + { + // Store old internal field + const Field oldInternalField(flds[0].primitiveField()); + + // Modify internal field + Field& intFld = flds[0].primitiveFieldRef(); + + // Set to new mesh size + intFld.setSize(mesh0.nInternalFaces()); + + // Map + forAll(flds, meshi) + { + if (flds.set(meshi)) + { + const labelList& faceMap = faceProcAddressing[meshi]; + const auto& fld = flds[meshi]; + + // Map internal field + if (meshi == 0) + { + intFld.rmap(oldInternalField, faceMap); + } + else + { + intFld.rmap(fld.primitiveField(), faceMap); + } + + // Map faces that were boundary faces but are not anymore. + // There will be two meshes that provide the same face. Use + // owner one. + const auto& bfld = flds[meshi].boundaryField(); + + forAll(bfld, oldPatchi) + { + const fvsPatchField& pf = bfld[oldPatchi]; + //Pout<< "patch:" << pf.patch().name() << endl; + forAll(pf, patchFacei) + { + // Get new face, mapped face owner + label newFacei; + label newOwn; + if (meshi == 0) + { + // Do not access mesh information since in-place + // modified + const label oldFacei = + oldPatchStarts0[oldPatchi]+patchFacei; + newFacei = faceProcAddressing[meshi][oldFacei]; + const label oldOwn = oldFaceOwner0[oldFacei]; + newOwn = cellProcAddressing[meshi][oldOwn]; + + //Pout<< "MESH0: pfi:" << patchFacei + // << " old face:" << oldFacei + // << " new face:" << newFacei + // << " at:" << mesh0.faceCentres()[newFacei] + // << " oldOwn:" << oldOwn + // << " newOwn:" << newOwn << endl; + } + else + { + const label oldFacei = + pf.patch().start()+patchFacei; + newFacei = faceProcAddressing[meshi][oldFacei]; + const label oldOwn = + fld.mesh().faceOwner()[oldFacei]; + newOwn = cellProcAddressing[meshi][oldOwn]; + + //Pout<< "MESH:" << meshi << " pfi:" << patchFacei + // << " old face:" << oldFacei + // << " new face:" << newFacei + // << " at:" << mesh0.faceCentres()[newFacei] + // << " oldOwn:" << oldOwn + // << " newOwn:" << newOwn << endl; + } + + if + ( + newFacei >= 0 + && newFacei < mesh0.nInternalFaces() + && (newOwn == mesh0.faceOwner()[newFacei]) + ) + { + intFld[newFacei] = pf[patchFacei]; + } + //else + //{ + // Pout<< " ignoring pfi:" << patchFacei + // << " value:" << pf[patchFacei] + // << " since newFacei:" << newFacei + // << " since newOwn:" << newOwn + // << " own:" << mesh0.faceOwner()[newFacei] + // << endl; + //} + } + } + } + } + } + + + // Patch fields from old mesh + // ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + auto& bfld0 = flds[0].boundaryFieldRef(); + forAll(bfld0, patchi) + { + labelList newToOld + ( + calcPatchMap + ( + oldPatchStarts0[patchi], + oldPatchSizes0[patchi], + faceProcAddressing[0], + bfld0[patchi].patch().patch(), + -1 // unmapped value + ) + ); + + directFvPatchFieldMapper patchMapper(newToOld); + + // Override mapping (for use in e.g. fvMeshDistribute where + // it sorts mapping out itself) + if (fullyMapped) + { + patchMapper.hasUnmapped() = false; + } + + bfld0[patchi].autoMap(patchMapper); + } + + for (label meshi = 1; meshi < flds.size(); meshi++) + { + if (flds.set(meshi)) + { + const auto& bfld = flds[meshi].boundaryFieldRef(); + + const labelList& patchMap = patchProcAddressing[meshi]; + + forAll(patchMap, oldPatchi) + { + const auto& fvp = bfld[oldPatchi].patch(); + const label newPatchi = patchMap[oldPatchi]; + if (newPatchi >= 0 && newPatchi < bfld0.size()) + { + const auto& fvp0 = bfld0[newPatchi].patch(); + labelList addedToNew(bfld[oldPatchi].size(), -1); + forAll(addedToNew, i) + { + const label newFacei = + faceProcAddressing[meshi][fvp.start()+i]; + const label patchFacei = newFacei-fvp0.start(); + if + ( + patchFacei >= 0 + && patchFacei < fvp0.size() + ) + { + addedToNew[i] = patchFacei; + } + } + + bfld0[newPatchi].rmap(bfld[oldPatchi], addedToNew); + } + else + { + WarningInFunction << "Ignoring old patch " + << bfld[oldPatchi].patch().name() << " on field " + << flds[meshi].name() << endl; //exit(FatalError); + } + } + } + } +} + + +template +void Foam::fvMeshAdder::MapVolFields +( + const UPtrList& meshes, + const labelList& oldPatchStarts0, + const labelList& oldPatchSizes0, + const labelListList& patchProcAddressing, + const labelListList& cellProcAddressing, + const labelListList& faceProcAddressing, + const labelListList& pointProcAddressing, + const bool fullyMapped +) +{ + typedef GeometricField fldType; + + if (meshes.size() == 0 || !meshes.set(0)) + { + FatalErrorInFunction << "Not valid field at element 0" + << " in mesh list of size " << meshes.size() << exit(FatalError); + } + const fvMesh& mesh0 = meshes[0]; + + HashTable fields + ( + mesh0.objectRegistry::lookupClass() + ); + + + // It is necessary to enforce that all old-time fields are stored + // before the mapping is performed. Otherwise, if the + // old-time-level field is mapped before the field itself, sizes + // will not match. + + for (const auto& fld : fields) + { + DebugPout + << "MapVolFields : Storing old time for " << fld->name() + << endl; + + const_cast(*fld).storeOldTimes(); + } + + + for (const auto& fld : fields) + { + const word& name0 = fld->name(); + + DebugPout + << "MapVolFields : mapping " << name0 << endl; + + UPtrList meshToField(meshes.size()); + forAll(meshes, meshi) + { + if (meshes.set(meshi)) + { + auto& meshFld = meshes[meshi]. + objectRegistry::lookupObjectRef(name0); + meshToField.set(meshi, &meshFld); + } + } + + MapVolField + ( + meshToField, + oldPatchStarts0, + oldPatchSizes0, + patchProcAddressing, + cellProcAddressing, + faceProcAddressing, + fullyMapped + ); + } +} + + +template +void Foam::fvMeshAdder::MapDimFields +( + const UPtrList& meshes, + const labelListList& cellProcAddressing, + const bool fullyMapped +) +{ + typedef DimensionedField fldType; + + if (meshes.size() == 0 || !meshes.set(0)) + { + FatalErrorInFunction << "Not valid field at element 0" + << " in mesh list of size " << meshes.size() << exit(FatalError); + } + const fvMesh& mesh0 = meshes[0]; + + HashTable fields + ( + mesh0.objectRegistry::lookupClass() + ); + + + for (const auto& fld : fields) + { + const word& name0 = fld->name(); + + DebugPout + << "MapDimFields : mapping " << name0 << endl; + + UPtrList meshToField(meshes.size()); + forAll(meshes, meshi) + { + if (meshes.set(meshi)) + { + auto& meshFld = meshes[meshi]. + objectRegistry::lookupObjectRef(name0); + meshToField.set(meshi, &meshFld); + } + } + + MapDimField(meshToField, cellProcAddressing, fullyMapped); + } +} + + +template +void Foam::fvMeshAdder::MapSurfaceFields +( + const UPtrList& meshes, + const labelList& oldFaceOwner0, + const labelList& oldPatchStarts0, + const labelList& oldPatchSizes0, + const labelListList& patchProcAddressing, + const labelListList& cellProcAddressing, + const labelListList& faceProcAddressing, + const labelListList& pointProcAddressing, + const bool fullyMapped +) +{ + typedef GeometricField fldType; + + if (meshes.size() == 0 || !meshes.set(0)) + { + FatalErrorInFunction << "Not valid field at element 0" + << " in mesh list of size " << meshes.size() << exit(FatalError); + } + const auto& mesh0 = meshes[0]; + + HashTable fields + ( + mesh0.objectRegistry::lookupClass() + ); + + + // It is necessary to enforce that all old-time fields are stored + // before the mapping is performed. Otherwise, if the + // old-time-level field is mapped before the field itself, sizes + // will not match. + + for (const auto& fld : fields) + { + DebugPout + << "MapSurfaceFields : Storing old time for " << fld->name() + << endl; + + const_cast(*fld).storeOldTimes(); + } + + + for (const auto& fld : fields) + { + const word& name0 = fld->name(); + + DebugPout + << "MapSurfaceFields : Mapping " << fld->name() << endl; + + UPtrList meshToField(meshes.size()); + forAll(meshes, meshi) + { + if (meshes.set(meshi)) + { + auto& meshFld = meshes[meshi]. + objectRegistry::lookupObjectRef(name0); + meshToField.set(meshi, &meshFld); + } + } + + MapSurfaceField + ( + meshToField, + oldFaceOwner0, + oldPatchStarts0, + oldPatchSizes0, + patchProcAddressing, + cellProcAddressing, + faceProcAddressing, + fullyMapped + ); + } +} + + // ************************************************************************* // diff --git a/src/dynamicMesh/polyMeshAdder/polyMeshAdder.C b/src/dynamicMesh/polyMeshAdder/polyMeshAdder.C index 5fc8eff9a9..0dfaa92d41 100644 --- a/src/dynamicMesh/polyMeshAdder/polyMeshAdder.C +++ b/src/dynamicMesh/polyMeshAdder/polyMeshAdder.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019,2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -38,6 +38,7 @@ License #include "polyModifyFace.H" #include "polyRemovePoint.H" #include "polyTopoChange.H" +#include "globalIndex.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -2121,8 +2122,7 @@ Foam::Map Foam::polyMeshAdder::findSharedPoints //Pout<< "Merging point " << pointi // << " at " << mesh.points()[pointi] - // << " into master point " - // << masterPointi + // << " into master point " << masterPointi // << " at " << mesh.points()[masterPointi] // << endl; @@ -2302,4 +2302,747 @@ void Foam::polyMeshAdder::mergePoints } +Foam::label Foam::polyMeshAdder::procPatchIndex +( + const polyBoundaryMesh& pbm, + const label nbrProci, + const label n +) +{ + // Find n'th processor patch going to nbrProci. Usually n=0 but in some + // cases (e.g. processorCyclic, implicit cht) there can be more than one + // processor patch between two processors. + + label index = n; + + for (label patchi = pbm.nNonProcessor(); patchi < pbm.size(); patchi++) + { + const processorPolyPatch& pp = + refCast(pbm[patchi]); + if (pp.neighbProcNo() == nbrProci) + { + if (index == 0) + { + return patchi; + } + else + { + --index; + } + } + } + + FatalErrorInFunction << "no patch found to processor " << nbrProci + << ". Current patches:" << pbm.names() << exit(FatalError); + return -1; +} + + +Foam::label Foam::polyMeshAdder::procPatchPairs +( + const UPtrList& meshes, + List>& localPatch, + List>& remoteProc, + List>& remotePatch + //List& remotePatchFace, + //List& remotePatchFaceStart +) +{ + // Determine pairs of processor patches: + // - remote processor + // - patch on remote processor + // - face on remote patch + // - starting index on remote face + localPatch.setSize(meshes.size()); + remoteProc.setSize(meshes.size()); + remotePatch.setSize(meshes.size()); + //remotePatchFace.setSize(meshes.size()); + //remotePatchFaceStart.setSize(meshes.size()); + + + // Check that all processors have the same globalPatches + { + const polyBoundaryMesh& pbm = meshes[0].boundaryMesh(); + const wordList names0(SubList(pbm.names(), pbm.nNonProcessor())); + for (label proci = 1; proci < meshes.size(); proci++) + { + const polyBoundaryMesh& pbm = meshes[proci].boundaryMesh(); + const wordList names(pbm.names()); + + if (SubList(names, pbm.nNonProcessor()) != names0) + { + FatalErrorInFunction + << "Patch names should be identical on all processors." + << " Processor 0 has " << names0 + << ". Processor " << proci + << " has " << names + << exit(FatalError); + } + } + } + + + // Work array + labelList nNeighbourProcs(meshes.size()); + + forAll(meshes, proci) + { + const polyBoundaryMesh& pbm = meshes[proci].boundaryMesh(); + + // Running count of number of patches communicating with same nbr + // (usually 0) + nNeighbourProcs = 0; + + for (label patchi = pbm.nNonProcessor(); patchi < pbm.size(); patchi++) + { + const processorPolyPatch& pp = + refCast(pbm[patchi]); + if (pp.owner()) + { + const label nbrProci = pp.neighbProcNo(); + const label nbrPatchi = procPatchIndex + ( + meshes[nbrProci].boundaryMesh(), + proci, + nNeighbourProcs[nbrProci] + ); + + const auto& nbrPbm = meshes[nbrProci].boundaryMesh(); + const auto& nbrPp = nbrPbm[nbrPatchi]; + if (pp.size() != nbrPp.size()) + { + FatalErrorInFunction + << "at proc:" << proci + << " processor patch " + << pp.name() << " is not same size " << pp.size() + << " as coupled patch " << nbrPp.name() + << " on proc:" << nbrProci + << " size:" << nbrPp.size() + << exit(FatalError); + } + + localPatch[proci].append(patchi); + remoteProc[proci].append(nbrProci); + remotePatch[proci].append(nbrPatchi); + + localPatch[nbrProci].append(nbrPatchi); + remoteProc[nbrProci].append(proci); + remotePatch[nbrProci].append(patchi); + + nNeighbourProcs[nbrProci]++; + } + } + } + + //// Fill in the patch face ordering. Assume correct ordering. + //forAll(meshes, proci) + //{ + // const polyBoundaryMesh& pbm = meshes[proci].boundaryMesh(); + // + // const DynamicList