mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: add absolute weighting for surfaceFieldValue (issue #567)
- can be useful either for flow-rate weighting where backflow is to be ignored in the average, or for flow-rate weighting on surfaces with inconsistent orientation. Reworked to code to make better use of Enum (the NamedEnum replacement). Enum doesn't require contiguous enumeration values, which lets us use bitmasking of similar operations to reduce duplicate code.
This commit is contained in:
@ -69,23 +69,32 @@ const Foam::Enum
|
||||
>
|
||||
Foam::functionObjects::fieldValues::surfaceFieldValue::operationTypeNames_
|
||||
{
|
||||
// Normal operations
|
||||
{ operationType::opNone, "none" },
|
||||
{ operationType::opMin, "min" },
|
||||
{ operationType::opMax, "max" },
|
||||
{ operationType::opSum, "sum" },
|
||||
{ operationType::opWeightedSum, "weightedSum" },
|
||||
{ operationType::opSumMag, "sumMag" },
|
||||
{ operationType::opSumDirection, "sumDirection" },
|
||||
{ operationType::opSumDirectionBalance, "sumDirectionBalance" },
|
||||
{ operationType::opAverage, "average" },
|
||||
{ operationType::opWeightedAverage, "weightedAverage" },
|
||||
{ operationType::opAreaAverage, "areaAverage" },
|
||||
{ operationType::opWeightedAreaAverage, "weightedAreaAverage" },
|
||||
{ operationType::opAreaIntegrate, "areaIntegrate" },
|
||||
{ operationType::opWeightedAreaIntegrate, "weightedAreaIntegrate" },
|
||||
{ operationType::opMin, "min" },
|
||||
{ operationType::opMax, "max" },
|
||||
{ operationType::opCoV, "CoV" },
|
||||
{ operationType::opAreaNormalAverage, "areaNormalAverage" },
|
||||
{ operationType::opAreaNormalIntegrate, "areaNormalIntegrate" },
|
||||
|
||||
// Using weighting
|
||||
{ operationType::opWeightedSum, "weightedSum" },
|
||||
{ operationType::opWeightedAverage, "weightedAverage" },
|
||||
{ operationType::opWeightedAreaAverage, "weightedAreaAverage" },
|
||||
{ operationType::opWeightedAreaIntegrate, "weightedAreaIntegrate" },
|
||||
|
||||
// Using absolute weighting
|
||||
{ operationType::opAbsWeightedSum, "absWeightedSum" },
|
||||
{ operationType::opAbsWeightedAverage, "absWeightedAverage" },
|
||||
{ operationType::opAbsWeightedAreaAverage, "absWeightedAreaAverage" },
|
||||
{ operationType::opAbsWeightedAreaIntegrate, "absWeightedAreaIntegrate" },
|
||||
};
|
||||
|
||||
const Foam::Enum
|
||||
@ -244,7 +253,7 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::combineMeshGeometry
|
||||
{
|
||||
if (facePatchId_[i] != -1)
|
||||
{
|
||||
label patchi = facePatchId_[i];
|
||||
const label patchi = facePatchId_[i];
|
||||
globalFacesIs[i] += mesh_.boundaryMesh()[patchi].start();
|
||||
}
|
||||
}
|
||||
@ -279,9 +288,8 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::combineMeshGeometry
|
||||
// My own data first
|
||||
{
|
||||
const faceList& fcs = allFaces[Pstream::myProcNo()];
|
||||
forAll(fcs, i)
|
||||
for (const face& f : fcs)
|
||||
{
|
||||
const face& f = fcs[i];
|
||||
face& newF = faces[nFaces++];
|
||||
newF.setSize(f.size());
|
||||
forAll(f, fp)
|
||||
@ -291,9 +299,9 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::combineMeshGeometry
|
||||
}
|
||||
|
||||
const pointField& pts = allPoints[Pstream::myProcNo()];
|
||||
forAll(pts, i)
|
||||
for (const point& pt : pts)
|
||||
{
|
||||
points[nPoints++] = pts[i];
|
||||
points[nPoints++] = pt;
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,9 +311,8 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::combineMeshGeometry
|
||||
if (proci != Pstream::myProcNo())
|
||||
{
|
||||
const faceList& fcs = allFaces[proci];
|
||||
forAll(fcs, i)
|
||||
for (const face& f : fcs)
|
||||
{
|
||||
const face& f = fcs[i];
|
||||
face& newF = faces[nFaces++];
|
||||
newF.setSize(f.size());
|
||||
forAll(f, fp)
|
||||
@ -315,9 +322,9 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::combineMeshGeometry
|
||||
}
|
||||
|
||||
const pointField& pts = allPoints[proci];
|
||||
forAll(pts, i)
|
||||
for (const point& pt : pts)
|
||||
{
|
||||
points[nPoints++] = pts[i];
|
||||
points[nPoints++] = pt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -343,9 +350,9 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::combineMeshGeometry
|
||||
}
|
||||
|
||||
points.transfer(newPoints);
|
||||
forAll(faces, i)
|
||||
for (face& f : faces)
|
||||
{
|
||||
inplaceRenumber(oldToNew, faces[i]);
|
||||
inplaceRenumber(oldToNew, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -447,17 +454,19 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::totalArea() const
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
bool Foam::functionObjects::fieldValues::surfaceFieldValue::needsSf() const
|
||||
bool Foam::functionObjects::fieldValues::surfaceFieldValue::usesSf() const
|
||||
{
|
||||
// Many operations use the Sf field
|
||||
// Only a few operations do not require the Sf field
|
||||
switch (operation_)
|
||||
{
|
||||
case opNone:
|
||||
case opMin:
|
||||
case opMax:
|
||||
case opSum:
|
||||
case opSumMag:
|
||||
case opAverage:
|
||||
case opMin:
|
||||
case opMax:
|
||||
case opSumDirection:
|
||||
case opSumDirectionBalance:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -469,26 +478,6 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::needsSf() const
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::fieldValues::surfaceFieldValue::needsWeight() const
|
||||
{
|
||||
// Only a few operations use weight field
|
||||
switch (operation_)
|
||||
{
|
||||
case opWeightedSum:
|
||||
case opWeightedAverage:
|
||||
case opWeightedAreaAverage:
|
||||
case opWeightedAreaIntegrate:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::fieldValues::surfaceFieldValue::initialise
|
||||
(
|
||||
const dictionary& dict
|
||||
@ -582,19 +571,16 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::initialise
|
||||
|
||||
|
||||
weightFieldName_ = "none";
|
||||
if (needsWeight())
|
||||
if (usesWeight() && dict.readIfPresent("weightField", weightFieldName_))
|
||||
{
|
||||
if (dict.readIfPresent("weightField", weightFieldName_))
|
||||
if (regionType_ == stSampledSurface)
|
||||
{
|
||||
if (regionType_ == stSampledSurface)
|
||||
{
|
||||
FatalIOErrorInFunction(dict)
|
||||
<< "Cannot use weightField for sampledSurface"
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
Info<< " weight field = " << weightFieldName_ << nl;
|
||||
FatalIOErrorInFunction(dict)
|
||||
<< "Cannot use weightField for sampledSurface"
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
Info<< " weight field = " << weightFieldName_ << nl;
|
||||
}
|
||||
|
||||
// Backwards compatibility for v1612+ and older
|
||||
@ -660,10 +646,10 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::writeFileHeader
|
||||
os << tab << "Area";
|
||||
}
|
||||
|
||||
forAll(fields_, i)
|
||||
for (const word& fieldName : fields_)
|
||||
{
|
||||
os << tab << operationTypeNames_[operation_]
|
||||
<< "(" << fields_[i] << ")";
|
||||
<< "(" << fieldName << ")";
|
||||
}
|
||||
|
||||
os << endl;
|
||||
@ -684,12 +670,12 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
|
||||
{
|
||||
case opSumDirection:
|
||||
{
|
||||
vector n(dict_.lookup("direction"));
|
||||
const vector n(dict_.lookup("direction"));
|
||||
return gSum(pos(values*(Sf & n))*mag(values));
|
||||
}
|
||||
case opSumDirectionBalance:
|
||||
{
|
||||
vector n(dict_.lookup("direction"));
|
||||
const vector n(dict_.lookup("direction"));
|
||||
const scalarField nv(values*(Sf & n));
|
||||
|
||||
return gSum(pos(nv)*mag(values) - neg(nv)*mag(values));
|
||||
@ -754,10 +740,17 @@ Foam::tmp<Foam::scalarField>
|
||||
Foam::functionObjects::fieldValues::surfaceFieldValue::weightingFactor
|
||||
(
|
||||
const Field<scalar>& weightField
|
||||
)
|
||||
) const
|
||||
{
|
||||
// pass through
|
||||
return weightField;
|
||||
if (usesMag())
|
||||
{
|
||||
return mag(weightField);
|
||||
}
|
||||
else
|
||||
{
|
||||
// pass through
|
||||
return weightField;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -767,16 +760,21 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::weightingFactor
|
||||
(
|
||||
const Field<scalar>& weightField,
|
||||
const vectorField& Sf
|
||||
)
|
||||
) const
|
||||
{
|
||||
// scalar * Area
|
||||
if (returnReduce(weightField.empty(), andOp<bool>()))
|
||||
{
|
||||
// No weight field - revert to unweighted form
|
||||
return mag(Sf);
|
||||
}
|
||||
else if (usesMag())
|
||||
{
|
||||
return mag(weightField * mag(Sf));
|
||||
}
|
||||
else
|
||||
{
|
||||
return weightField * mag(Sf);
|
||||
return (weightField * mag(Sf));
|
||||
}
|
||||
}
|
||||
|
||||
@ -787,16 +785,21 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::weightingFactor
|
||||
(
|
||||
const Field<vector>& weightField,
|
||||
const vectorField& Sf
|
||||
)
|
||||
) const
|
||||
{
|
||||
// vector (dot) Area
|
||||
if (returnReduce(weightField.empty(), andOp<bool>()))
|
||||
{
|
||||
// No weight field - revert to unweighted form
|
||||
return mag(Sf);
|
||||
}
|
||||
else if (usesMag())
|
||||
{
|
||||
return mag(weightField & Sf);
|
||||
}
|
||||
else
|
||||
{
|
||||
return weightField & Sf;
|
||||
return (weightField & Sf);
|
||||
}
|
||||
}
|
||||
|
||||
@ -915,7 +918,7 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::write()
|
||||
|
||||
// Many operations use the Sf field
|
||||
vectorField Sf;
|
||||
if (needsSf())
|
||||
if (usesSf())
|
||||
{
|
||||
if (regionType_ == stSurface)
|
||||
{
|
||||
|
||||
@ -103,22 +103,26 @@ Usage
|
||||
The \c operation is one of:
|
||||
\plaintable
|
||||
none | no operation
|
||||
sum | sum
|
||||
weightedSum | weighted sum
|
||||
sumMag | sum of component magnitudes
|
||||
sumDirection | sum values which are positive in given direction
|
||||
sumDirectionBalance | sum of balance of values in given direction
|
||||
average | ensemble average
|
||||
weightedAverage | weighted average
|
||||
areaAverage | area-weighted average
|
||||
weightedAreaAverage | weighted area average
|
||||
areaIntegrate | area integral
|
||||
weightedAreaIntegrate | weighted area integral
|
||||
min | minimum
|
||||
max | maximum
|
||||
sum | sum
|
||||
sumMag | sum of component magnitudes
|
||||
sumDirection | sum values that are positive in given direction
|
||||
sumDirectionBalance | sum of balance of values in given direction
|
||||
average | ensemble average
|
||||
areaAverage | area-weighted average
|
||||
areaIntegrate | area integral
|
||||
CoV | coefficient of variation: standard deviation/mean
|
||||
areaNormalAverage| area-weighted average in face normal direction
|
||||
areaNormalIntegrate | area-weighted integral in face normal directon
|
||||
weightedSum | weighted sum
|
||||
weightedAverage | weighted average
|
||||
weightedAreaAverage | weighted area average
|
||||
weightedAreaIntegrate | weighted area integral
|
||||
absWeightedSum | sum using absolute weighting
|
||||
absWeightedAverage | average using absolute weighting
|
||||
absWeightedAreaAverage | area average using absolute weighting
|
||||
absWeightedAreaIntegrate | area integral using absolute weighting
|
||||
\endplaintable
|
||||
|
||||
Note
|
||||
@ -190,36 +194,73 @@ public:
|
||||
//- Region type enumeration
|
||||
enum regionTypes
|
||||
{
|
||||
stFaceZone,
|
||||
stPatch,
|
||||
stSurface,
|
||||
stSampledSurface
|
||||
stFaceZone, //!< Calculate on a faceZone
|
||||
stPatch, //!< Calculate on a patch
|
||||
stSurface, //!< Calculate with fields on a surfMesh
|
||||
stSampledSurface //!< Sample onto surface and calculate
|
||||
};
|
||||
|
||||
//- Region type names
|
||||
static const Enum<regionTypes> regionTypeNames_;
|
||||
|
||||
//- Bitmask values for operation variants
|
||||
enum operationVariant
|
||||
{
|
||||
typeBase = 0, //!< Base operation
|
||||
typeWeighted = 0x100, //!< Operation using weighting
|
||||
typeAbsolute = 0x200, //!< Operation using mag (eg, for weighting)
|
||||
};
|
||||
|
||||
//- Operation type enumeration
|
||||
enum operationType
|
||||
{
|
||||
opNone, //!< None
|
||||
opSum, //!< Sum
|
||||
opWeightedSum, //!< Weighted sum
|
||||
opSumMag, //!< Magnitude of sum
|
||||
// Normal operations
|
||||
|
||||
opNone = 0, //!< No operation
|
||||
opMin, //!< Minimum value
|
||||
opMax, //!< Maximum value
|
||||
opSum, //!< Sum of values
|
||||
opSumMag, //!< Sum of component magnitudes
|
||||
opSumDirection, //!< Sum in a given direction
|
||||
opSumDirectionBalance, //!< Sum in a given direction for multiple
|
||||
opAverage, //!< Average
|
||||
opWeightedAverage, //!< Weighted average
|
||||
|
||||
//! Sum of balance of values in given direction
|
||||
opSumDirectionBalance,
|
||||
|
||||
opAverage, //!< Ensemble average
|
||||
opAreaAverage, //!< Area average
|
||||
opWeightedAreaAverage, //!< Weighted area average
|
||||
opAreaIntegrate, //!< Area integral
|
||||
opWeightedAreaIntegrate, //!< Weighted area integral
|
||||
opMin, //!< Minimum
|
||||
opMax, //!< Maximum
|
||||
opCoV, //!< Coefficient of variation
|
||||
opAreaNormalAverage, //!< Area average in normal direction
|
||||
opAreaNormalIntegrate //!< Area integral in normal direction
|
||||
opAreaNormalIntegrate, //!< Area integral in normal direction
|
||||
|
||||
// Weighted variants
|
||||
|
||||
//! Weighted sum
|
||||
opWeightedSum = (opSum | typeWeighted),
|
||||
|
||||
//! Weighted average
|
||||
opWeightedAverage = (opAverage | typeWeighted),
|
||||
|
||||
//! Weighted area average
|
||||
opWeightedAreaAverage = (opAreaAverage | typeWeighted),
|
||||
|
||||
//! Weighted area integral
|
||||
opWeightedAreaIntegrate = (opAreaIntegrate | typeWeighted),
|
||||
|
||||
// Variants using absolute weighting
|
||||
|
||||
//! Sum using abs weighting
|
||||
opAbsWeightedSum = (opWeightedSum | typeAbsolute),
|
||||
|
||||
//! Average using abs weighting
|
||||
opAbsWeightedAverage = (opWeightedAverage | typeAbsolute),
|
||||
|
||||
//! Area average using abs weighting
|
||||
opAbsWeightedAreaAverage = (opWeightedAreaAverage | typeAbsolute),
|
||||
|
||||
//! Area integral using abs weighting
|
||||
opAbsWeightedAreaIntegrate =
|
||||
(opWeightedAreaIntegrate | typeAbsolute),
|
||||
};
|
||||
|
||||
//- Operation type names
|
||||
@ -229,8 +270,8 @@ public:
|
||||
//- Post-operation type enumeration
|
||||
enum postOperationType
|
||||
{
|
||||
postOpNone,
|
||||
postOpSqrt
|
||||
postOpNone, //!< No additional operation after calculation
|
||||
postOpSqrt //!< Perform sqrt after normal operation
|
||||
};
|
||||
|
||||
//- Operation type names
|
||||
@ -325,11 +366,19 @@ protected:
|
||||
//- Return the local true/false list representing the face flip map
|
||||
inline const boolList& faceFlip() const;
|
||||
|
||||
//- True if the specified operation needs a surface Sf
|
||||
bool needsSf() const;
|
||||
//- True if the operation needs a surface Sf
|
||||
bool usesSf() const;
|
||||
|
||||
//- True if the specified operation needs a weight-field
|
||||
bool needsWeight() const;
|
||||
//- True if the operation variant uses mag
|
||||
inline bool usesMag() const;
|
||||
|
||||
//- True if the operation variant uses a weight-field
|
||||
inline bool usesWeight() const;
|
||||
|
||||
//- True if operation variant uses a weight-field that is available.
|
||||
// Checks for availability on any processor.
|
||||
template<class WeightType>
|
||||
inline bool canWeight(const Field<WeightType>& weightField) const;
|
||||
|
||||
//- Initialise, e.g. face addressing
|
||||
void initialise(const dictionary& dict);
|
||||
@ -365,6 +414,7 @@ protected:
|
||||
const Field<WeightType>& weightField
|
||||
) const;
|
||||
|
||||
|
||||
//- Filter a surface field according to faceIds
|
||||
template<class Type>
|
||||
tmp<Field<Type>> filterField
|
||||
@ -379,20 +429,24 @@ protected:
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field
|
||||
) const;
|
||||
|
||||
//- Weighting factor
|
||||
|
||||
//- Weighting factor.
|
||||
// Possibly applies mag() depending on the operation type.
|
||||
template<class WeightType>
|
||||
static tmp<scalarField> weightingFactor
|
||||
tmp<scalarField> weightingFactor
|
||||
(
|
||||
const Field<WeightType>& weightField
|
||||
);
|
||||
) const;
|
||||
|
||||
//- Weighting factor, weight field with the area
|
||||
//- Weighting factor, weight field with the area.
|
||||
// Possibly applies mag() depending on the operation type.
|
||||
// Reverts to mag(Sf) if the weight field is not available.
|
||||
template<class WeightType>
|
||||
static tmp<scalarField> weightingFactor
|
||||
tmp<scalarField> weightingFactor
|
||||
(
|
||||
const Field<WeightType>& weightField,
|
||||
const vectorField& Sf
|
||||
);
|
||||
) const;
|
||||
|
||||
|
||||
//- Templated helper function to output field values
|
||||
@ -489,7 +543,7 @@ template<>
|
||||
tmp<scalarField> surfaceFieldValue::weightingFactor
|
||||
(
|
||||
const Field<scalar>& weightField
|
||||
);
|
||||
) const;
|
||||
|
||||
|
||||
//- Specialisation for scalar - scalar * Area
|
||||
@ -498,7 +552,7 @@ tmp<scalarField> surfaceFieldValue::weightingFactor
|
||||
(
|
||||
const Field<scalar>& weightField,
|
||||
const vectorField& Sf
|
||||
);
|
||||
) const;
|
||||
|
||||
|
||||
//- Specialisation for vector - vector (dot) Area
|
||||
@ -507,7 +561,7 @@ tmp<scalarField> surfaceFieldValue::weightingFactor
|
||||
(
|
||||
const Field<vector>& weightField,
|
||||
const vectorField& Sf
|
||||
);
|
||||
) const;
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -23,7 +23,6 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "surfaceFieldValue.H"
|
||||
#include "Time.H"
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
@ -51,6 +50,22 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::faceFlip() const
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
inline bool
|
||||
Foam::functionObjects::fieldValues::surfaceFieldValue::usesMag() const
|
||||
{
|
||||
// Operation specifically tagged to use mag
|
||||
return (operation_ & typeAbsolute);
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
Foam::functionObjects::fieldValues::surfaceFieldValue::usesWeight() const
|
||||
{
|
||||
// Operation specifically tagged to require a weight field
|
||||
return (operation_ & typeWeighted);
|
||||
}
|
||||
|
||||
|
||||
inline const Foam::functionObjects::fieldValues::surfaceFieldValue::regionTypes&
|
||||
Foam::functionObjects::fieldValues::surfaceFieldValue::regionType() const
|
||||
{
|
||||
|
||||
@ -33,6 +33,20 @@ License
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class WeightType>
|
||||
inline bool Foam::functionObjects::fieldValues::surfaceFieldValue::canWeight
|
||||
(
|
||||
const Field<WeightType>& weightField
|
||||
) const
|
||||
{
|
||||
return
|
||||
(
|
||||
usesWeight()
|
||||
&& returnReduce(!weightField.empty(), orOp<bool>()) // On some processor
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
bool Foam::functionObjects::fieldValues::surfaceFieldValue::validField
|
||||
(
|
||||
@ -142,23 +156,14 @@ processSameTypeValues
|
||||
{
|
||||
break;
|
||||
}
|
||||
case opSum:
|
||||
case opMin:
|
||||
{
|
||||
result = gSum(values);
|
||||
result = gMin(values);
|
||||
break;
|
||||
}
|
||||
case opWeightedSum:
|
||||
case opMax:
|
||||
{
|
||||
if (returnReduce(weightField.empty(), andOp<bool>()))
|
||||
{
|
||||
result = gSum(values);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp<scalarField> weight(weightingFactor(weightField));
|
||||
|
||||
result = gSum(weight*values);
|
||||
}
|
||||
result = gMax(values);
|
||||
break;
|
||||
}
|
||||
case opSumMag:
|
||||
@ -166,6 +171,23 @@ processSameTypeValues
|
||||
result = gSum(cmptMag(values));
|
||||
break;
|
||||
}
|
||||
case opSum:
|
||||
case opWeightedSum:
|
||||
case opAbsWeightedSum:
|
||||
{
|
||||
if (canWeight(weightField))
|
||||
{
|
||||
tmp<scalarField> weight(weightingFactor(weightField));
|
||||
|
||||
result = gSum(weight*values);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unweighted form
|
||||
result = gSum(values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case opSumDirection:
|
||||
case opSumDirectionBalance:
|
||||
{
|
||||
@ -178,62 +200,56 @@ processSameTypeValues
|
||||
break;
|
||||
}
|
||||
case opAverage:
|
||||
{
|
||||
const label n = returnReduce(values.size(), sumOp<label>());
|
||||
result = gSum(values)/(scalar(n) + ROOTVSMALL);
|
||||
break;
|
||||
}
|
||||
case opWeightedAverage:
|
||||
case opAbsWeightedAverage:
|
||||
{
|
||||
if (returnReduce(weightField.empty(), andOp<bool>()))
|
||||
{
|
||||
const label n = returnReduce(values.size(), sumOp<label>());
|
||||
result = gSum(values)/(scalar(n) + ROOTVSMALL);
|
||||
}
|
||||
else
|
||||
if (canWeight(weightField))
|
||||
{
|
||||
const scalarField factor(weightingFactor(weightField));
|
||||
|
||||
result = gSum(factor*values)/(gSum(factor) + ROOTVSMALL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unweighted form
|
||||
const label n = returnReduce(values.size(), sumOp<label>());
|
||||
result = gSum(values)/(scalar(n) + ROOTVSMALL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case opAreaAverage:
|
||||
{
|
||||
const scalarField factor(mag(Sf));
|
||||
|
||||
result = gSum(factor*values)/gSum(factor);
|
||||
break;
|
||||
}
|
||||
case opWeightedAreaAverage:
|
||||
case opAbsWeightedAreaAverage:
|
||||
{
|
||||
const scalarField factor(weightingFactor(weightField, Sf));
|
||||
if (canWeight(weightField))
|
||||
{
|
||||
const scalarField factor(weightingFactor(weightField, Sf));
|
||||
|
||||
result = gSum(factor*values)/gSum(factor + ROOTVSMALL);
|
||||
result = gSum(factor*values)/gSum(factor + ROOTVSMALL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unweighted form
|
||||
const scalarField factor(mag(Sf));
|
||||
result = gSum(factor*values)/gSum(factor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case opAreaIntegrate:
|
||||
{
|
||||
const scalarField factor(mag(Sf));
|
||||
|
||||
result = gSum(factor*values);
|
||||
break;
|
||||
}
|
||||
case opWeightedAreaIntegrate:
|
||||
case opAbsWeightedAreaIntegrate:
|
||||
{
|
||||
const scalarField factor(weightingFactor(weightField, Sf));
|
||||
|
||||
result = gSum(factor*values);
|
||||
break;
|
||||
}
|
||||
case opMin:
|
||||
{
|
||||
result = gMin(values);
|
||||
break;
|
||||
}
|
||||
case opMax:
|
||||
{
|
||||
result = gMax(values);
|
||||
if (canWeight(weightField))
|
||||
{
|
||||
tmp<scalarField> factor(weightingFactor(weightField, Sf));
|
||||
result = gSum(factor*values);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unweighted form
|
||||
tmp<scalarField> factor(mag(Sf));
|
||||
result = gSum(factor*values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case opCoV:
|
||||
@ -245,8 +261,8 @@ processSameTypeValues
|
||||
|
||||
for (direction d=0; d < pTraits<Type>::nComponents; ++d)
|
||||
{
|
||||
tmp<scalarField> vals = values.component(d);
|
||||
scalar mean = component(meanValue, d);
|
||||
tmp<scalarField> vals(values.component(d));
|
||||
const scalar mean = component(meanValue, d);
|
||||
scalar& res = setComponent(result, d);
|
||||
|
||||
res =
|
||||
@ -286,8 +302,10 @@ Foam::tmp<Foam::scalarField>
|
||||
Foam::functionObjects::fieldValues::surfaceFieldValue::weightingFactor
|
||||
(
|
||||
const Field<WeightType>& weightField
|
||||
)
|
||||
) const
|
||||
{
|
||||
// The scalar form is specialized.
|
||||
// For other types always need mag() to generate a scalar field.
|
||||
return mag(weightField);
|
||||
}
|
||||
|
||||
@ -302,10 +320,8 @@ Foam::label Foam::functionObjects::fieldValues::surfaceFieldValue::writeAll
|
||||
{
|
||||
label nProcessed = 0;
|
||||
|
||||
forAll(fields_, i)
|
||||
for (const word& fieldName : fields_)
|
||||
{
|
||||
const word& fieldName = fields_[i];
|
||||
|
||||
if
|
||||
(
|
||||
writeValues<scalar>(fieldName, Sf, weightField, surfToWrite)
|
||||
@ -437,8 +453,8 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::filterField
|
||||
|
||||
forAll(values, i)
|
||||
{
|
||||
label facei = faceId_[i];
|
||||
label patchi = facePatchId_[i];
|
||||
const label facei = faceId_[i];
|
||||
const label patchi = facePatchId_[i];
|
||||
if (patchi >= 0)
|
||||
{
|
||||
values[i] = field.boundaryField()[patchi][facei];
|
||||
@ -472,8 +488,8 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::filterField
|
||||
|
||||
forAll(values, i)
|
||||
{
|
||||
label facei = faceId_[i];
|
||||
label patchi = facePatchId_[i];
|
||||
const label facei = faceId_[i];
|
||||
const label patchi = facePatchId_[i];
|
||||
if (patchi >= 0)
|
||||
{
|
||||
values[i] = field.boundaryField()[patchi][facei];
|
||||
|
||||
@ -49,32 +49,35 @@ const Foam::Enum
|
||||
>
|
||||
Foam::functionObjects::fieldValues::volFieldValue::operationTypeNames_
|
||||
{
|
||||
// Normal operations
|
||||
{ operationType::opNone, "none" },
|
||||
{ operationType::opSum, "sum" },
|
||||
{ operationType::opWeightedSum, "weightedSum" },
|
||||
{ operationType::opSumMag, "sumMag" },
|
||||
{ operationType::opAverage, "average" },
|
||||
{ operationType::opWeightedAverage, "weightedAverage" },
|
||||
{ operationType::opVolAverage, "volAverage" },
|
||||
{ operationType::opWeightedVolAverage, "weightedVolAverage" },
|
||||
{ operationType::opVolIntegrate, "volIntegrate" },
|
||||
{ operationType::opWeightedVolIntegrate, "weightedVolIntegrate" },
|
||||
{ operationType::opMin, "min" },
|
||||
{ operationType::opMax, "max" },
|
||||
{ operationType::opSum, "sum" },
|
||||
{ operationType::opSumMag, "sumMag" },
|
||||
{ operationType::opAverage, "average" },
|
||||
{ operationType::opVolAverage, "volAverage" },
|
||||
{ operationType::opVolIntegrate, "volIntegrate" },
|
||||
{ operationType::opCoV, "CoV" },
|
||||
|
||||
// Using weighting
|
||||
{ operationType::opWeightedSum, "weightedSum" },
|
||||
{ operationType::opWeightedAverage, "weightedAverage" },
|
||||
{ operationType::opWeightedVolAverage, "weightedVolAverage" },
|
||||
{ operationType::opWeightedVolIntegrate, "weightedVolIntegrate" },
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
bool Foam::functionObjects::fieldValues::volFieldValue::needsVol() const
|
||||
bool Foam::functionObjects::fieldValues::volFieldValue::usesVol() const
|
||||
{
|
||||
// Only some operations need the cell volume
|
||||
// Only a few operations require the cell volume
|
||||
switch (operation_)
|
||||
{
|
||||
case opVolAverage:
|
||||
case opWeightedVolAverage:
|
||||
case opVolIntegrate:
|
||||
case opWeightedVolAverage:
|
||||
case opWeightedVolIntegrate:
|
||||
case opCoV:
|
||||
return true;
|
||||
@ -85,20 +88,23 @@ bool Foam::functionObjects::fieldValues::volFieldValue::needsVol() const
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::fieldValues::volFieldValue::needsWeight() const
|
||||
bool Foam::functionObjects::fieldValues::volFieldValue::usesWeight() const
|
||||
{
|
||||
// Only a few operations use weight field
|
||||
switch (operation_)
|
||||
{
|
||||
case opWeightedSum:
|
||||
case opWeightedAverage:
|
||||
case opWeightedVolAverage:
|
||||
case opWeightedVolIntegrate:
|
||||
return true;
|
||||
// Operation specifically tagged to require a weight field
|
||||
return (operation_ & typeWeighted);
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Foam::functionObjects::fieldValues::volFieldValue::canWeight
|
||||
(
|
||||
const scalarField& weightField
|
||||
) const
|
||||
{
|
||||
return
|
||||
(
|
||||
usesWeight()
|
||||
&& returnReduce(!weightField.empty(), orOp<bool>()) // On some processor
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -108,12 +114,9 @@ void Foam::functionObjects::fieldValues::volFieldValue::initialise
|
||||
)
|
||||
{
|
||||
weightFieldName_ = "none";
|
||||
if (needsWeight())
|
||||
if (usesWeight() && dict.readIfPresent("weightField", weightFieldName_))
|
||||
{
|
||||
if (dict.readIfPresent("weightField", weightFieldName_))
|
||||
{
|
||||
Info<< " weight field = " << weightFieldName_;
|
||||
}
|
||||
Info<< " weight field = " << weightFieldName_;
|
||||
}
|
||||
|
||||
Info<< nl << endl;
|
||||
@ -133,10 +136,10 @@ void Foam::functionObjects::fieldValues::volFieldValue::writeFileHeader
|
||||
|
||||
writeCommented(os, "Time");
|
||||
|
||||
forAll(fields_, fieldi)
|
||||
for (const word& fieldName : fields_)
|
||||
{
|
||||
os << tab << operationTypeNames_[operation_]
|
||||
<< "(" << fields_[fieldi] << ")";
|
||||
<< "(" << fieldName << ")";
|
||||
}
|
||||
|
||||
os << endl;
|
||||
@ -151,10 +154,8 @@ Foam::label Foam::functionObjects::fieldValues::volFieldValue::writeAll
|
||||
{
|
||||
label nProcessed = 0;
|
||||
|
||||
forAll(fields_, i)
|
||||
for (const word& fieldName : fields_)
|
||||
{
|
||||
const word& fieldName = fields_[i];
|
||||
|
||||
if
|
||||
(
|
||||
writeValues<scalar>(fieldName, V, weightField)
|
||||
@ -245,7 +246,7 @@ bool Foam::functionObjects::fieldValues::volFieldValue::write()
|
||||
|
||||
// Only some operations need the cell volume
|
||||
scalarField V;
|
||||
if (needsVol())
|
||||
if (usesVol())
|
||||
{
|
||||
V = filterField(fieldValue::mesh_.V());
|
||||
}
|
||||
|
||||
@ -81,18 +81,18 @@ Usage
|
||||
The \c operation is one of:
|
||||
\plaintable
|
||||
none | No operation
|
||||
sum | Sum
|
||||
weightedSum | Weighted sum
|
||||
sumMag | Sum of component magnitudes
|
||||
average | Ensemble average
|
||||
weightedAverage | Weighted average
|
||||
volAverage | Volume weighted average
|
||||
weightedVolAverage | Weighted volume average
|
||||
volIntegrate | Volume integral
|
||||
weightedVolIntegrate | Weighted volume integral
|
||||
min | Minimum
|
||||
max | Maximum
|
||||
sum | Sum
|
||||
sumMag | Sum of component magnitudes
|
||||
average | Ensemble average
|
||||
volAverage | Volume weighted average
|
||||
volIntegrate | Volume integral
|
||||
CoV | Coefficient of variation: standard deviation/mean
|
||||
weightedSum | Weighted sum
|
||||
weightedAverage | Weighted average
|
||||
weightedVolAverage | Weighted volume average
|
||||
weightedVolIntegrate | Weighted volume integral
|
||||
\endplaintable
|
||||
|
||||
See also
|
||||
@ -134,22 +134,41 @@ public:
|
||||
|
||||
// Public data types
|
||||
|
||||
//- Bitmask values for operation variants
|
||||
enum operationVariant
|
||||
{
|
||||
typeBase = 0, //!< Base operation
|
||||
typeWeighted = 0x100, //!< Operation using weighting
|
||||
};
|
||||
|
||||
//- Operation type enumeration
|
||||
enum operationType
|
||||
{
|
||||
opNone, //!< None
|
||||
opSum, //!< Sum
|
||||
opWeightedSum, //!< Weighted sum
|
||||
opSumMag, //!< Magnitude of sum
|
||||
opAverage, //!< Average
|
||||
opWeightedAverage, //!< Weighted average
|
||||
opVolAverage, //!< Volume average
|
||||
opWeightedVolAverage, //!< Weighted volume average
|
||||
opVolIntegrate, //!< Volume integral
|
||||
opWeightedVolIntegrate, //!< Weighted volume integral
|
||||
// Normal operations
|
||||
|
||||
opNone = 0, //!< No operation
|
||||
opMin, //!< Minimum
|
||||
opMax, //!< Maximum
|
||||
opCoV //!< Coefficient of variation
|
||||
opSum, //!< Sum
|
||||
opSumMag, //!< Magnitude of sum
|
||||
opAverage, //!< Average
|
||||
opVolAverage, //!< Volume average
|
||||
opVolIntegrate, //!< Volume integral
|
||||
opCoV, //!< Coefficient of variation
|
||||
|
||||
// Weighted variants
|
||||
|
||||
//! Weighted sum
|
||||
opWeightedSum = (opSum | typeWeighted),
|
||||
|
||||
//! Weighted average
|
||||
opWeightedAverage = (opAverage | typeWeighted),
|
||||
|
||||
//! Weighted volume average
|
||||
opWeightedVolAverage = (opVolAverage | typeWeighted),
|
||||
|
||||
//! Weighted volume integral
|
||||
opWeightedVolIntegrate = (opVolIntegrate | typeWeighted),
|
||||
};
|
||||
|
||||
//- Operation type names
|
||||
@ -169,11 +188,15 @@ protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- True if the specified operation needs the cell-volume
|
||||
bool needsVol() const;
|
||||
//- True if the operation needs the cell-volume
|
||||
bool usesVol() const;
|
||||
|
||||
//- True if the specified operation needs a weight-field
|
||||
bool needsWeight() const;
|
||||
//- True if the operation variant uses a weight-field
|
||||
bool usesWeight() const;
|
||||
|
||||
//- True if operation variant uses a weight-field that is available.
|
||||
// Checks for availability on any processor.
|
||||
inline bool canWeight(const scalarField& weightField) const;
|
||||
|
||||
//- Initialise, e.g. cell addressing
|
||||
void initialise(const dictionary& dict);
|
||||
|
||||
@ -82,81 +82,8 @@ Type Foam::functionObjects::fieldValues::volFieldValue::processValues
|
||||
Type result = Zero;
|
||||
switch (operation_)
|
||||
{
|
||||
case opSum:
|
||||
case opNone:
|
||||
{
|
||||
result = gSum(values);
|
||||
break;
|
||||
}
|
||||
case opWeightedSum:
|
||||
{
|
||||
if (returnReduce(weightField.empty(), andOp<bool>()))
|
||||
{
|
||||
result = gSum(values);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = gSum(weightField*values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case opSumMag:
|
||||
{
|
||||
result = gSum(cmptMag(values));
|
||||
break;
|
||||
}
|
||||
case opAverage:
|
||||
{
|
||||
const label n = returnReduce(values.size(), sumOp<label>());
|
||||
result = gSum(values)/(scalar(n) + ROOTVSMALL);
|
||||
break;
|
||||
}
|
||||
case opWeightedAverage:
|
||||
{
|
||||
if (returnReduce(weightField.empty(), andOp<bool>()))
|
||||
{
|
||||
const label n = returnReduce(values.size(), sumOp<label>());
|
||||
result = gSum(values)/(scalar(n) + ROOTVSMALL);
|
||||
}
|
||||
else
|
||||
{
|
||||
result =
|
||||
gSum(weightField*values)/(gSum(weightField) + ROOTVSMALL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case opVolAverage:
|
||||
{
|
||||
result = gSum(values*V)/gSum(V);
|
||||
break;
|
||||
}
|
||||
case opWeightedVolAverage:
|
||||
{
|
||||
if (returnReduce(weightField.empty(), andOp<bool>()))
|
||||
{
|
||||
result = gSum(V*values)/(gSum(V) + ROOTVSMALL);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = gSum(weightField*V*values)
|
||||
/(gSum(weightField*V) + ROOTVSMALL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case opVolIntegrate:
|
||||
{
|
||||
result = gSum(V*values);
|
||||
break;
|
||||
}
|
||||
case opWeightedVolIntegrate:
|
||||
{
|
||||
if (returnReduce(weightField.empty(), andOp<bool>()))
|
||||
{
|
||||
result = gSum(V*values);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = gSum(weightField*V*values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case opMin:
|
||||
@ -169,6 +96,70 @@ Type Foam::functionObjects::fieldValues::volFieldValue::processValues
|
||||
result = gMax(values);
|
||||
break;
|
||||
}
|
||||
case opSumMag:
|
||||
{
|
||||
result = gSum(cmptMag(values));
|
||||
break;
|
||||
}
|
||||
case opSum:
|
||||
case opWeightedSum:
|
||||
{
|
||||
if (canWeight(weightField))
|
||||
{
|
||||
result = gSum(weightField*values);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unweighted form
|
||||
result = gSum(values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case opAverage:
|
||||
case opWeightedAverage:
|
||||
{
|
||||
if (canWeight(weightField))
|
||||
{
|
||||
result =
|
||||
gSum(weightField*values)/(gSum(weightField) + ROOTVSMALL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unweighted form
|
||||
const label n = returnReduce(values.size(), sumOp<label>());
|
||||
result = gSum(values)/(scalar(n) + ROOTVSMALL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case opVolAverage:
|
||||
case opWeightedVolAverage:
|
||||
{
|
||||
if (canWeight(weightField))
|
||||
{
|
||||
result = gSum(weightField*V*values)
|
||||
/(gSum(weightField*V) + ROOTVSMALL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unweighted form
|
||||
result = gSum(V*values)/(gSum(V) + ROOTVSMALL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case opVolIntegrate:
|
||||
case opWeightedVolIntegrate:
|
||||
{
|
||||
if (canWeight(weightField))
|
||||
{
|
||||
result = gSum(weightField*V*values);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unweighted form
|
||||
result = gSum(V*values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case opCoV:
|
||||
{
|
||||
const scalar sumV = gSum(V);
|
||||
@ -177,8 +168,8 @@ Type Foam::functionObjects::fieldValues::volFieldValue::processValues
|
||||
|
||||
for (direction d=0; d < pTraits<Type>::nComponents; ++d)
|
||||
{
|
||||
scalarField vals(values.component(d));
|
||||
scalar mean = component(meanValue, d);
|
||||
tmp<scalarField> vals(values.component(d));
|
||||
const scalar mean = component(meanValue, d);
|
||||
scalar& res = setComponent(result, d);
|
||||
|
||||
res = sqrt(gSum(V*sqr(vals - mean))/sumV)/(mean + ROOTVSMALL);
|
||||
@ -186,8 +177,6 @@ Type Foam::functionObjects::fieldValues::volFieldValue::processValues
|
||||
|
||||
break;
|
||||
}
|
||||
case opNone:
|
||||
{}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user