ENH: support multiple weights on some field function objects (#1930)

- weight fields are combined by multiplication

  - volFieldValue:
    * 0-N scalar fields

  - surfaceFieldValue:
    * 0-N scalar fields
    * 0-1 vector fields

  In some cases this can be used to avoid creating additional
  fields.

      weightFields  (rho U);
  vs.
      derivedFields (rhoU);
      weightField   rhoU;
This commit is contained in:
Mark Olesen 2020-11-24 17:03:00 +01:00
parent f8d08a805b
commit ab692caf7c
7 changed files with 189 additions and 53 deletions

View File

@ -645,9 +645,14 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::writeFileHeader
writeHeaderValue(os, "Area", totalArea_);
writeHeaderValue(os, "Scale factor", scaleFactor_);
if (weightFieldName_ != "none")
if (weightFieldNames_.size())
{
writeHeaderValue(os, "Weight field", weightFieldName_);
writeHeaderValue
(
os,
"Weight field",
flatOutput(weightFieldNames_, FlatOutput::BareComma{})
);
}
writeCommented(os, "Time");
@ -915,7 +920,7 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::surfaceFieldValue
needsUpdate_(true),
writeArea_(false),
selectionNames_(),
weightFieldName_("none"),
weightFieldNames_(),
totalArea_(0),
nFaces_(0),
faceId_(),
@ -949,7 +954,7 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::surfaceFieldValue
needsUpdate_(true),
writeArea_(false),
selectionNames_(),
weightFieldName_("none"),
weightFieldNames_(),
totalArea_(0),
nFaces_(0),
faceId_(),
@ -971,7 +976,8 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::read
needsUpdate_ = true;
writeArea_ = dict.getOrDefault("writeArea", false);
weightFieldName_ = "none";
weightFieldNames_.clear();
totalArea_ = 0;
nFaces_ = 0;
faceId_.clear();
@ -1054,11 +1060,29 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::read
<< exit(FatalIOError);
}
if (dict.readIfPresent("weightField", weightFieldName_))
// Can have "weightFields" or "weightField"
bool missing = true;
if (dict.readIfPresent("weightFields", weightFieldNames_))
{
Info<< " weight field = " << weightFieldName_ << nl;
missing = false;
}
else
{
weightFieldNames_.resize(1);
if (dict.readIfPresent("weightField", weightFieldNames_.first()))
{
missing = false;
if ("none" == weightFieldNames_.first())
{
// "none" == no weighting
weightFieldNames_.clear();
}
}
}
if (missing)
{
// Suggest possible alternative unweighted operation?
FatalIOErrorInFunction(dict)
@ -1069,6 +1093,16 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::read
<< "or use a different operation."
<< exit(FatalIOError);
}
Info<< " weight field = ";
if (weightFieldNames_.empty())
{
Info<< "none" << nl;
}
else
{
Info<< flatOutput(weightFieldNames_) << nl;
}
}
// Backwards compatibility for v1612 and older
@ -1177,46 +1211,79 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::write()
}
}
// Only a few weight types (scalar, vector)
if (weightFieldName_ != "none")
// Check availability and type of weight field
// Only support a few weight types:
// scalar: 0-N fields
// vector: 0-1 fields
// Default is a zero-size scalar weight field (ie, weight = 1)
scalarField scalarWeights;
vectorField vectorWeights;
for (const word& weightName : weightFieldNames_)
{
if (validField<scalar>(weightFieldName_))
if (validField<scalar>(weightName))
{
scalarField weightField
(
getFieldValues<scalar>(weightFieldName_, true)
);
tmp<scalarField> tfld = getFieldValues<scalar>(weightName, true);
// Process the fields
writeAll(Sf, weightField, points, faces);
if (scalarWeights.empty())
{
scalarWeights = tfld;
}
else
{
scalarWeights *= tfld;
}
}
else if (validField<vector>(weightFieldName_))
else if (validField<vector>(weightName))
{
vectorField weightField
(
getFieldValues<vector>(weightFieldName_, true)
);
tmp<vectorField> tfld = getFieldValues<vector>(weightName, true);
// Process the fields
writeAll(Sf, weightField, points, faces);
if (vectorWeights.empty())
{
vectorWeights = tfld;
}
else
{
FatalErrorInFunction
<< "weightField " << weightName
<< " - only one vector weight field allowed. " << nl
<< "weights: " << flatOutput(weightFieldNames_) << nl
<< abort(FatalError);
}
}
else
else if (weightName != "none")
{
// Silently ignore "none", flag everything else as an error
// TBD: treat missing "rho" like incompressible with rho = 1
// and/or provided rhoRef value
FatalErrorInFunction
<< "weightField " << weightFieldName_
<< " not found or an unsupported type"
<< "weightField " << weightName
<< " not found or an unsupported type" << nl
<< abort(FatalError);
}
}
// Process the fields
if (vectorWeights.size())
{
if (scalarWeights.size())
{
vectorWeights *= scalarWeights;
}
writeAll(Sf, vectorWeights, points, faces);
}
else
{
// Default is a zero-size scalar weight field (ie, weight = 1)
scalarField weightField;
// Process the fields
writeAll(Sf, weightField, points, faces);
writeAll(Sf, scalarWeights, points, faces);
}
if (operation_ != opNone)
{
file() << endl;

View File

@ -84,7 +84,7 @@ Usage
names (<zone-name> <zone-regex>);
postOperation none;
weightField alpha1;
weightFields (rho U);
scaleFactor 1.0;
writeArea false;
surfaceFormat none;
@ -105,7 +105,8 @@ Usage
names | Extended selection | word/regex list | no | -
operation | Operation type: see below | word | yes | -
postOperation | Post-operation type: see below | word | no | none
weightField | Name of field to apply weighting | word | no | none
weightField | Name of field to apply weighting | word | maybe |
weightFields | Names of fields to apply weighting | wordList | maybe |
scaleFactor | Output value scaling factor | scalar | no | 1.0
writeArea | Write the surface area | bool | no | false
surfaceFormat | Output value format | word <!--
@ -403,8 +404,8 @@ protected:
//- Extended selections
wordRes selectionNames_;
//- Weight field name - optional
word weightFieldName_;
//- Weight field name(s) - optional
wordList weightFieldNames_;
//- Total area of the surfaceFieldValue
scalar totalArea_;

View File

@ -118,7 +118,7 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::getFieldValues
if (mandatory)
{
FatalErrorInFunction
<< "Field " << fieldName << " not found in database"
<< "Field " << fieldName << " not found in database" << nl
<< abort(FatalError);
}

View File

@ -135,9 +135,15 @@ void Foam::functionObjects::fieldValues::volFieldValue::writeFileHeader
) const
{
volRegion::writeFileHeader(*this, os);
if (weightFieldName_ != "none")
if (weightFieldNames_.size())
{
writeHeaderValue(os, "Weight field", weightFieldName_);
writeHeaderValue
(
os,
"Weight field",
flatOutput(weightFieldNames_, FlatOutput::BareComma{})
);
}
writeCommented(os, "Time");
@ -210,7 +216,7 @@ Foam::functionObjects::fieldValues::volFieldValue::volFieldValue
true // Failsafe behaviour
)
),
weightFieldName_("none")
weightFieldNames_()
{
read(dict);
writeFileHeader(file());
@ -237,7 +243,7 @@ Foam::functionObjects::fieldValues::volFieldValue::volFieldValue
true // Failsafe behaviour
)
),
weightFieldName_("none")
weightFieldNames_()
{
read(dict);
}
@ -252,15 +258,33 @@ bool Foam::functionObjects::fieldValues::volFieldValue::read
{
fieldValue::read(dict);
weightFieldName_ = "none";
weightFieldNames_.clear();
if (usesWeight())
{
if (dict.readIfPresent("weightField", weightFieldName_))
// Can have "weightFields" or "weightField"
bool missing = true;
if (dict.readIfPresent("weightFields", weightFieldNames_))
{
Info<< " weight field = " << weightFieldName_;
missing = false;
}
else
{
weightFieldNames_.resize(1);
if (dict.readIfPresent("weightField", weightFieldNames_.first()))
{
missing = false;
if ("none" == weightFieldNames_.first())
{
// "none" == no weighting
weightFieldNames_.clear();
}
}
}
if (missing)
{
// Suggest possible alternative unweighted operation?
FatalIOErrorInFunction(dict)
@ -271,6 +295,16 @@ bool Foam::functionObjects::fieldValues::volFieldValue::read
<< "or use a different operation."
<< exit(FatalIOError);
}
Info<< " weight field = ";
if (weightFieldNames_.empty())
{
Info<< "none" << nl;
}
else
{
Info<< flatOutput(weightFieldNames_) << nl;
}
}
Info<< nl << endl;
@ -297,14 +331,45 @@ bool Foam::functionObjects::fieldValues::volFieldValue::write()
V = filterField(fieldValue::mesh_.V());
}
// Weight field - zero-size means weight = 1
scalarField weightField;
if (weightFieldName_ != "none")
// Check availability and type of weight field
// Only support a few weight types:
// scalar: 0-N fields
// Default is a zero-size scalar weight field (ie, weight = 1)
scalarField scalarWeights;
for (const word& weightName : weightFieldNames_)
{
weightField = getFieldValues<scalar>(weightFieldName_, true);
if (validField<scalar>(weightName))
{
tmp<scalarField> tfld = getFieldValues<scalar>(weightName, true);
if (scalarWeights.empty())
{
scalarWeights = tfld;
}
else
{
scalarWeights *= tfld;
}
}
else if (weightName != "none")
{
// Silently ignore "none", flag everything else as an error
// TBD: treat missing "rho" like incompressible with rho = 1
// and/or provided rhoRef value
FatalErrorInFunction
<< "weightField " << weightName
<< " not found or an unsupported type" << nl
<< abort(FatalError);
}
}
writeAll(V, weightField);
// Process the fields
writeAll(V, scalarWeights);
if (Pstream::master())
{

View File

@ -69,7 +69,8 @@ Usage
name | Name for regionType | word | yes | -
operation | Operation type: see below | word | yes | -
postOperation | Post-operation type: see below | word | no | none
weightField | Name of field to apply weighting | word | no | none
weightField | Name of field to apply weighting | word | maybe |
weightFields | Names of fields to apply weighting | wordList | maybe |
\endtable
The inherited entries are elaborated in:
@ -214,8 +215,8 @@ protected:
//- Optional post-evaluation operation
postOperationType postOperation_;
//- Weight field name - only used for weighted modes
word weightFieldName_;
//- Weight field name(s) - optional
wordList weightFieldNames_;
// Protected Member Functions
@ -233,7 +234,7 @@ protected:
// Checks for availability on any processor.
inline bool canWeight(const scalarField& weightField) const;
//- True if the field name is valid (exists, and a supported type)
//- Return true if the field name is valid
template<class Type>
bool validField(const word& fieldName) const;

View File

@ -71,7 +71,7 @@ Foam::functionObjects::fieldValues::volFieldValue::getFieldValues
if (mandatory)
{
FatalErrorInFunction
<< "Field " << fieldName << " not found in database"
<< "Field " << fieldName << " not found in database" << nl
<< abort(FatalError);
}

View File

@ -182,6 +182,7 @@ areaAverage
operation weightedAreaAverage;
weightField rhoU;
weightFields ( rho U none ); // 2012 and later
fields ( p pTotal );
}
@ -194,6 +195,7 @@ areaIntegrate
operation weightedAreaIntegrate;
weightField rhoU;
weightFields ( rho U ); // 2012 and later
fields ( T );
}