Compare commits

...

6 Commits

Author SHA1 Message Date
Andrew Heather
1307c4eb2e ENH: Propagated AMI API code changes across dependant code 2024-05-03 17:26:00 +01:00
Andrew Heather
de8dd7a5cf WIP: AMI - knock out connections with invalid interpolated delta vectors 2024-05-03 17:13:23 +01:00
Andrew Heather
a083ebb7bf ENH: AMI - propagate lowWeightOption 2024-05-03 17:08:01 +01:00
Andrew Heather
279abca7fa ENH: cyclicAMI - enable user to select low-weight correction
Example

    lowWeightOption assign;

Options:

- none   : no-op
- assign : set value when sum of weights < threshold (same as v2312) [DEFAULT]
- blend  : linear blend of AMI interpolated value plus (1 - sum_of_weights)
           times (supplied) default value
2024-05-03 16:37:33 +01:00
Andrew Heather
8c89c8f417 ENH: Refactored low-level AMI code to use new field-based ops 2024-05-03 16:10:52 +01:00
Andrew Heather
e44184e626 ENH: AMI - added new set of field-based AMI operations 2024-05-03 16:06:22 +01:00
27 changed files with 1165 additions and 516 deletions

View File

@ -44,6 +44,7 @@ Foam::cyclicAMIFvPatchField<Type>::cyclicAMIFvPatchField
cyclicAMILduInterfaceField(),
coupledFvPatchField<Type>(p, iF),
cyclicAMIPatch_(refCast<const cyclicAMIFvPatch>(p)),
lowWeightOption_(lowWeightCorrectionBase::option::ASSIGN),
patchNeighbourFieldPtr_(nullptr)
{}
@ -59,6 +60,15 @@ Foam::cyclicAMIFvPatchField<Type>::cyclicAMIFvPatchField
cyclicAMILduInterfaceField(),
coupledFvPatchField<Type>(p, iF, dict, IOobjectOption::NO_READ),
cyclicAMIPatch_(refCast<const cyclicAMIFvPatch>(p, dict)),
lowWeightOption_
(
lowWeightCorrectionBase::optionNames_.getOrDefault
(
"lowWeightOption",
dict,
lowWeightCorrectionBase::option::ASSIGN
)
),
patchNeighbourFieldPtr_(nullptr)
{
if (!isA<cyclicAMIFvPatch>(p))
@ -114,6 +124,7 @@ Foam::cyclicAMIFvPatchField<Type>::cyclicAMIFvPatchField
cyclicAMILduInterfaceField(),
coupledFvPatchField<Type>(ptf, p, iF, mapper),
cyclicAMIPatch_(refCast<const cyclicAMIFvPatch>(p)),
lowWeightOption_(ptf.lowWeightOption_),
patchNeighbourFieldPtr_(nullptr)
{
//if (ptf.patchNeighbourFieldPtr_ && cacheNeighbourField())
@ -152,6 +163,7 @@ Foam::cyclicAMIFvPatchField<Type>::cyclicAMIFvPatchField
cyclicAMILduInterfaceField(),
coupledFvPatchField<Type>(ptf),
cyclicAMIPatch_(ptf.cyclicAMIPatch_),
lowWeightOption_(ptf.lowWeightOption_),
patchNeighbourFieldPtr_(nullptr)
{
if (debug && !ptf.all_ready())
@ -173,6 +185,7 @@ Foam::cyclicAMIFvPatchField<Type>::cyclicAMIFvPatchField
cyclicAMILduInterfaceField(),
coupledFvPatchField<Type>(ptf, iF),
cyclicAMIPatch_(ptf.cyclicAMIPatch_),
lowWeightOption_(ptf.lowWeightOption_),
patchNeighbourFieldPtr_(nullptr)
{
if (debug && !ptf.all_ready())
@ -298,7 +311,8 @@ Foam::cyclicAMIFvPatchField<Type>::patchNeighbourField
defaultValues = Field<Type>(iField, cyclicAMIPatch_.faceCells());
}
tmp<Field<Type>> tpnf = cyclicAMIPatch_.interpolate(pnf, defaultValues);
tmp<Field<Type>> tpnf =
cyclicAMIPatch_.interpolate(pnf, defaultValues, lowWeightOption_);
if (doTransform())
{
@ -526,7 +540,8 @@ void Foam::cyclicAMIFvPatchField<Type>::evaluate
Field<Type>::null(), // Not used for distributed
recvRequests_,
recvBufs_,
defaultValues
defaultValues,
lowWeightOption_
).ptr()
);
@ -652,7 +667,8 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
solveScalarField::null(), // Not used for distributed
recvRequests_,
scalarRecvBufs_,
defaultValues
defaultValues,
lowWeightOption_
);
// Receive requests all handled by last function call
@ -674,7 +690,7 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
// Transform according to the transformation tensors
transformCoupleField(pnf, cmpt);
pnf = cyclicAMIPatch_.interpolate(pnf, defaultValues);
pnf = cyclicAMIPatch_.interpolate(pnf, defaultValues, lowWeightOption_);
}
// Multiply the field by coefficients and add into the result
@ -786,7 +802,8 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
Field<Type>::null(), // Not used for distributed
recvRequests_,
recvBufs_,
defaultValues
defaultValues,
lowWeightOption_
);
// Receive requests all handled by last function call
@ -808,7 +825,7 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
defaultValues = Field<Type>(psiInternal, faceCells);
}
pnf = cyclicAMIPatch_.interpolate(pnf, defaultValues);
pnf = cyclicAMIPatch_.interpolate(pnf, defaultValues, lowWeightOption_);
}
// Multiply the field by coefficients and add into the result
@ -994,6 +1011,12 @@ void Foam::cyclicAMIFvPatchField<Type>::write(Ostream& os) const
{
patchNeighbourFieldPtr_->writeEntry("neighbourValue", os);
}
os.writeEntry
(
"lowWeightOption",
lowWeightCorrectionBase::optionNames_[lowWeightOption_]
);
}

View File

