From f95eb5fd116b81019ff1c90db975ac8b5b333901 Mon Sep 17 00:00:00 2001 From: Will Bainbridge Date: Fri, 3 Feb 2023 13:14:00 +0000 Subject: [PATCH] meshToMesh, mapFieldsPar: Rationalisation Cell-to-cell interpolation has been moved to a hierarchy separate from meshToMesh, called cellsToCells. The meshToMesh class is now a combination of a cellsToCells object and multiple patchToPatch objects. This means that when only cell-to-cell interpolation is needed a basic cellsToCells object can be selected. Cell-to-cell and vol-field-to-vol-field interpolation now has two well defined sets of functions, with a clear distinction in how weights that do not sum to unity are handled. Non-unity weights are either normalised, or a left-over field is provided with which to complete the weighted sum. The left-over approach is now consistently applied in mapFieldsPar, across both the internal and patch fields, if mapping onto an existing field in the target case. Warning are now generated for invalid combinations of settings, such as mapping between inconsistent meshes without a pre-existing target field. All mapping functions now take fields as const references and return tmp fields. This avoids the pattern in which non-const fields are provided which relate to the source, and at some point in the function transfer to the target. This pattern is difficult to reason about and does not provide any actual computational advantage, as the fields invariably get re-allocated as part of the process anyway. MeshToMesh no longer stores the cutting patches. The set of cutting patches is not needed anywhere except at the point of mapping a field, so it is now supplied to the mapping functions as an argument. The meshToMesh topology changer no longer supports cutting patch information. This did not previously work. Cutting patches either get generated as calculated, or they require a pre-existing field to specify their boundary condition. Neither of these options is suitable for a run-time mesh change. More code has been shared with patchToPatch, reducing duplication. --- .../preProcessing/mapFieldsPar/mapFieldsPar.C | 37 +- .../mapFieldsPar/mapGeometricFields.C | 232 +++------ .../mapFieldsPar/mapGeometricFields.H | 3 +- src/finiteVolume/Make/files | 2 + .../fvMeshToFvMesh/fvMeshToFvMesh.H | 86 ++-- .../fvMeshToFvMesh/fvMeshToFvMeshTemplates.C | 323 +++++++----- .../patchToPatchFvPatchFieldMapper.C | 9 +- .../patchToPatchFvPatchFieldMapper.H | 20 +- .../patchToPatchFvPatchFieldMapperTemplates.C | 29 +- .../patchToPatchLeftOverFvPatchFieldMapper.C | 37 ++ .../patchToPatchLeftOverFvPatchFieldMapper.H | 104 ++++ ...atchLeftOverFvPatchFieldMapperTemplates.C} | 43 +- ...patchToPatchNormalisedFvPatchFieldMapper.C | 37 ++ ...patchToPatchNormalisedFvPatchFieldMapper.H | 104 ++++ ...tchNormalisedFvPatchFieldMapperTemplates.C | 53 ++ .../meshToMesh/MeshToMeshMapGeometricFields.H | 94 +--- .../meshToMesh/fvMeshTopoChangersMeshToMesh.C | 74 +-- .../meshToMesh/fvMeshTopoChangersMeshToMesh.H | 6 +- .../interRegionHeatTransfer.H | 2 +- .../interRegionModel/interRegionModel.C | 71 ++- .../interRegionModel/interRegionModel.H | 17 +- .../interRegionModel/interRegionModelI.H | 15 +- .../interRegionModelTemplates.C | 10 +- src/meshTools/Make/files | 12 +- .../cellsToCells/cellsToCells/cellsToCells.C | 368 ++++++++++++++ .../cellsToCells/cellsToCells/cellsToCells.H | 301 +++++++++++ .../cellsToCells/cellsToCells/cellsToCellsI.H | 42 ++ .../cellsToCells/cellsToCellsParallelOps.C} | 49 +- .../cellsToCells/cellsToCellsTemplates.C | 99 ++++ .../intersection/intersectionCellsToCells.C} | 218 ++++---- .../intersection/intersectionCellsToCells.H} | 102 ++-- .../matching/matchingCellsToCells.C} | 154 +++--- .../matching/matchingCellsToCells.H} | 86 ++-- .../nearest/nearestCellsToCells.C} | 158 +++--- .../nearest/nearestCellsToCells.H} | 90 ++-- .../meshToMeshMethod/meshToMeshMethod.C | 184 ------- .../meshToMeshMethod/meshToMeshMethod.H | 199 -------- src/meshTools/meshToMesh/meshToMesh.C | 469 ++++++------------ src/meshTools/meshToMesh/meshToMesh.H | 201 +------- src/meshTools/meshToMesh/meshToMeshI.H | 26 +- .../meshToMesh/meshToMeshTemplates.C | 200 -------- .../intersection/intersectionPatchToPatch.H | 4 +- .../patchToPatch/patchToPatch/patchToPatch.H | 30 +- .../patchToPatch/patchToPatchParallelOps.C | 10 +- .../patchToPatch/patchToPatchTemplates.C | 124 +---- .../patchToPatchTools/patchToPatchTools.H | 27 +- .../patchToPatchToolsTemplates.C | 106 +++- .../CHT/heatExchanger/constant/air/fvModels | 4 +- .../heatExchanger/constant/porous/fvModels | 2 +- 49 files changed, 2356 insertions(+), 2317 deletions(-) create mode 100644 src/finiteVolume/fvMeshToFvMesh/patchToPatchLeftOverFvPatchFieldMapper.C create mode 100644 src/finiteVolume/fvMeshToFvMesh/patchToPatchLeftOverFvPatchFieldMapper.H rename src/{meshTools/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethodNew.C => finiteVolume/fvMeshToFvMesh/patchToPatchLeftOverFvPatchFieldMapperTemplates.C} (58%) create mode 100644 src/finiteVolume/fvMeshToFvMesh/patchToPatchNormalisedFvPatchFieldMapper.C create mode 100644 src/finiteVolume/fvMeshToFvMesh/patchToPatchNormalisedFvPatchFieldMapper.H create mode 100644 src/finiteVolume/fvMeshToFvMesh/patchToPatchNormalisedFvPatchFieldMapperTemplates.C create mode 100644 src/meshTools/cellsToCells/cellsToCells/cellsToCells.C create mode 100644 src/meshTools/cellsToCells/cellsToCells/cellsToCells.H create mode 100644 src/meshTools/cellsToCells/cellsToCells/cellsToCellsI.H rename src/meshTools/{meshToMesh/meshToMeshParallelOps.C => cellsToCells/cellsToCells/cellsToCellsParallelOps.C} (97%) create mode 100644 src/meshTools/cellsToCells/cellsToCells/cellsToCellsTemplates.C rename src/meshTools/{meshToMesh/calcMethod/cellVolumeWeight/cellVolumeWeightMethod.C => cellsToCells/intersection/intersectionCellsToCells.C} (70%) rename src/meshTools/{meshToMesh/calcMethod/cellVolumeWeight/cellVolumeWeightMethod.H => cellsToCells/intersection/intersectionCellsToCells.H} (66%) rename src/meshTools/{meshToMesh/calcMethod/direct/directMethod.C => cellsToCells/matching/matchingCellsToCells.C} (70%) rename src/meshTools/{meshToMesh/calcMethod/direct/directMethod.H => cellsToCells/matching/matchingCellsToCells.H} (70%) rename src/meshTools/{meshToMesh/calcMethod/mapNearest/mapNearestMethod.C => cellsToCells/nearest/nearestCellsToCells.C} (76%) rename src/meshTools/{meshToMesh/calcMethod/mapNearest/mapNearestMethod.H => cellsToCells/nearest/nearestCellsToCells.H} (71%) delete mode 100644 src/meshTools/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.C delete mode 100644 src/meshTools/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.H delete mode 100644 src/meshTools/meshToMesh/meshToMeshTemplates.C diff --git a/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C b/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C index 3a4ee7068c..020a652c17 100644 --- a/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C +++ b/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2023 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -34,7 +34,7 @@ Description #include "fvMeshToFvMesh.H" #include "mapGeometricFields.H" #include "mapClouds.H" -#include "cellVolumeWeightMethod.H" +#include "intersectionCellsToCells.H" using namespace Foam; @@ -56,12 +56,7 @@ void mapConsistentMesh Info<< nl << "Mapping geometric fields" << endl; - mapGeometricFields - ( - interp, - selectedFields, - noLagrangian - ); + mapGeometricFields(interp, wordReList(), selectedFields, noLagrangian); if (!noLagrangian) { @@ -70,12 +65,12 @@ void mapConsistentMesh } -void mapSubMesh +void mapMesh ( const fvMesh& srcMesh, const fvMesh& tgtMesh, const HashTable& patchMap, - const wordList& cuttingPatches, + const wordReList& cuttingPatches, const word& mapMethod, const HashSet& selectedFields, const bool noLagrangian @@ -84,23 +79,11 @@ void mapSubMesh Info<< nl << "Creating and mapping fields for time " << srcMesh.time().name() << nl << endl; - fvMeshToFvMesh interp - ( - srcMesh, - tgtMesh, - mapMethod, - patchMap, - cuttingPatches - ); + fvMeshToFvMesh interp(srcMesh, tgtMesh, mapMethod, patchMap); Info<< nl << "Mapping geometric fields" << endl; - mapGeometricFields - ( - interp, - selectedFields, - noLagrangian - ); + mapGeometricFields(interp, cuttingPatches, selectedFields, noLagrangian); if (!noLagrangian) { @@ -194,7 +177,7 @@ int main(int argc, char *argv[]) args.optionLookupOrDefault ( "mapMethod", - cellVolumeWeightMethod::typeName + cellsToCellss::intersection::typeName ) ); Info<< "Mapping method: " << mapMethod << endl; @@ -210,7 +193,7 @@ int main(int argc, char *argv[]) #include "createTimes.H" HashTable patchMap; - wordList cuttingPatches; + wordReList cuttingPatches; if (!consistent) { @@ -276,7 +259,7 @@ int main(int argc, char *argv[]) } else { - mapSubMesh + mapMesh ( srcMesh, tgtMesh, diff --git a/applications/utilities/preProcessing/mapFieldsPar/mapGeometricFields.C b/applications/utilities/preProcessing/mapFieldsPar/mapGeometricFields.C index 40cb4fd77a..68fecf12e3 100644 --- a/applications/utilities/preProcessing/mapFieldsPar/mapGeometricFields.C +++ b/applications/utilities/preProcessing/mapFieldsPar/mapGeometricFields.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2023 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -35,94 +35,13 @@ License namespace Foam { -template -void evaluateConstraintTypes(VolField& fld) -{ - typename VolField:: - Boundary& fldBf = fld.boundaryFieldRef(); - - if - ( - Pstream::defaultCommsType == Pstream::commsTypes::blocking - || Pstream::defaultCommsType == Pstream::commsTypes::nonBlocking - ) - { - label nReq = Pstream::nRequests(); - - forAll(fldBf, patchi) - { - fvPatchField& tgtField = fldBf[patchi]; - - if - ( - tgtField.type() == tgtField.patch().patch().type() - && polyPatch::constraintType(tgtField.patch().patch().type()) - ) - { - tgtField.initEvaluate(Pstream::defaultCommsType); - } - } - - // Block for any outstanding requests - if - ( - Pstream::parRun() - && Pstream::defaultCommsType == Pstream::commsTypes::nonBlocking - ) - { - Pstream::waitRequests(nReq); - } - - forAll(fldBf, patchi) - { - fvPatchField& tgtField = fldBf[patchi]; - - if - ( - tgtField.type() == tgtField.patch().patch().type() - && polyPatch::constraintType(tgtField.patch().patch().type()) - ) - { - tgtField.evaluate(Pstream::defaultCommsType); - } - } - } - else if (Pstream::defaultCommsType == Pstream::commsTypes::scheduled) - { - const lduSchedule& patchSchedule = - fld.mesh().globalData().patchSchedule(); - - forAll(patchSchedule, patchEvali) - { - label patchi = patchSchedule[patchEvali].patch; - fvPatchField& tgtField = fldBf[patchi]; - - if - ( - tgtField.type() == tgtField.patch().patch().type() - && polyPatch::constraintType(tgtField.patch().patch().type()) - ) - { - if (patchSchedule[patchEvali].init) - { - tgtField.initEvaluate(Pstream::commsTypes::scheduled); - } - else - { - tgtField.evaluate(Pstream::commsTypes::scheduled); - } - } - } - } -} - - template void mapVolTypeFields ( - const IOobjectList& objects, + const fvMeshToFvMesh& interp, + const wordReList& cuttingPatches, const HashSet& selectedFields, - const fvMeshToFvMesh& interp + const IOobjectList& objects ) { const fvMesh& srcMesh = static_cast(interp.srcMesh()); @@ -134,106 +53,95 @@ void mapVolTypeFields { const word& fieldName = fieldIter()->name(); - if (selectedFields.empty() || selectedFields.found(fieldName)) + if (!selectedFields.empty() && !selectedFields.found(fieldName)) { - const VolField fieldSource(*fieldIter(), srcMesh); + continue; + } - typeIOobject> targetIO + const VolField fieldSource(*fieldIter(), srcMesh); + + typeIOobject> targetIO + ( + fieldName, + tgtMesh.time().name(), + tgtMesh, + IOobject::READ_IF_PRESENT + ); + + // Warnings about inconsistent execution + if (targetIO.headerOk() && interp.consistent()) + { + WarningInFunction + << "Mapping of field " << fieldName << " will not utilise " + << "the corresponding field in the target case, as the map is " + << "consistent (i.e., all patches are mapped)" << endl; + } + if (!targetIO.headerOk() && !interp.consistent()) + { + WarningInFunction + << "Cannot map field " << fieldName << " because the " + << "map is not consistent (i.e., not all patches are " + << "mapped), and there is no corresponding field in " + << "the target case" << endl; + continue; + } + if (!targetIO.headerOk() && !cuttingPatches.empty()) + { + WarningInFunction + << "Cutting patches will not be used for field " << fieldName + << " because no there is no corresponding field in the target " + << "case" << endl; + } + + if (targetIO.headerOk()) + { + Info<< " mapping into existing field " << fieldName << endl; + + VolField fieldTarget(targetIO, tgtMesh); + + fieldTarget.reset ( - fieldName, - tgtMesh.time().name(), - tgtMesh, - IOobject::MUST_READ + interp.srcToTgt(fieldSource, fieldTarget, cuttingPatches) ); - if (targetIO.headerOk()) - { - Info<< " interpolating onto existing field " - << fieldName << endl; - VolField fieldTarget(targetIO, tgtMesh); + fieldTarget.write(); + } + else + { + Info<< " creating new field " << fieldName << endl; - interp.mapSrcToTgt(fieldSource, fieldTarget); - - evaluateConstraintTypes(fieldTarget); - - fieldTarget.write(); - } - else - { - Info<< " creating new field " - << fieldName << endl; - - targetIO.readOpt() = IOobject::NO_READ; - - tmp> tfieldTarget - ( - interp.mapSrcToTgt(fieldSource) - ); - - VolField fieldTarget(targetIO, tfieldTarget); - - evaluateConstraintTypes(fieldTarget); - - fieldTarget.write(); - } + VolField(targetIO, interp.srcToTgt(fieldSource)).write(); } } } - -template class GeoField> -void unMappedTypeFields(const IOobjectList& objects) -{ - IOobjectList fields = objects.lookupClass(GeoField::typeName); - - forAllConstIter(IOobjectList, fields, fieldIter) - { - mvBak(fieldIter()->objectPath(false), "unmapped"); - } } -} // End namespace Foam - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // void Foam::mapGeometricFields ( const fvMeshToFvMesh& interp, + const wordReList& cuttingPatches, const HashSet& selectedFields, const bool noLagrangian ) { + // Search for list of source objects for this time const polyMesh& srcMesh = interp.srcMesh(); - const polyMesh& tgtMesh = interp.tgtMesh(); + IOobjectList objects(srcMesh, srcMesh.time().name()); - { - // Search for list of source objects for this time - IOobjectList objects(srcMesh, srcMesh.time().name()); - - // Map the fields - #define MapVolTypeFields(Type, nullArg) \ - mapVolTypeFields \ - ( \ - objects, \ - selectedFields, \ - interp \ - ); - FOR_ALL_FIELD_TYPES(MapVolTypeFields); - #undef MapVolTypeFields - } - - { - // Search for list of target objects for this time - IOobjectList objects(tgtMesh, tgtMesh.time().name()); - - // Mark surface and point fields as unmapped - #define UnMappedTypeFields(Type, GeoField) \ - unMappedTypeFields(objects); - FOR_ALL_FIELD_TYPES(UnMappedTypeFields, SurfaceField); - FOR_ALL_FIELD_TYPES(UnMappedTypeFields, PointField); - #undef UnMappedTypeFields - } + // Map the fields + #define MapVolTypeFields(Type, nullArg) \ + mapVolTypeFields \ + ( \ + interp, \ + cuttingPatches, \ + selectedFields, \ + objects \ + ); + FOR_ALL_FIELD_TYPES(MapVolTypeFields); + #undef MapVolTypeFields } diff --git a/applications/utilities/preProcessing/mapFieldsPar/mapGeometricFields.H b/applications/utilities/preProcessing/mapFieldsPar/mapGeometricFields.H index 039fadc6a4..cd823f125e 100644 --- a/applications/utilities/preProcessing/mapFieldsPar/mapGeometricFields.H +++ b/applications/utilities/preProcessing/mapFieldsPar/mapGeometricFields.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2023 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -47,6 +47,7 @@ class fvMeshToFvMesh; void mapGeometricFields ( const fvMeshToFvMesh& interp, + const wordReList& cuttingPatches, const HashSet& selectedFields, const bool noLagrangian ); diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files index 4e299686aa..47bbcbe6be 100644 --- a/src/finiteVolume/Make/files +++ b/src/finiteVolume/Make/files @@ -517,5 +517,7 @@ solver/solverNew.C fvMeshToFvMesh/fvMeshToFvMesh.C fvMeshToFvMesh/patchToPatchFvPatchFieldMapper.C +fvMeshToFvMesh/patchToPatchLeftOverFvPatchFieldMapper.C +fvMeshToFvMesh/patchToPatchNormalisedFvPatchFieldMapper.C LIB = $(FOAM_LIBBIN)/libfiniteVolume diff --git a/src/finiteVolume/fvMeshToFvMesh/fvMeshToFvMesh.H b/src/finiteVolume/fvMeshToFvMesh/fvMeshToFvMesh.H index 2adcb32383..36f0a88dda 100644 --- a/src/finiteVolume/fvMeshToFvMesh/fvMeshToFvMesh.H +++ b/src/finiteVolume/fvMeshToFvMesh/fvMeshToFvMesh.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2022 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2022-2023 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -50,6 +50,15 @@ class fvMeshToFvMesh : public meshToMesh { +private: + + // Private Member Functions + + //- Evaluate constraint types for the given vol field + template + static void evaluateConstraintTypes(VolField& fld); + + public: //- Run-time type information @@ -68,48 +77,47 @@ public: // Member Functions - // Evaluation + // Interpolation - // Source-to-target volume field mapping + //- Interpolate a source vol field to the target with no left + // over values specified. If the interpolation weight sum is less + // than one for a face then they will be normalised. If the + // interpolation weight sum is zero for a face then that face's + // value will be NaN. + template + tmp> srcToTgt + ( + const VolField& srcFld + ) const; - //- Interpolate a field with a defined operation. Values - // passed in via 'result' are used to initialise the return - // value. - template - void mapSrcToTgt - ( - const VolField& field, - VolField& result - ) const; + //- Interpolate a source vol field to the target with left over + // values specified. If the interpolation weight sum is less than + // one for a face then the average will include the left over + // value multiplied by one minus the weight sum. + template + tmp> srcToTgt + ( + const VolField& srcFld, + const VolField& leftOverTgtFld, + const UList& tgtCuttingPatches + ) const; - //- Interpolate a field with a defined operation. The initial - // values of the result are set to zero. - template - tmp> mapSrcToTgt - ( - const VolField& field - ) const; + //- Interpolate a source vol internal field to the target with no + // left over values specified. As the corresponding srcToTgt. + template + tmp> srcToTgt + ( + const VolInternalField& srcFld + ) const; - - // Source-to-target volume internal field mapping - - //- Interpolate a field with a defined operation. Values - // passed in via 'result' are used to initialise the return - // value. - template - void mapSrcToTgt - ( - const VolInternalField& field, - VolInternalField& result - ) const; - - //- Interpolate a field with a defined operation. The initial - // values of the result are set to zero. - template - tmp> mapSrcToTgt - ( - const VolInternalField& field - ) const; + //- Interpolate a source vol internal field to the target with left + // over values specified. As the corresponding srcToTgt. + template + tmp> srcToTgt + ( + const VolInternalField& srcFld, + const VolInternalField& leftOverTgtFld + ) const; }; diff --git a/src/finiteVolume/fvMeshToFvMesh/fvMeshToFvMeshTemplates.C b/src/finiteVolume/fvMeshToFvMesh/fvMeshToFvMeshTemplates.C index 252fe70bb7..109ea25ec9 100644 --- a/src/finiteVolume/fvMeshToFvMesh/fvMeshToFvMeshTemplates.C +++ b/src/finiteVolume/fvMeshToFvMesh/fvMeshToFvMeshTemplates.C @@ -26,78 +26,105 @@ License #include "fvMeshToFvMesh.H" #include "directFvPatchFieldMapper.H" #include "identityFvPatchFieldMapper.H" -#include "patchToPatchFvPatchFieldMapper.H" +#include "patchToPatchNormalisedFvPatchFieldMapper.H" +#include "patchToPatchLeftOverFvPatchFieldMapper.H" -// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // template -void Foam::fvMeshToFvMesh::mapSrcToTgt -( - const VolField& field, - VolField& result -) const +void Foam::fvMeshToFvMesh::evaluateConstraintTypes(VolField& fld) { - meshToMesh::mapSrcToTgt(field, result.primitiveFieldRef()); + typename VolField::Boundary& fldBf = fld.boundaryFieldRef(); - typename VolField:: - Boundary& resultBf = result.boundaryFieldRef(); - - forAll(srcToTgtPatchIDs(), i) + if + ( + Pstream::defaultCommsType == Pstream::commsTypes::blocking + || Pstream::defaultCommsType == Pstream::commsTypes::nonBlocking + ) { - const label srcPatchi = srcToTgtPatchIDs()[i].first(); - const label tgtPatchi = srcToTgtPatchIDs()[i].second(); + label nReq = Pstream::nRequests(); - const fvPatchField& srcField = field.boundaryField()[srcPatchi]; - fvPatchField& tgtField = resultBf[tgtPatchi]; + forAll(fldBf, patchi) + { + fvPatchField& tgtField = fldBf[patchi]; - // Clone and map - tmp> tnewTgt - ( - fvPatchField::New + if ( - srcField, - tgtField.patch(), - result(), - patchToPatchFvPatchFieldMapper - ( - srcToTgtPatchToPatches()[i], - true - ) + tgtField.type() == tgtField.patch().patch().type() + && polyPatch::constraintType(tgtField.patch().patch().type()) ) - ); + { + tgtField.initEvaluate(Pstream::defaultCommsType); + } + } - // Transfer all mapped quantities (value and e.g. gradient) onto - // tgtField. Value will get overwritten below. - tgtField.map(tnewTgt(), identityFvPatchFieldMapper()); + // Block for any outstanding requests + if + ( + Pstream::parRun() + && Pstream::defaultCommsType == Pstream::commsTypes::nonBlocking + ) + { + Pstream::waitRequests(nReq); + } + + forAll(fldBf, patchi) + { + fvPatchField& tgtField = fldBf[patchi]; + + if + ( + tgtField.type() == tgtField.patch().patch().type() + && polyPatch::constraintType(tgtField.patch().patch().type()) + ) + { + tgtField.evaluate(Pstream::defaultCommsType); + } + } } - - forAll(tgtCuttingPatchIDs(), i) + else if (Pstream::defaultCommsType == Pstream::commsTypes::scheduled) { - const label patchi = tgtCuttingPatchIDs()[i]; - fvPatchField& pf = resultBf[patchi]; - pf == pf.patchInternalField(); + const lduSchedule& patchSchedule = + fld.mesh().globalData().patchSchedule(); + + forAll(patchSchedule, patchEvali) + { + label patchi = patchSchedule[patchEvali].patch; + fvPatchField& tgtField = fldBf[patchi]; + + if + ( + tgtField.type() == tgtField.patch().patch().type() + && polyPatch::constraintType(tgtField.patch().patch().type()) + ) + { + if (patchSchedule[patchEvali].init) + { + tgtField.initEvaluate(Pstream::commsTypes::scheduled); + } + else + { + tgtField.evaluate(Pstream::commsTypes::scheduled); + } + } + } } } +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + template -Foam::tmp> -Foam::fvMeshToFvMesh::mapSrcToTgt +Foam::tmp> Foam::fvMeshToFvMesh::srcToTgt ( - const VolField& field + const VolField& srcFld ) const { const fvMesh& tgtMesh = static_cast(meshToMesh::tgtMesh()); - const fvBoundaryMesh& tgtBm = tgtMesh.boundary(); - const typename VolField::Boundary& srcBfld = - field.boundaryField(); - - PtrList> tgtPatchFields(tgtBm.size()); - - // construct tgt boundary patch types as copy of 'field' boundary types - // note: this will provide place holders for fields with additional - // entries, but these values will need to be reset + // Construct target patch fields as copies of source patch fields, but do + // not map values yet + PtrList> tgtPatchFields(tgtMesh.boundary().size()); forAll(srcToTgtPatchIDs(), i) { const label srcPatchi = srcToTgtPatchIDs()[i].first(); @@ -110,7 +137,7 @@ Foam::fvMeshToFvMesh::mapSrcToTgt tgtPatchi, fvPatchField::New ( - srcBfld[srcPatchi], + srcFld.boundaryField()[srcPatchi], tgtMesh.boundary()[tgtPatchi], DimensionedField::null(), directFvPatchFieldMapper @@ -122,13 +149,14 @@ Foam::fvMeshToFvMesh::mapSrcToTgt } } - // Any unset tgtPatchFields become calculated + // Create calculated patch fields for any unset target patches. Use + // fvPatchField::New to construct these, rather than using the + // calculated constructor directly, so that constraints are maintained. + labelList tgtPatchFieldIsUnMapped(tgtPatchFields.size(), false); forAll(tgtPatchFields, tgtPatchi) { if (!tgtPatchFields.set(tgtPatchi)) { - // Note: use factory New method instead of direct generation of - // calculated so we keep constraints tgtPatchFields.set ( tgtPatchi, @@ -139,75 +167,148 @@ Foam::fvMeshToFvMesh::mapSrcToTgt DimensionedField::null() ) ); + + tgtPatchFieldIsUnMapped[tgtPatchi] = + polyPatch::constraintType + ( + tgtMesh.boundary()[tgtPatchi].patch().type() + ); } } - tmp> tresult - ( - new VolField + // Construct the result field + tmp> ttgtFld = + VolField::New ( - IOobject - ( - typedName("interpolate(" + field.name() + ")"), - tgtMesh.time().name(), - tgtMesh, - IOobject::NO_READ, - IOobject::NO_WRITE - ), - tgtMesh, - field.dimensions(), - Field(tgtMesh.nCells(), Zero), + typedName("interpolate(" + srcFld.name() + ")"), + srcToTgt(srcFld.internalField())(), tgtPatchFields - ) - ); + ); + typename VolField::Boundary& tgtBfld = + ttgtFld.ref().boundaryFieldRef(); - fvMeshToFvMesh::mapSrcToTgt(field, tresult.ref()); + // Mapped patches + forAll(srcToTgtPatchIDs(), i) + { + const label srcPatchi = srcToTgtPatchIDs()[i].first(); + const label tgtPatchi = srcToTgtPatchIDs()[i].second(); - return tresult; -} - - -template -void Foam::fvMeshToFvMesh::mapSrcToTgt -( - const VolInternalField& field, - VolInternalField& result -) const -{ - meshToMesh::mapSrcToTgt(field, result); -} - - -template -Foam::tmp> -Foam::fvMeshToFvMesh::mapSrcToTgt -( - const VolInternalField& field -) const -{ - const fvMesh& tgtMesh = static_cast(meshToMesh::tgtMesh()); - - tmp> tresult - ( - new VolInternalField + tgtBfld[tgtPatchi].map ( - IOobject + srcFld.boundaryField()[srcPatchi], + patchToPatchNormalisedFvPatchFieldMapper ( - typedName("interpolate(" + field.name() + ")"), - tgtMesh.time().name(), - tgtMesh, - IOobject::NO_READ, - IOobject::NO_WRITE - ), - tgtMesh, - field.dimensions(), - Field(tgtMesh.nCells(), Zero) - ) - ); + srcToTgtPatchToPatches()[i], + true + ) + ); + } - fvMeshToFvMesh::mapSrcToTgt(field, tresult.ref()); + // Un-mapped patches. Set values to that of the internal cell field. + forAll(tgtBfld, patchi) + { + if (tgtPatchFieldIsUnMapped[patchi]) + { + fvPatchField& tgtPfld = tgtBfld[patchi]; + tgtPfld == tgtPfld.patchInternalField(); + } + } - return tresult; + // Evaluate constraints + evaluateConstraintTypes(ttgtFld.ref()); + + return ttgtFld; +} + + +template +Foam::tmp> Foam::fvMeshToFvMesh::srcToTgt +( + const VolField& srcFld, + const VolField& leftOverTgtFld, + const UList& tgtCuttingPatchNames +) const +{ + // Construct the result field + tmp> ttgtFld = + VolField::New + ( + typedName("interpolate(" + srcFld.name() + ")"), + srcToTgt(srcFld.v(), leftOverTgtFld.v())(), + leftOverTgtFld.boundaryField() + ); + typename VolField::Boundary& tgtBfld = + ttgtFld.ref().boundaryFieldRef(); + + // Mapped patches + forAll(srcToTgtPatchIDs(), i) + { + const label srcPatchi = srcToTgtPatchIDs()[i].first(); + const label tgtPatchi = srcToTgtPatchIDs()[i].second(); + + tgtBfld[tgtPatchi].map + ( + leftOverTgtFld.boundaryField()[tgtPatchi], + identityFvPatchFieldMapper() + ); + tgtBfld[tgtPatchi].map + ( + srcFld.boundaryField()[srcPatchi], + patchToPatchLeftOverFvPatchFieldMapper + ( + srcToTgtPatchToPatches()[i], + true + ) + ); + } + + // Cutting patches. Set values to that of the internal cell field. + const labelHashSet tgtCuttingPatchIDs = + leftOverTgtFld.mesh().boundaryMesh().patchSet(tgtCuttingPatchNames); + forAllConstIter(labelHashSet, tgtCuttingPatchIDs, iter) + { + tgtBfld[iter.key()] == tgtBfld[iter.key()].patchInternalField(); + } + + // Evaluate constraints + evaluateConstraintTypes(ttgtFld.ref()); + + return ttgtFld; +} + + +template +Foam::tmp> Foam::fvMeshToFvMesh::srcToTgt +( + const VolInternalField& srcFld +) const +{ + return + VolInternalField::New + ( + typedName("interpolate(" + srcFld.name() + ")"), + static_cast(meshToMesh::tgtMesh()), + srcFld.dimensions(), + srcToTgtCellsToCells().srcToTgt(srcFld) + ); +} + + +template +Foam::tmp> Foam::fvMeshToFvMesh::srcToTgt +( + const VolInternalField& srcFld, + const VolInternalField& leftOverTgtFld +) const +{ + return + VolInternalField::New + ( + typedName("interpolate(" + srcFld.name() + ")"), + static_cast(meshToMesh::tgtMesh()), + leftOverTgtFld.dimensions(), + srcToTgtCellsToCells().srcToTgt(srcFld, leftOverTgtFld) + ); } diff --git a/src/finiteVolume/fvMeshToFvMesh/patchToPatchFvPatchFieldMapper.C b/src/finiteVolume/fvMeshToFvMesh/patchToPatchFvPatchFieldMapper.C index 9ce743d1c1..53fcea895d 100644 --- a/src/finiteVolume/fvMeshToFvMesh/patchToPatchFvPatchFieldMapper.C +++ b/src/finiteVolume/fvMeshToFvMesh/patchToPatchFvPatchFieldMapper.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2022 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2022-2023 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -27,13 +27,6 @@ License // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // -FOR_ALL_FIELD_TYPES -( - IMPLEMENT_FIELD_MAPPER_OPERATOR, - patchToPatchFvPatchFieldMapper -) - - void Foam::patchToPatchFvPatchFieldMapper::operator() ( Field