mapFieldsPar: updated to enable mapping from source patches (instead of recreating)

- patchFields now get mapped (instead of created)
  - with -consistent it now maps all patches except for processor ones (they are
    the only ones that are processor-local)
  - all constraint patches get evaluated after mapping to bring them up to date.

Patch contributed by Mattijs Janssens
This commit is contained in:
Henry Weller 2016-06-21 14:16:18 +01:00
parent e6f4d41228
commit 0aa05185db
9 changed files with 625 additions and 118 deletions

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -35,6 +35,88 @@ License
namespace Foam
{
template<class Type>
void evaluateConstraintTypes(GeometricField<Type, fvPatchField, volMesh>& fld)
{
typename GeometricField<Type, fvPatchField, volMesh>::
Boundary& fldBf = fld.boundaryFieldRef();
if
(
Pstream::defaultCommsType == Pstream::blocking
|| Pstream::defaultCommsType == Pstream::nonBlocking
)
{
label nReq = Pstream::nRequests();
forAll(fldBf, patchi)
{
fvPatchField<Type>& 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::nonBlocking
)
{
Pstream::waitRequests(nReq);
}
forAll(fldBf, patchi)
{
fvPatchField<Type>& 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::scheduled)
{
const lduSchedule& patchSchedule =
fld.mesh().globalData().patchSchedule();
forAll(patchSchedule, patchEvali)
{
label patchi = patchSchedule[patchEvali].patch;
fvPatchField<Type>& tgtField = fldBf[patchi];
if
(
tgtField.type() == tgtField.patch().patch().type()
&& polyPatch::constraintType(tgtField.patch().patch().type())
)
{
if (patchSchedule[patchEvali].init)
{
tgtField.initEvaluate(Pstream::scheduled);
}
else
{
tgtField.evaluate(Pstream::scheduled);
}
}
}
}
}
template<class Type, class CombineOp>
void MapVolFields
(
@ -57,8 +139,6 @@ void MapVolFields
if (selectedFields.empty() || selectedFields.found(fieldName))
{
Info<< " interpolating " << fieldName << endl;
const fieldType fieldSource(*fieldIter(), meshSource);
IOobject targetIO
@ -71,14 +151,21 @@ void MapVolFields
if (targetIO.headerOk())
{
Info<< " interpolating onto existing field "
<< fieldName << endl;
fieldType fieldTarget(targetIO, meshTarget);
interp.mapSrcToTgt(fieldSource, cop, fieldTarget);
evaluateConstraintTypes(fieldTarget);
fieldTarget.write();
}
else
{
Info<< " creating new field "
<< fieldName << endl;
targetIO.readOpt() = IOobject::NO_READ;
tmp<fieldType>
@ -86,6 +173,8 @@ void MapVolFields
fieldType fieldTarget(targetIO, tfieldTarget);
evaluateConstraintTypes(fieldTarget);
fieldTarget.write();
}
}

View File

@ -263,11 +263,11 @@ int main(int argc, char *argv[])
if (!consistent)
{
IOdictionary mapFieldsParDict
IOdictionary mapFieldsDict
(
IOobject
(
"mapFieldsParDict",
"mapFieldsDict",
runTimeTarget.system(),
runTimeTarget,
IOobject::MUST_READ_IF_MODIFIED,
@ -276,8 +276,8 @@ int main(int argc, char *argv[])
)
);
mapFieldsParDict.lookup("patchMap") >> patchMap;
mapFieldsParDict.lookup("cuttingPatches") >> cuttingPatches;
mapFieldsDict.lookup("patchMap") >> patchMap;
mapFieldsDict.lookup("cuttingPatches") >> cuttingPatches;
}
#include "setTimeIndex.H"
@ -326,7 +326,7 @@ int main(int argc, char *argv[])
meshSource,
meshTarget,
patchMap,
addProcessorPatches(meshTarget, cuttingPatches),
cuttingPatches,
mapMethod,
subtract,
selectedFields,

View File

@ -1,5 +1,13 @@
{
instantList sourceTimes = runTimeSource.times();
if (sourceTimes.empty())
{
FatalErrorInFunction << "No result times in source "
<< runTimeSource.caseName()
<< exit(FatalError);
}
label sourceTimeIndex = runTimeSource.timeIndex();
if (args.optionFound("sourceTime"))
{

View File

@ -153,7 +153,7 @@ Foam::fvPatchField<Type>::fvPatchField
patchType_(ptf.patchType_)
{
// For unmapped faces set to internal field value (zero-gradient)
if (notNull(iF) && iF.size())
if (notNull(iF) && mapper.hasUnmapped())
{
fvPatchField<Type>::operator=(this->patchInternalField());
}
@ -243,7 +243,7 @@ void Foam::fvPatchField<Type>::autoMap
{
Field<Type>& f = *this;
if (!this->size())
if (!this->size() && !mapper.distributed())
{
f.setSize(mapper.size());
if (f.size())
@ -257,38 +257,39 @@ void Foam::fvPatchField<Type>::autoMap
Field<Type>::autoMap(mapper);
// For unmapped faces set to internal field value (zero-gradient)
if
(
mapper.direct()
&& notNull(mapper.directAddressing())
&& mapper.directAddressing().size()
)
if (mapper.hasUnmapped())
{
Field<Type> pif(this->patchInternalField());
const labelList& mapAddressing = mapper.directAddressing();
forAll(mapAddressing, i)
if
(
mapper.direct()
&& notNull(mapper.directAddressing())
&& mapper.directAddressing().size()
)
{
if (mapAddressing[i] < 0)
const labelList& mapAddressing = mapper.directAddressing();
forAll(mapAddressing, i)
{
f[i] = pif[i];
if (mapAddressing[i] < 0)
{
f[i] = pif[i];
}
}
}
}
else if (!mapper.direct() && mapper.addressing().size())
{
Field<Type> pif(this->patchInternalField());
const labelListList& mapAddressing = mapper.addressing();
forAll(mapAddressing, i)
else if (!mapper.direct() && mapper.addressing().size())
{
const labelList& localAddrs = mapAddressing[i];
const labelListList& mapAddressing = mapper.addressing();
if (!localAddrs.size())
forAll(mapAddressing, i)
{
f[i] = pif[i];
const labelList& localAddrs = mapAddressing[i];
if (!localAddrs.size())
{
f[i] = pif[i];
}
}
}
}

View File

@ -72,21 +72,15 @@ bool Foam::directMethod::findInitialSeeds
if (mapFlag[srcI])
{
const pointField
pts(srcCells[srcI].points(srcFaces, srcPts).xfer());
forAll(pts, ptI)
{
const point& pt = pts[ptI];
label tgtI = tgt_.cellTree().findInside(pt);
const point srcCtr(srcCells[srcI].centre(srcPts, srcFaces));
label tgtI = tgt_.cellTree().findInside(srcCtr);
if (tgtI != -1 && intersect(srcI, tgtI))
{
srcSeedI = srcI;
tgtSeedI = tgtI;
return true;
}
return true;
}
}
}
@ -178,8 +172,6 @@ void Foam::directMethod::appendToDirectSeeds
const labelList& srcNbr = src_.cellCells()[srcSeedI];
const labelList& tgtNbr = tgt_.cellCells()[tgtSeedI];
const vectorField& srcCentre = src_.cellCentres();
forAll(srcNbr, i)
{
label srcI = srcNbr[i];
@ -194,15 +186,7 @@ void Foam::directMethod::appendToDirectSeeds
{
label tgtI = tgtNbr[j];
if
(
tgt_.pointInCell
(
srcCentre[srcI],
tgtI,
polyMesh::FACE_PLANES
)
)
if (intersect(srcI, tgtI))
{
// new match - append to lists
found = true;

View File

@ -0,0 +1,170 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::distributedWeightedFvPatchFieldMapper
Description
FieldMapper with weighted mapping from (optionally remote) quantities.
\*---------------------------------------------------------------------------*/
#ifndef distributedWeightedFvPatchFieldMapper_H
#define distributedWeightedFvPatchFieldMapper_H
#include "fvPatchFieldMapper.H"
#include "mapDistributeBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class distributedWeightedFvPatchFieldMapper Declaration
\*---------------------------------------------------------------------------*/
class distributedWeightedFvPatchFieldMapper
:
public fvPatchFieldMapper
{
const label singlePatchProc_;
const mapDistributeBase* distMapPtr_;
const labelListList& addressing_;
const scalarListList& weights_;
bool hasUnmapped_;
public:
// Constructors
//- Construct given addressing
distributedWeightedFvPatchFieldMapper
(
const label singlePatchProc,
const mapDistributeBase* distMapPtr,
const labelListList& addressing,
const scalarListList& weights
)
:
singlePatchProc_(singlePatchProc),
distMapPtr_(distMapPtr),
addressing_(addressing),
weights_(weights),
hasUnmapped_(false)
{
forAll(addressing_, i)
{
if (addressing_[i].size() == 0)
{
hasUnmapped_ = true;
}
}
if ((singlePatchProc_ == -1) != (distMapPtr_ != NULL))
{
FatalErrorIn
(
"distributedWeightedFvPatchFieldMapper::"
"distributedWeightedFvPatchFieldMapper(..)"
) << "Supply a mapDistributeBase if and only if "
<< "singlePatchProc is -1"
<< " singlePatchProc_:" << singlePatchProc_
<< " distMapPtr_:" << (distMapPtr_ != NULL)
<< exit(FatalError);
}
}
//- Destructor
virtual ~distributedWeightedFvPatchFieldMapper()
{}
// Member Functions
virtual label size() const
{
if (distributed())
{
return distributeMap().constructSize();
}
else
{
return addressing().size();
}
}
virtual bool direct() const
{
return false;
}
virtual bool distributed() const
{
return singlePatchProc_ == -1;
}
virtual const mapDistributeBase& distributeMap() const
{
if (!distMapPtr_)
{
FatalErrorIn
(
"distributedWeightedFvPatchFieldMapper::"
"distributeMap()"
) << "Cannot ask for distributeMap on a non-distributed"
<< " mapper" << exit(FatalError);
}
return *distMapPtr_;
}
virtual bool hasUnmapped() const
{
return hasUnmapped_;
}
virtual const labelListList& addressing() const
{
return addressing_;
}
virtual const scalarListList& weights() const
{
return weights_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -53,6 +53,116 @@ namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<>
void Foam::meshToMesh::mapAndOpSrcToTgt
(
const AMIPatchToPatchInterpolation& AMI,
const Field<scalar>& srcField,
Field<scalar>& tgtField,
const plusEqOp<scalar>& cop
) const
{}
template<>
void Foam::meshToMesh::mapAndOpSrcToTgt
(
const AMIPatchToPatchInterpolation& AMI,
const Field<vector>& srcField,
Field<vector>& tgtField,
const plusEqOp<vector>& cop
) const
{}
template<>
void Foam::meshToMesh::mapAndOpSrcToTgt
(
const AMIPatchToPatchInterpolation& AMI,
const Field<sphericalTensor>& srcField,
Field<sphericalTensor>& tgtField,
const plusEqOp<sphericalTensor>& cop
) const
{}
template<>
void Foam::meshToMesh::mapAndOpSrcToTgt
(
const AMIPatchToPatchInterpolation& AMI,
const Field<symmTensor>& srcField,
Field<symmTensor>& tgtField,
const plusEqOp<symmTensor>& cop
) const
{}
template<>
void Foam::meshToMesh::mapAndOpSrcToTgt
(
const AMIPatchToPatchInterpolation& AMI,
const Field<tensor>& srcField,
Field<tensor>& tgtField,
const plusEqOp<tensor>& cop
) const
{}
template<>
void Foam::meshToMesh::mapAndOpTgtToSrc
(
const AMIPatchToPatchInterpolation& AMI,
Field<scalar>& srcField,
const Field<scalar>& tgtField,
const plusEqOp<scalar>& cop
) const
{}
template<>
void Foam::meshToMesh::mapAndOpTgtToSrc
(
const AMIPatchToPatchInterpolation& AMI,
Field<vector>& srcField,
const Field<vector>& tgtField,
const plusEqOp<vector>& cop
) const
{}
template<>
void Foam::meshToMesh::mapAndOpTgtToSrc
(
const AMIPatchToPatchInterpolation& AMI,
Field<sphericalTensor>& srcField,
const Field<sphericalTensor>& tgtField,
const plusEqOp<sphericalTensor>& cop
) const
{}
template<>
void Foam::meshToMesh::mapAndOpTgtToSrc
(
const AMIPatchToPatchInterpolation& AMI,
Field<symmTensor>& srcField,
const Field<symmTensor>& tgtField,
const plusEqOp<symmTensor>& cop
) const
{}
template<>
void Foam::meshToMesh::mapAndOpTgtToSrc
(
const AMIPatchToPatchInterpolation& AMI,
Field<tensor>& srcField,
const Field<tensor>& tgtField,
const plusEqOp<tensor>& cop
) const
{}
Foam::labelList Foam::meshToMesh::maskCells
(
const polyMesh& src,
@ -443,7 +553,11 @@ void Foam::meshToMesh::constructNoCuttingPatches
forAll(srcBM, patchi)
{
const polyPatch& pp = srcBM[patchi];
if (!polyPatch::constraintType(pp.type()))
// We want to map all the global patches, including constraint
// patches (since they might have mappable properties, e.g.
// jumpCyclic). We'll fix the value afterwards.
if (!isA<processorPolyPatch>(pp))
{
srcPatchID.append(pp.index());

View File

@ -129,6 +129,28 @@ private:
template<class Type>
void add(UList<Type>& fld, const label offset) const;
//- Helper function to interpolate patch field. Template
// specialisations below
template<class Type, class CombineOp>
void mapAndOpSrcToTgt
(
const AMIPatchToPatchInterpolation& AMI,
const Field<Type>& srcField,
Field<Type>& tgtField,
const CombineOp& cop
) const;
//- Helper function to interpolate patch field. Template
// specialisations below
template<class Type, class CombineOp>
void mapAndOpTgtToSrc
(
const AMIPatchToPatchInterpolation& AMI,
Field<Type>& srcField,
const Field<Type>& tgtField,
const CombineOp& cop
) const;
//- Return src cell IDs for the overlap region
labelList maskCells(const polyMesh& src, const polyMesh& tgt) const;
@ -524,6 +546,91 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Disable fvPatchField value override after rmap
template<>
void meshToMesh::mapAndOpSrcToTgt
(
const AMIPatchToPatchInterpolation& AMI,
const Field<scalar>& srcField,
Field<scalar>& tgtField,
const plusEqOp<scalar>& cop
) const;
template<>
void meshToMesh::mapAndOpSrcToTgt
(
const AMIPatchToPatchInterpolation& AMI,
const Field<vector>& srcField,
Field<vector>& tgtField,
const plusEqOp<vector>& cop
) const;
template<>
void meshToMesh::mapAndOpSrcToTgt
(
const AMIPatchToPatchInterpolation& AMI,
const Field<sphericalTensor>& srcField,
Field<sphericalTensor>& tgtField,
const plusEqOp<sphericalTensor>& cop
) const;
template<>
void meshToMesh::mapAndOpSrcToTgt
(
const AMIPatchToPatchInterpolation& AMI,
const Field<symmTensor>& srcField,
Field<symmTensor>& tgtField,
const plusEqOp<symmTensor>& cop
) const;
template<>
void meshToMesh::mapAndOpSrcToTgt
(
const AMIPatchToPatchInterpolation& AMI,
const Field<tensor>& srcField,
Field<tensor>& tgtField,
const plusEqOp<tensor>& cop
) const;
template<>
void meshToMesh::mapAndOpTgtToSrc
(
const AMIPatchToPatchInterpolation& AMI,
Field<scalar>& srcField,
const Field<scalar>& tgtField,
const plusEqOp<scalar>& cop
) const;
template<>
void meshToMesh::mapAndOpTgtToSrc
(
const AMIPatchToPatchInterpolation& AMI,
Field<vector>& srcField,
const Field<vector>& tgtField,
const plusEqOp<vector>& cop
) const;
template<>
void meshToMesh::mapAndOpTgtToSrc
(
const AMIPatchToPatchInterpolation& AMI,
Field<sphericalTensor>& srcField,
const Field<sphericalTensor>& tgtField,
const plusEqOp<sphericalTensor>& cop
) const;
template<>
void meshToMesh::mapAndOpTgtToSrc
(
const AMIPatchToPatchInterpolation& AMI,
Field<symmTensor>& srcField,
const Field<symmTensor>& tgtField,
const plusEqOp<symmTensor>& cop
) const;
template<>
void meshToMesh::mapAndOpTgtToSrc
(
const AMIPatchToPatchInterpolation& AMI,
Field<tensor>& srcField,
const Field<tensor>& tgtField,
const plusEqOp<tensor>& cop
) const;
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -27,7 +27,7 @@ License
#include "volFields.H"
#include "directFvPatchFieldMapper.H"
#include "calculatedFvPatchField.H"
#include "weightedFvPatchFieldMapper.H"
#include "distributedWeightedFvPatchFieldMapper.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -317,6 +317,27 @@ Foam::tmp<Foam::Field<Type>> Foam::meshToMesh::mapTgtToSrc
}
template<class Type, class CombineOp>
void Foam::meshToMesh::mapAndOpSrcToTgt
(
const AMIPatchToPatchInterpolation& AMI,
const Field<Type>& srcField,
Field<Type>& tgtField,
const CombineOp& cop
) const
{
tgtField = pTraits<Type>::zero;
AMI.interpolateToTarget
(
srcField,
multiplyWeightedOp<Type, CombineOp>(cop),
tgtField,
UList<Type>::null()
);
}
template<class Type, class CombineOp>
void Foam::meshToMesh::mapSrcToTgt
(
@ -340,40 +361,35 @@ void Foam::meshToMesh::mapSrcToTgt
const fvPatchField<Type>& srcField = field.boundaryField()[srcPatchi];
fvPatchField<Type>& tgtField = resultBf[tgtPatchi];
// 2.3 does not do distributed mapping yet so only do if
// running on single processor
if (AMIList[i].singlePatchProc() != -1)
{
// Clone and map (since rmap does not do general mapping)
tmp<fvPatchField<Type>> tnewTgt
(
fvPatchField<Type>::New
(
srcField,
tgtField.patch(),
result(),
weightedFvPatchFieldMapper
(
AMIList[i].tgtAddress(),
AMIList[i].tgtWeights()
)
)
);
// Transfer all mapped quantities (value and e.g. gradient) onto
// tgtField. Value will get overwritten below.
tgtField.rmap(tnewTgt(), identity(tgtField.size()));
}
tgtField == Type(Zero);
AMIList[i].interpolateToTarget
// Clone and map (since rmap does not do general mapping)
tmp<fvPatchField<Type>> tnewTgt
(
srcField,
multiplyWeightedOp<Type, CombineOp>(cop),
tgtField,
UList<Type>::null()
fvPatchField<Type>::New
(
srcField,
tgtField.patch(),
result(),
distributedWeightedFvPatchFieldMapper
(
AMIList[i].singlePatchProc(),
(
AMIList[i].singlePatchProc() == -1
? &AMIList[i].srcMap()
: NULL
),
AMIList[i].tgtAddress(),
AMIList[i].tgtWeights()
)
)
);
// Transfer all mapped quantities (value and e.g. gradient) onto
// tgtField. Value will get overwritten below.
tgtField.rmap(tnewTgt(), identity(tgtField.size()));
// Override value to account for CombineOp (note: is dummy template
// specialisation for plusEqOp)
mapAndOpSrcToTgt(AMIList[i], srcField, tgtField, cop);
}
forAll(cuttingPatches_, i)
@ -403,7 +419,7 @@ Foam::meshToMesh::mapSrcToTgt
PtrList<fvPatchField<Type>> tgtPatchFields(tgtBm.size());
// constuct tgt boundary patch types as copy of 'field' boundary types
// 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
forAll(tgtPatchID_, i)
@ -509,6 +525,27 @@ Foam::meshToMesh::mapSrcToTgt
}
template<class Type, class CombineOp>
void Foam::meshToMesh::mapAndOpTgtToSrc
(
const AMIPatchToPatchInterpolation& AMI,
Field<Type>& srcField,
const Field<Type>& tgtField,
const CombineOp& cop
) const
{
srcField = pTraits<Type>::zero;
AMI.interpolateToSource
(
tgtField,
multiplyWeightedOp<Type, CombineOp>(cop),
srcField,
UList<Type>::null()
);
}
template<class Type, class CombineOp>
void Foam::meshToMesh::mapTgtToSrc
(
@ -529,40 +566,37 @@ void Foam::meshToMesh::mapTgtToSrc
fvPatchField<Type>& srcField = result.boundaryField()[srcPatchi];
const fvPatchField<Type>& tgtField = field.boundaryField()[tgtPatchi];
// 2.3 does not do distributed mapping yet so only do if
// running on single processor
if (AMIList[i].singlePatchProc() != -1)
{
// Clone and map (since rmap does not do general mapping)
tmp<fvPatchField<Type>> tnewSrc
(
fvPatchField<Type>::New
(
tgtField,
srcField.patch(),
result(),
weightedFvPatchFieldMapper
(
AMIList[i].srcAddress(),
AMIList[i].srcWeights()
)
)
);
// Transfer all mapped quantities (value and e.g. gradient) onto
// srcField. Value will get overwritten below
srcField.rmap(tnewSrc(), identity(srcField.size()));
}
srcField == Type(Zero);
AMIList[i].interpolateToSource
// Clone and map (since rmap does not do general mapping)
tmp<fvPatchField<Type>> tnewSrc
(
tgtField,
multiplyWeightedOp<Type, CombineOp>(cop),
srcField,
UList<Type>::null()
fvPatchField<Type>::New
(
tgtField,
srcField.patch(),
result(),
distributedWeightedFvPatchFieldMapper
(
AMIList[i].singlePatchProc(),
(
AMIList[i].singlePatchProc() == -1
? &AMIList[i].tgtMap()
: NULL
),
AMIList[i].srcAddress(),
AMIList[i].srcWeights()
)
)
);
// Transfer all mapped quantities (value and e.g. gradient) onto
// srcField. Value will get overwritten below
srcField.rmap(tnewSrc(), identity(srcField.size()));
// Override value to account for CombineOp (could be dummy for
// plusEqOp)
mapAndOpTgtToSrc(AMIList[i], srcField, tgtField, cop);
}
forAll(cuttingPatches_, i)