@ -71,6 +71,7 @@ SourceFiles
#include "cyclicAMIFvPatch.H"
#include "coupledFvPatchField.H"
#include "cyclicAMILduInterfaceField.H"
#include "lowWeightCorrectionBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -92,6 +93,10 @@ class cyclicAMIFvPatchField
//- Local reference cast into the cyclic patch
const cyclicAMIFvPatch& cyclicAMIPatch_;
//- Low weight correction mode
// Default: assign (same as v2312 and earlier)
lowWeightCorrectionBase::option lowWeightOption_;
// Sending and receiving (distributed AMI)

View File

@ -29,6 +29,7 @@ License
#include "addToRunTimeSelectionTable.H"
#include "faceAreaWeightAMI.H"
#include "turbulentDFSEMInletFvPatchVectorField.H"
#include "AMIFieldOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -82,14 +83,8 @@ void Foam::turbulentDigitalFilterInletFvPatchField<Type>::mapL
}
// Map two-point correlations (integral scales)
plusEqOp<Type> cop;
AMIPtr_->interpolateToSource
(
sourceFld,
multiplyWeightedOp<Type, plusEqOp<Type>>(cop),
fld,
UList<Type>::null()
);
AMIMultiplyWeightedOp<Type> cop(AMIPtr_(), true);
AMIPtr_->interpolate(sourceFld, cop, fld, UList<Type>::null());
// Map forward-stepwise method correlations if requested
if (L_.fsm())

View File

@ -100,12 +100,19 @@ void Foam::cyclicACMIFvPatch::makeWeights(scalarField& w) const
// These deltas are of the cyclic part alone - they are
// not affected by the amount of overlap with the nonOverlapPatch
scalarField nbrDeltas
scalarField nbrDeltas;
const auto& AMI = owner() ? this->AMI() : nbrPatch.AMI();
// Multiply-weighted op - no low weight correction
auto cop = AMIMultiplyWeightedOp<scalar>(AMI, owner());
AMI.interpolate
(
interpolate
(
nbrPatch.nf() & nbrPatch.coupledFvPatch::delta()
)
(nbrPatch.nf() & nbrPatch.coupledFvPatch::delta())(),
cop,
nbrDeltas,
UList<scalar>()
);
const scalar tol = cyclicACMIPolyPatch::tolerance();
@ -244,31 +251,35 @@ Foam::tmp<Foam::vectorField> Foam::cyclicACMIFvPatch::delta() const
const vectorField patchD(coupledFvPatch::delta());
vectorField nbrPatchD(interpolate(nbrPatch.coupledFvPatch::delta()));
const auto& AMI = owner() ? this->AMI() : nbrPatch.AMI();
// Multiply-weighted op - no low weight correction
auto cop = AMIMultiplyWeightedOp<vector>(AMI, owner());
vectorField nbrPatchD;
AMI.interpolate
(
nbrPatch.coupledFvPatch::delta()(),
cop,
nbrPatchD,
UList<vector>()
);
// Do the transformation if necessary
if (!parallel())
{
transform(nbrPatchD, forwardT()[0], nbrPatchD);
}
auto tpdv = tmp<vectorField>::New(patchD.size());
vectorField& pdv = tpdv.ref();
// do the transformation if necessary
if (parallel())
forAll(patchD, facei)
{
forAll(patchD, facei)
{
const vector& ddi = patchD[facei];
const vector& dni = nbrPatchD[facei];
pdv[facei] = ddi - dni;
}
}
else
{
forAll(patchD, facei)
{
const vector& ddi = patchD[facei];
const vector& dni = nbrPatchD[facei];
pdv[facei] = ddi - transform(forwardT()[0], dni);
}
const vector& ddi = patchD[facei];
const vector& dni = nbrPatchD[facei];
pdv[facei] = ddi - dni;
pdv[facei] = ddi - dni;
}
return tpdv;

View File

@ -251,7 +251,7 @@ public:
localFld,
requests,
recvBuffers,
UList<Type>()
UList<Type>::null()
);
}

View File

@ -97,32 +97,50 @@ void Foam::cyclicAMIFvPatch::makeWeights(scalarField& w) const
{
const cyclicAMIFvPatch& nbrPatch = neighbFvPatch();
const scalarField deltas(nf() & coupledFvPatch::delta());
const auto& AMI = owner() ? this->AMI() : nbrPatch.AMI();
tmp<scalarField> tnbrDeltas;
auto tnbrDeltas = tmp<scalarField>::New();
if (applyLowWeightCorrection())
{
tnbrDeltas =
interpolate
(
nbrPatch.nf() & nbrPatch.coupledFvPatch::delta(),
scalarField(this->size(), 1.0)
);
// Use 'assign' correction for geometric interpolation
auto cop = AMICorrectedMultiplyWeightedOp<scalar>
(
AMI,
owner(),
lowWeightCorrectionBase::option::ASSIGN
);
// Faces with invalid interpolation weights converted to one-sided
AMI.interpolate
(
(nbrPatch.nf() & nbrPatch.coupledFvPatch::delta())(),
cop,
tnbrDeltas.ref(),
scalarList(this->size(), 1.0)
);
}
else
{
tnbrDeltas =
interpolate(nbrPatch.nf() & nbrPatch.coupledFvPatch::delta());
// Multiply-weighted op - no low weight correction
auto cop = AMIMultiplyWeightedOp<scalar>(AMI, owner());
AMI.interpolate
(
(nbrPatch.nf() & nbrPatch.coupledFvPatch::delta())(),
cop,
tnbrDeltas.ref(),
UList<scalar>::null()
);
}
const scalarField& nbrDeltas = tnbrDeltas();
const scalarField deltas(nf() & coupledFvPatch::delta());
forAll(deltas, facei)
{
// Note use of mag
scalar di = mag(deltas[facei]);
scalar dni = mag(nbrDeltas[facei]);
w[facei] = dni/(di + dni);
}
}
@ -162,46 +180,58 @@ Foam::tmp<Foam::vectorField> Foam::cyclicAMIFvPatch::delta() const
{
const vectorField patchD(coupledFvPatch::delta());
tmp<vectorField> tnbrPatchD;
const auto& AMI = owner() ? this->AMI() : nbrPatch.AMI();
auto tnbrPatchD = tmp<vectorField>::New();
if (applyLowWeightCorrection())
{
tnbrPatchD =
interpolate
(
nbrPatch.coupledFvPatch::delta(),
vectorField(this->size(), Zero)
);
// Use 'assign' correction for geometric interpolation
auto cop = AMICorrectedMultiplyWeightedOp<vector>
(
AMI,
owner(),
lowWeightCorrectionBase::option::ASSIGN
);
// Faces with invalid interpolation weights converted to one-sided
AMI.interpolate
(
nbrPatch.coupledFvPatch::delta()(),
cop,
tnbrPatchD.ref(),
vectorField(this->size(), Zero)
);
}
else
{
tnbrPatchD = interpolate(nbrPatch.coupledFvPatch::delta());
// Multiply-weighted op - no low weight correction
auto cop = AMIMultiplyWeightedOp<vector>(AMI, owner());
AMI.interpolate
(
nbrPatch.coupledFvPatch::delta()(),
cop,
tnbrPatchD.ref(),
UList<vector>::null()
);
}
const vectorField& nbrPatchD = tnbrPatchD();
vectorField& nbrPatchD = tnbrPatchD.ref();
// Do the transformation if necessary
if (!parallel())
{
transform(nbrPatchD, forwardT()[0], nbrPatchD);
}
auto tpdv = tmp<vectorField>::New(patchD.size());
vectorField& pdv = tpdv.ref();
// do the transformation if necessary
if (parallel())
forAll(patchD, facei)
{
forAll(patchD, facei)
{
const vector& ddi = patchD[facei];
const vector& dni = nbrPatchD[facei];
pdv[facei] = ddi - dni;
}
}
else
{
forAll(patchD, facei)
{
const vector& ddi = patchD[facei];
const vector& dni = nbrPatchD[facei];
pdv[facei] = ddi - transform(forwardT()[0], dni);
}
const vector& ddi = patchD[facei];
const vector& dni = nbrPatchD[facei];
pdv[facei] = ddi - dni;
}
return tpdv;

View File

@ -217,20 +217,34 @@ public:
tmp<Field<Type>> interpolate
(
const Field<Type>& fld,
const UList<Type>& defaultValues = UList<Type>()
const UList<Type>& defaultValues = UList<Type>::null(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const
{
return cyclicAMIPolyPatch_.interpolate(fld, defaultValues);
return cyclicAMIPolyPatch_.interpolate
(
fld,
defaultValues,
lwOption
);
}
template<class Type>
tmp<Field<Type>> interpolate
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues = UList<Type>()
const UList<Type>& defaultValues = UList<Type>::null(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const
{
return cyclicAMIPolyPatch_.interpolate(tFld, defaultValues);
return cyclicAMIPolyPatch_.interpolate
(
tFld,
defaultValues,
lwOption
);
}

View File

@ -0,0 +1,114 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
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::AMIFieldOP
Description
General template for AMI field operations
\*---------------------------------------------------------------------------*/
#ifndef AMIFieldOp_H
#define AMIFieldOp_H
#include "AMIFieldOpBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class AMIFieldOp Declaration
\*---------------------------------------------------------------------------*/
template<class Type, class CombineOp>
class AMIFieldOp
:
public AMIFieldOpBase
{
// Private Data
//- Combine operator, e.g. plusEqOp<Type>()
// Note: must be null-constructed
CombineOp cop_;
public:
typedef Type value_type;
//- Constructor
AMIFieldOp(const AMIInterpolation& ami, bool toSource)
:
AMIFieldOpBase(ami, toSource),
cop_()
{}
//- Destructor
~AMIFieldOp() = default;
//- Apply the op
// Note: does not use default values
void operator()
(
List<value_type>& result,
const UList<value_type>& fld,
const UList<value_type>& /* unused defaultValues */
) const
{
const auto& address = this->address();
forAll(result, facei)
{
const labelList& faceSlots = address[facei];
forAll(faceSlots, i)
{
if (i == 0)
{
result[facei] = fld[faceSlots[i]];
}
else
{
cop_(result[facei], fld[faceSlots[i]]);
}
}
}
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,105 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
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::AMIFieldOpBase
Description
Base class for AMI field operations
\*---------------------------------------------------------------------------*/
#ifndef AMIFieldOpsBase_H
#define AMIFieldOpsBase_H
#include "AMIInterpolation.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class AMIFieldOpBase Declaration
\*---------------------------------------------------------------------------*/
class AMIFieldOpBase
{
protected:
//- Reference to the AMI
const AMIInterpolation& ami_;
//- Interpolation to source; false=interpolate to target
const bool toSource_;
public:
//- Constructor
AMIFieldOpBase(const AMIInterpolation& ami, const bool toSource)
:
ami_(ami),
toSource_(toSource)
{}
// Member Functions
//- Return the 'toSource' flag
bool toSource() const
{
return toSource_;
}
//- Return the AMI addressing
const labelListList& address() const
{
return toSource_ ? ami_.srcAddress() : ami_.tgtAddress();
}
//- Return the AMI weights
const scalarListList& weights() const
{
return toSource_ ? ami_.srcWeights() : ami_.tgtWeights();
}
//- Return the AMI sum of weights
const scalarList& weightsSum() const
{
return toSource_ ? ami_.srcWeightsSum() : ami_.tgtWeightsSum();
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,58 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
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/>.
\*---------------------------------------------------------------------------*/
#ifndef AMIFieldOps_H
#define AMIFieldOps_H
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "ops.H"
#include "AMIFieldOp.H"
#include "AMIMultiplyWeightedOp.H"
#include "LowWeightCorrection.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
template<class Type>
using AMIMaxOp = AMIFieldOp<Type, maxEqOp<Type>>;
template<class Type>
using AMIMinOp = AMIFieldOp<Type, minEqOp<Type>>;
template<class Type>
using AMICorrectedMultiplyWeightedOp =
LowWeightCorrection<AMIMultiplyWeightedOp<Type>, plusEqOp<Type>>;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,112 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
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/>.
\*---------------------------------------------------------------------------*/
#ifndef AMIMultiplyWeightedOp_H
#define AMIMultiplyWeightedOp_H
#include "AMIFieldOpBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class AMIMultiplyWeightedOp Declaration
\*---------------------------------------------------------------------------*/
template<class Type, class CombineOp = plusEqOp<Type>>
class AMIMultiplyWeightedOp
:
public AMIFieldOpBase
{
// Private Data
//- Combine operator, e.g. plusEqOp<Type>()
// Note: must be null-constructed
CombineOp cop_;
public:
typedef Type value_type;
//- Constructor
AMIMultiplyWeightedOp
(
const AMIInterpolation& ami,
const bool toSource
)
:
AMIFieldOpBase(ami, toSource),
cop_()
{}
//- Multiply-weighted op
// Note: does not use default values
void operator()
(
List<value_type>& result,
const UList<value_type>& fld,
const UList<value_type>& /* unused defaultValues */
) const
{
const auto& address = this->address();
const auto& weights = this->weights();
forAll(result, facei)
{
const labelList& faceSlots = address[facei];
const scalarList& faceWeights = weights[facei];
forAll(faceSlots, i)
{
if (i == 0)
{
result[facei] = faceWeights[i]*fld[faceSlots[i]];
}
else
{
cop_(result[facei], faceWeights[i]*fld[faceSlots[i]]);
}
}
}
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,176 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
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::LowWeightCorrection
Description
Wrapper around the AMI field op
\*---------------------------------------------------------------------------*/
#ifndef LowWeightCorrection_H
#define LowWeightCorrection_H
#include "lowWeightCorrectionBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class LowWeightCorrection Declaration
\*---------------------------------------------------------------------------*/
template<class AMIOpType, class CombineOp>
class LowWeightCorrection
:
public lowWeightCorrectionBase,
public AMIOpType
{
typedef typename AMIOpType::value_type value_type;
public:
//- Constructor
LowWeightCorrection
(
const AMIInterpolation& ami,
const bool toSource,
const lowWeightCorrectionBase::option& opt =
lowWeightCorrectionBase::option::NONE
)
:
lowWeightCorrectionBase(opt),
AMIOpType(ami, toSource)
{}
// Member Functions
//- Helper function to ensure default value field is valid
bool validDefaults(const UList<value_type>& defaultValues) const
{
const auto& ami = AMIOpType::ami_;
if (ami.lowWeightCorrection() > 0)
{
const auto& weightsSum = this->weightsSum();
if (defaultValues.size() != weightsSum.size())
{
FatalErrorInFunction
<< "Employing default values when sum of weights "
<< "falls below " << ami.lowWeightCorrection()
<< " but number of default values is not equal to "
<< "addressing size" << nl
<< " default values size = "
<< defaultValues.size() << nl
<< " addressing size = "
<< weightsSum.size() << nl
<< abort(FatalError);
}
return true;
}
return false;
}
//- Correction operator
void operator()
(
List<value_type>& result,
const UList<value_type>& fld,
const UList<value_type>& defaultValues
) const
{
// Apply AMI interpolator
AMIOpType::operator()(result, fld, UList<value_type>::null());
if (!validDefaults(defaultValues)) return;
switch (opt_)
{
case option::NONE:
{
break;
}
case option::ASSIGN:
{
const auto& ami = AMIOpType::ami_;
const auto& weightsSum = this->weightsSum();
forAll(result, facei)
{
if (weightsSum[facei] < ami.lowWeightCorrection())
{
// Assign default value
result[facei] = defaultValues[facei];
}
}
break;
}
case option::BLEND:
{
const auto& ami = AMIOpType::ami_;
const auto& weightsSum = this->weightsSum();
forAll(result, facei)
{
if (weightsSum[facei] < ami.lowWeightCorrection())
{
// Already have 'weightSum' contribution in result
// - blend 'missing' contribution into result
const scalar w = min(1, max(0, weightsSum[facei]));
result[facei] += (1 - w)*defaultValues[facei];
}
}
break;
}
default:
{
FatalErrorInFunction
<< "Unhandled enumeration " << static_cast<int>(opt_)
<< abort(FatalError);
}
}
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,49 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
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/>.
\*---------------------------------------------------------------------------*/
#include "lowWeightCorrectionBase.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::Enum<Foam::lowWeightCorrectionBase::option>
Foam::lowWeightCorrectionBase::optionNames_
({
{ option::NONE, "none" },
{ option::ASSIGN, "assign" },
{ option::BLEND, "blend" },
});
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::lowWeightCorrectionBase::lowWeightCorrectionBase(const option& opt)
:
opt_(opt)
{}
// ************************************************************************* //

View File

@ -0,0 +1,90 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
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::lowWeightCorrectionBase
Description
Base class for AMI low weight corrections
\*---------------------------------------------------------------------------*/
#ifndef lowWeightCorrectionBase_H
#define lowWeightCorrectionBase_H
#include "Enum.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class lowWeightCorrectionBase Declaration
\*---------------------------------------------------------------------------*/
class lowWeightCorrectionBase
{
public:
enum class option
{
NONE,
ASSIGN,
BLEND
};
static const Enum<option> optionNames_;
protected:
// Protected Data
//- Option
option opt_;
public:
//- Constructors
lowWeightCorrectionBase(const option& opt = option::NONE);
//- Destructor
~lowWeightCorrectionBase() = default;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1123,6 +1123,36 @@ void Foam::AMIInterpolation::normaliseWeights
}
void Foam::AMIInterpolation::removeSourceConnection(const label facei)
{
if (facei < 0 || facei > srcAddress_.size())
{
FatalErrorInFunction
<< "Face index " << facei << " out of bonds"
<< abort(FatalError);
}
srcWeightsSum_[facei] = 0;
srcWeights_[facei].clear();
srcAddress_[facei].clear();
}
void Foam::AMIInterpolation::removeTargetConnection(const label facei)
{
if (facei < 0 || facei > tgtAddress_.size())
{
FatalErrorInFunction
<< "Face index " << facei << " out of bonds"
<< abort(FatalError);
}
tgtWeightsSum_[facei] = 0;
tgtWeights_[facei].clear();
tgtAddress_[facei].clear();
}
Foam::label Foam::AMIInterpolation::srcPointFace
(
const primitivePatch& srcPatch,

View File

@ -61,7 +61,7 @@ SourceFiles
#include "indexedOctree.H"
#include "treeDataPrimitivePatch.H"
#include "runTimeSelectionTables.H"
#include "lowWeightCorrectionBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -512,39 +512,21 @@ public:
//- Normalise the weights
void normaliseWeights(const bool conformal, const bool output);
//- Remove source face connection
void removeSourceConnection(const label facei);
//- Remove target face connection
void removeTargetConnection(const label facei);
// Evaluation
// Low-level
//- Weighted sum of contributions
//- Interpolate with supplied op to combine existing value
//- with remote value and weight
template<class Type, class CombineOp>
static void weightedSum
(
const scalar lowWeightCorrection,
const labelListList& allSlots,
const scalarListList& allWeights,
const scalarField& weightsSum,
const UList<Type>& fld,
const CombineOp& cop,
List<Type>& result,
const UList<Type>& defaultValues
);
//- Weighted sum of contributions
template<class Type>
void weightedSum
(
const bool interpolateToSource,
const UList<Type>& fld,
List<Type>& result,
const UList<Type>& defaultValues
) const;
//- Interpolate from target to source with supplied op
//- to combine existing value with remote value and weight
template<class Type, class CombineOp>
void interpolateToSource
void interpolate
(
const UList<Type>& fld,
const CombineOp& cop,
@ -552,48 +534,18 @@ public:
const UList<Type>& defaultValues = UList<Type>::null()
) const;
//- Interpolate from source to target with supplied op
//- to combine existing value with remote value and weight
template<class Type, class CombineOp>
void interpolateToTarget
(
const UList<Type>& fld,
const CombineOp& cop,
List<Type>& result,
const UList<Type>& defaultValues = UList<Type>::null()
) const;
//- Interpolate from target to source with supplied op
//- Interpolate with supplied op
template<class Type, class CombineOp>
tmp<Field<Type>> interpolateToSource
tmp<Field<Type>> interpolate
(
const Field<Type>& fld,
const CombineOp& cop,
const UList<Type>& defaultValues = UList<Type>::null()
) const;
//- Interpolate from target tmp field to source with supplied op
//- Interpolate with supplied op
template<class Type, class CombineOp>
tmp<Field<Type>> interpolateToSource
(
const tmp<Field<Type>>& tFld,
const CombineOp& cop,
const UList<Type>& defaultValues = UList<Type>::null()
) const;
//- Interpolate from source to target with supplied op
template<class Type, class CombineOp>
tmp<Field<Type>> interpolateToTarget
(
const Field<Type>& fld,
const CombineOp& cop,
const UList<Type>& defaultValues = UList<Type>::null()
) const;
//- Interpolate from source tmp field to target with supplied op
template<class Type, class CombineOp>
tmp<Field<Type>> interpolateToTarget
tmp<Field<Type>> interpolate
(
const tmp<Field<Type>>& tFld,
const CombineOp& cop,
@ -605,7 +557,9 @@ public:
tmp<Field<Type>> interpolateToSource
(
const Field<Type>& fld,
const UList<Type>& defaultValues = UList<Type>::null()
const UList<Type>& defaultValues = UList<Type>::null(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;
//- Interpolate from target tmp field
@ -613,7 +567,9 @@ public:
tmp<Field<Type>> interpolateToSource
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues = UList<Type>::null()
const UList<Type>& defaultValues = UList<Type>::null(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;
//- Interpolate from source to target
@ -621,7 +577,9 @@ public:
tmp<Field<Type>> interpolateToTarget
(
const Field<Type>& fld,
const UList<Type>& defaultValues = UList<Type>::null()
const UList<Type>& defaultValues = UList<Type>::null(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;
//- Interpolate from source tmp field
@ -629,7 +587,9 @@ public:
tmp<Field<Type>> interpolateToTarget
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues = UList<Type>::null()
const UList<Type>& defaultValues = UList<Type>::null(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;

View File

@ -28,266 +28,80 @@ License
#include "profiling.H"
#include "mapDistribute.H"
#include "AMIFieldOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type, class CombineOp>
void Foam::AMIInterpolation::weightedSum
void Foam::AMIInterpolation::interpolate
(
const scalar lowWeightCorrection,
const labelListList& allSlots,
const scalarListList& allWeights,
const scalarField& weightsSum,
const UList<Type>& fld,
const CombineOp& cop,
List<Type>& result,
const UList<Type>& defaultValues
)
) const
{
if (lowWeightCorrection > 0)
{
forAll(result, facei)
{
if (weightsSum[facei] < lowWeightCorrection)
{
result[facei] = defaultValues[facei];
}
else
{
const labelList& slots = allSlots[facei];
const scalarList& weights = allWeights[facei];
addProfiling(ami, "AMIInterpolation::interpolate");
forAll(slots, i)
{
cop(result[facei], facei, fld[slots[i]], weights[i]);
}
}
}
label inSize = cop.toSource() ? tgtAddress_.size() : srcAddress_.size();
if (fld.size() != inSize)
{
FatalErrorInFunction
<< "Supplied field size is not equal to expected field size ("
<< inSize << ")" << nl
<< " source patch = " << srcAddress_.size() << nl
<< " target patch = " << tgtAddress_.size() << nl
<< " supplied field = " << fld.size()
<< abort(FatalError);
}
label outSize = cop.toSource() ? srcAddress_.size() : tgtAddress_.size();
result.resize_nocopy(outSize);
if (distributed())
{
const auto& map = cop.toSource() ? tgtMapPtr_() : srcMapPtr_();
List<Type> work = fld; // deep copy
map.distribute(work);
// Apply interpolation
cop(result, work, defaultValues);
}
else
{
forAll(result, facei)
{
const labelList& slots = allSlots[facei];
const scalarList& weights = allWeights[facei];
forAll(slots, i)
{
cop(result[facei], facei, fld[slots[i]], weights[i]);
}
}
// Apply interpolation
cop(result, fld, defaultValues);
}
}
template<class Type>
void Foam::AMIInterpolation::weightedSum
(
const bool interpolateToSource,
const UList<Type>& fld,
List<Type>& result,
const UList<Type>& defaultValues
) const
{
weightedSum
(
lowWeightCorrection_,
(interpolateToSource ? srcAddress_ : tgtAddress_),
(interpolateToSource ? srcWeights_ : tgtWeights_),
(interpolateToSource ? srcWeightsSum_ : tgtWeightsSum_),
fld,
multiplyWeightedOp<Type, plusEqOp<Type>>(plusEqOp<Type>()),
result,
defaultValues
);
}
template<class Type, class CombineOp>
void Foam::AMIInterpolation::interpolateToTarget
(
const UList<Type>& fld,
const CombineOp& cop,
List<Type>& result,
const UList<Type>& defaultValues
) const
{
addProfiling(ami, "AMIInterpolation::interpolateToTarget");
if (fld.size() != srcAddress_.size())
{
FatalErrorInFunction
<< "Supplied field size is not equal to source patch size" << nl
<< " source patch = " << srcAddress_.size() << nl
<< " target patch = " << tgtAddress_.size() << nl
<< " supplied field = " << fld.size()
<< abort(FatalError);
}
else if
(
(lowWeightCorrection_ > 0)
&& (defaultValues.size() != tgtAddress_.size())
)
{
FatalErrorInFunction
<< "Employing default values when sum of weights falls below "
<< lowWeightCorrection_
<< " but supplied default field size is not equal to target "
<< "patch size" << nl
<< " default values = " << defaultValues.size() << nl
<< " target patch = " << tgtAddress_.size() << nl
<< abort(FatalError);
}
result.setSize(tgtAddress_.size());
List<Type> work;
if (distributed())
{
const mapDistribute& map = srcMapPtr_();
work = fld; // deep copy
map.distribute(work);
}
weightedSum
(
lowWeightCorrection_,
tgtAddress_,
tgtWeights_,
tgtWeightsSum_,
(distributed() ? work : fld),
cop,
result,
defaultValues
);
}
template<class Type, class CombineOp>
void Foam::AMIInterpolation::interpolateToSource
(
const UList<Type>& fld,
const CombineOp& cop,
List<Type>& result,
const UList<Type>& defaultValues
) const
{
addProfiling(ami, "AMIInterpolation::interpolateToSource");
if (fld.size() != tgtAddress_.size())
{
FatalErrorInFunction
<< "Supplied field size is not equal to target patch size" << nl
<< " source patch = " << srcAddress_.size() << nl
<< " target patch = " << tgtAddress_.size() << nl
<< " supplied field = " << fld.size()
<< abort(FatalError);
}
else if
(
(lowWeightCorrection_ > 0)
&& (defaultValues.size() != srcAddress_.size())
)
{
FatalErrorInFunction
<< "Employing default values when sum of weights falls below "
<< lowWeightCorrection_
<< " but number of default values is not equal to source "
<< "patch size" << nl
<< " default values = " << defaultValues.size() << nl
<< " source patch = " << srcAddress_.size() << nl
<< abort(FatalError);
}
result.setSize(srcAddress_.size());
List<Type> work;
if (distributed())
{
const mapDistribute& map = tgtMapPtr_();
work = fld; // deep copy
map.distribute(work);
}
weightedSum
(
lowWeightCorrection_,
srcAddress_,
srcWeights_,
srcWeightsSum_,
(distributed() ? work : fld),
cop,
result,
defaultValues
);
}
template<class Type, class CombineOp>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToSource
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolate
(
const Field<Type>& fld,
const CombineOp& cop,
const UList<Type>& defaultValues
) const
{
auto tresult = tmp<Field<Type>>::New(srcAddress_.size(), Zero);
auto tresult = tmp<Field<Type>>::New();
interpolateToSource
(
fld,
multiplyWeightedOp<Type, CombineOp>(cop),
tresult.ref(),
defaultValues
);
interpolate(fld, cop, tresult.ref(), defaultValues);
return tresult;
}
template<class Type, class CombineOp>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToSource
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolate
(
const tmp<Field<Type>>& tFld,
const CombineOp& cop,
const UList<Type>& defaultValues
) const
{
return interpolateToSource(tFld(), cop, defaultValues);
}
template<class Type, class CombineOp>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToTarget
(
const Field<Type>& fld,
const CombineOp& cop,
const UList<Type>& defaultValues
) const
{
auto tresult = tmp<Field<Type>>::New(tgtAddress_.size(), Zero);
interpolateToTarget
(
fld,
multiplyWeightedOp<Type, CombineOp>(cop),
tresult.ref(),
defaultValues
);
return tresult;
}
template<class Type, class CombineOp>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToTarget
(
const tmp<Field<Type>>& tFld,
const CombineOp& cop,
const UList<Type>& defaultValues
) const
{
return interpolateToTarget(tFld(), cop, defaultValues);
return interpolate(tFld(), cop, defaultValues);
}
@ -295,10 +109,13 @@ template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToSource
(
const Field<Type>& fld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
return interpolateToSource(fld, plusEqOp<Type>(), defaultValues);
AMICorrectedMultiplyWeightedOp<Type> cop(*this, true, lwOption);
return interpolate(fld, cop, defaultValues);
}
@ -306,10 +123,11 @@ template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToSource
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
return interpolateToSource(tFld(), plusEqOp<Type>(), defaultValues);
return interpolateToSource(tFld(), defaultValues, lwOption);
}
@ -317,10 +135,13 @@ template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToTarget
(
const Field<Type>& fld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
return interpolateToTarget(fld, plusEqOp<Type>(), defaultValues);
AMICorrectedMultiplyWeightedOp<Type> cop(*this, false, lwOption);
return interpolate(fld, cop, defaultValues);
}
@ -328,10 +149,11 @@ template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToTarget
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
return interpolateToTarget(tFld(), plusEqOp<Type>(), defaultValues);
return interpolateToTarget(tFld(), defaultValues, lwOption);
}

View File

@ -292,14 +292,15 @@ void Foam::cyclicACMIGAMGInterfaceField::updateInterfaceMatrix
recvRequests_.clear();
solveScalarField pnf(faceCells.size(), Zero);
AMI.weightedSum
AMIMultiplyWeightedOp<solveScalar> cop
(
cyclicACMIInterface_.owner(),
work,
pnf, // result
solveScalarField::null()
AMI,
cyclicACMIInterface_.owner()
);
cop(pnf, work, solveScalarField::null());
// Add result using coefficients
this->addToInternalField(result, !add, faceCells, coeffs, pnf);
}

View File

@ -306,13 +306,14 @@ void Foam::cyclicAMIGAMGInterfaceField::updateInterfaceMatrix
recvRequests_.clear();
solveScalarField pnf(faceCells.size(), Zero);
AMI.weightedSum
// Note: no low-weight correction
AMIMultiplyWeightedOp<solveScalar> cop
(
cyclicAMIInterface_.owner(),
work,
pnf, // result
defaultValues
AMI,
cyclicAMIInterface_.owner()
);
cop(pnf, work, defaultValues);
// Add result using coefficients
this->addToInternalField(result, !add, faceCells, coeffs, pnf);
@ -329,13 +330,14 @@ void Foam::cyclicAMIGAMGInterfaceField::updateInterfaceMatrix
transformCoupleField(work, cmpt);
solveScalarField pnf(faceCells.size(), Zero);
AMI.weightedSum
// Note: no low-weight correction
AMIMultiplyWeightedOp<solveScalar> cop
(
cyclicAMIInterface_.owner(),
work,
pnf, // result
defaultValues
AMI,
cyclicAMIInterface_.owner()
);
cop(pnf, work, defaultValues);
// Add result using coefficients
this->addToInternalField(result, !add, faceCells, coeffs, pnf);

View File

@ -446,6 +446,54 @@ void Foam::cyclicAMIPolyPatch::resetAMI(const UList<point>& points) const
{
AMIPtr_->checkSymmetricWeights(true);
}
// Check connectivity
if (applyLowWeightCorrection() || !AMIPtr_->requireMatch())
{
Info<< "AMI: performing connectivity checks" << endl;
const auto& C = boundaryMesh().mesh().cellCentres();
auto cosTheta =
[&](const polyPatch& p1, const polyPatch& p2, const bool toSource)
{
const auto& Cf1 = p1.faceCentres();
const auto& faceCells1 = p1.faceCells();
vectorField delta1(p1.size());
forAll(delta1, i)
{
delta1[i] = Cf1[i] - C[faceCells1[i]];
}
// Interpolate nbr delta to local (src) side using (uncorrected)
// multiply-weighted op
const AMIMultiplyWeightedOp<vector> cop(*AMIPtr_, toSource);
AMIPtr_->interpolate(delta1, cop, UList<vector>::null());
delta1.normalise();
return delta1 & p2.faceNormals();
};
const scalarField ctSrc(cosTheta(*this, nbr, true));
forAll(ctSrc, facei)
{
if (ctSrc[facei] < 0)
{
AMIPtr_->removeSourceConnection(facei);
}
}
const scalarField ctTgt(cosTheta(nbr, *this, false));
forAll(ctTgt, facei)
{
if (ctTgt[facei] < 0)
{
AMIPtr_->removeTargetConnection(facei);
}
}
}
}

View File

@ -483,7 +483,9 @@ public:
tmp<Field<Type>> interpolate
(
const Field<Type>& fld,
const UList<Type>& defaultValues = UList<Type>()
const UList<Type>& defaultValues = UList<Type>(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;
//- Interpolate tmp field
@ -491,7 +493,9 @@ public:
tmp<Field<Type>> interpolate
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues = UList<Type>()
const UList<Type>& defaultValues = UList<Type>(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;
//- Interpolate without periodic
@ -499,7 +503,9 @@ public:
tmp<Field<Type>> interpolateUntransformed
(
const Field<Type>& fld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;
//- Low-level interpolate List
@ -541,7 +547,9 @@ public:
const Field<Type>& localFld,
const labelRange& requests, // The receive requests
const PtrList<List<Type>>& recvBuffers,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;

View File

@ -26,22 +26,30 @@ License
\*---------------------------------------------------------------------------*/
#include "AMIFieldOps.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolateUntransformed
(
const Field<Type>& fld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
if (owner())
{
return AMI().interpolateToSource(fld, defaultValues);
return AMI().interpolateToSource(fld, defaultValues, lwOption);
}
else
{
return neighbPatch().AMI().interpolateToTarget(fld, defaultValues);
return neighbPatch().AMI().interpolateToTarget
(
fld,
defaultValues,
lwOption
);
}
}
@ -50,7 +58,8 @@ template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
(
const Field<Type>& fld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
autoPtr<coordSystem::cylindrical> cs;
@ -65,7 +74,7 @@ Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
if (!cs)
{
return interpolateUntransformed(fld, defaultValues);
return interpolateUntransformed(fld, defaultValues, lwOption);
}
else
{
@ -141,7 +150,7 @@ Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
return Foam::transform
(
ownT,
interpolateUntransformed(localFld, localDeflt)
interpolateUntransformed(localFld, localDeflt, lwOption)
);
}
}
@ -151,10 +160,11 @@ template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
return interpolate(tFld(), defaultValues);
return interpolate(tFld(), defaultValues, lwOption);
}
@ -245,7 +255,8 @@ Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
const Field<Type>& localFld,
const labelRange& requests,
const PtrList<List<Type>>& recvBuffers,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI());
@ -272,13 +283,9 @@ Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
if (!cs)
{
AMI.weightedSum
(
owner(),
fld,
tresult.ref(),
defaultValues
);
AMICorrectedMultiplyWeightedOp<Type> cop(AMI, owner(), lwOption);
cop(tresult.ref(), fld, defaultValues);
}
else
{
@ -296,13 +303,8 @@ Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
Foam::invTransform(localDeflt, ownT, defaultFld);
}
AMI.weightedSum
(
owner(),
fld,
tresult.ref(),
localDeflt
);
AMICorrectedMultiplyWeightedOp<Type> cop(AMI, owner(), lwOption);
cop(tresult.ref(), fld, defaultValues);
// Transform back
Foam::transform(tresult.ref(), ownT, tresult());
@ -356,26 +358,7 @@ void Foam::cyclicAMIPolyPatch::interpolate
}
// Do actual AMI interpolation
if (owner())
{
AMI().interpolateToSource
(
fld,
cop,
result,
localDeflt
);
}
else
{
neighbPatch().AMI().interpolateToTarget
(
fld,
cop,
result,
localDeflt
);
}
AMI().interpolate(fld, cop, result, defaultValues);
// Transform back. Result is now at *this
Foam::transform(result, ownT, result);
@ -383,26 +366,7 @@ void Foam::cyclicAMIPolyPatch::interpolate
else
*/
{
if (owner())
{
AMI().interpolateToSource
(
fld,
cop,
result,
defaultValues
);
}
else
{
neighbPatch().AMI().interpolateToTarget
(
fld,
cop,
result,
defaultValues
);
}
AMI().interpolate(fld, cop, result, defaultValues);
}
}

View File

@ -276,6 +276,7 @@ processorLOD/cellBox/cellBox.C
processorLOD/faceBox/faceBox.C
AMI=AMIInterpolation
$(AMI)/AMIInterpolation/AMIFieldOps/lowWeightCorrectionBase.C
$(AMI)/AMIInterpolation/AMIInterpolation.C
$(AMI)/AMIInterpolation/AMIInterpolationNew.C
$(AMI)/AMIInterpolation/advancingFrontAMI/advancingFrontAMI.C

View File

@ -38,6 +38,7 @@ License
#include "typeInfo.H"
#include "SubField.H"
#include "globalMeshData.H"
#include "AMIFieldOps.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -95,6 +96,73 @@ namespace Foam
}
}
};
// Combine operator for AMIInterpolation
template<class Type, class TrackingData>
class combineField
:
public AMIFieldOpBase
{
// Private Data
FaceCellWave<Type, TrackingData>& solver_;
const cyclicAMIPolyPatch& patch_;
public:
combineField
(
FaceCellWave<Type, TrackingData>& solver,
const cyclicAMIPolyPatch& patch
)
:
AMIFieldOpBase(patch.AMI(), patch.owner()),
solver_(solver),
patch_(patch)
{}
void operator()
(
List<Type>& result,
const UList<Type>& fld,
const UList<Type>& /* unused defaultValues */
) const
{
const auto& allSlots = address();
forAll(result, facei)
{
const labelList& slots = allSlots[facei];
for (const label sloti : slots)
{
if (fld[sloti].valid(solver_.data()))
{
label meshFacei = -1;
if (patch_.owner())
{
meshFacei = patch_.start() + facei;
}
else
{
meshFacei =
patch_.neighbPatch().start() + facei;
}
result[facei].updateFace
(
solver_.mesh(),
meshFacei,
fld[sloti],
solver_.propagationTol(),
solver_.data()
);
}
}
}
}
};
}
@ -782,7 +850,7 @@ void Foam::FaceCellWave<Type, TrackingData>::handleAMICyclicPatches()
}
// Transfer sendInfo to cycPatch
combine<Type, TrackingData> cmb(*this, cycPatch);
combineField<Type, TrackingData> cmb(*this, cycPatch);
if (cycPatch.applyLowWeightCorrection())
{

View File

@ -26,6 +26,9 @@ License
\*---------------------------------------------------------------------------*/
#include "AMIFieldOps.H"
template<class Type>
void Foam::mappedPatchBase::distribute(List<Type>& lst) const
{
@ -120,7 +123,9 @@ void Foam::mappedPatchBase::distribute
const label oldWarnComm = UPstream::commWarn(myComm);
const label oldWorldComm = UPstream::commWorld(myComm);
lst = interp.interpolateToSource(Field<Type>(std::move(lst)), cop);
const auto op = AMIFieldOp<Type, CombineOp>(interp, cop, true);
lst = interp.interpolate(Field<Type>(std::move(lst)), op);
UPstream::commWarn(oldWarnComm);
UPstream::commWorld(oldWorldComm);
@ -206,7 +211,9 @@ void Foam::mappedPatchBase::reverseDistribute
const label oldWarnComm = UPstream::commWarn(myComm);
const label oldWorldComm = UPstream::commWorld(myComm);
lst = interp.interpolateToTarget(Field<Type>(std::move(lst)), cop);
const auto op = AMIFieldOp<Type, CombineOp>(interp, false);
lst = interp.interpolate(Field<Type>(std::move(lst)), op);
UPstream::commWarn(oldWarnComm);
UPstream::commWorld(oldWorldComm);

View File

@ -78,44 +78,8 @@ void Foam::decompositionConstraint::getMinBoundaryValue
const labelList nbrDecomp(decomposition, nbrPp.faceCells());
labelList thisDecomp(decomposition, cycPp.faceCells());
if (cycPp.owner())
{
cycPp.AMI().interpolateToSource
(
nbrDecomp,
[]
(
label& res,
const label facei,
const label& fld,
const scalar& w
)
{
res = min(res, fld);
},
thisDecomp,
thisDecomp // used in case of low-weight-corr
);
}
else
{
nbrPp.AMI().interpolateToTarget
(
nbrDecomp,
[]
(
label& res,
const label facei,
const label& fld,
const scalar& w
)
{
res = min(res, fld);
},
thisDecomp,
thisDecomp // used in case of low-weight-corr
);
}
AMIMinOp<label> cop(cycPp.AMI(), cycPp.owner());
cop(thisDecomp, nbrDecomp, thisDecomp);
forAll(thisDecomp, i)
{

View File

@ -492,13 +492,9 @@ void Foam::meshToMesh::mapAndOpSrcToTgt
{
tgtField = Type(Zero);
AMI.interpolateToTarget
(
srcField,
multiplyWeightedOp<Type, CombineOp>(cop),
tgtField,
UList<Type>::null()
);
const AMIMultiplyWeightedOp<Type, CombineOp> amicop(AMI, false);
AMI.interpolate(srcField, amicop, tgtField, UList<Type>::null());
}
@ -725,13 +721,9 @@ void Foam::meshToMesh::mapAndOpTgtToSrc
{
srcField = Type(Zero);
AMI.interpolateToSource
(
tgtField,
multiplyWeightedOp<Type, CombineOp>(cop),
srcField,
UList<Type>::null()
);
const AMIMultiplyWeightedOp<Type, CombineOp> amicop(AMI, true);
AMI.interpolate(tgtField, amicop, srcField, UList<Type>::null());
}