surfaceFieldValue: Ouput as correct primitive type

If the surfaceFieldValue function object is used to compute an
area-normal average or integral of a vector quantity, the result will
now be correctly written out as a scalar.

Previously surfaceFieldValue was limited to writing the same type as the
input field. A vector area-normal average or integral therefore had to
be written out as a vector. This was done by setting the x component to
the result, and the y and z components to zero. This was considered to
be counter-intuitive.
This commit is contained in:
Will Bainbridge
2021-01-08 13:08:28 +00:00
parent 476bce93ce
commit 34cbcd444d
3 changed files with 210 additions and 131 deletions

View File

@ -564,13 +564,12 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::writeFileHeader
}
template<>
Foam::scalar Foam::functionObjects::fieldValues::surfaceFieldValue::
processValues
bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
(
const Field<scalar>& values,
const vectorField& Sf,
const scalarField& weightField
const scalarField& weightField,
scalar& result
) const
{
switch (operation_)
@ -578,31 +577,59 @@ processValues
case operationType::sumDirection:
{
vector n(dict_.lookup("direction"));
return sum(pos0(values*(Sf & n))*mag(values));
result = sum(pos0(values*(Sf & n))*mag(values));
return true;
}
case operationType::sumDirectionBalance:
{
vector n(dict_.lookup("direction"));
const scalarField nv(values*(Sf & n));
return sum(pos0(nv)*mag(values) - neg(nv)*mag(values));
result = sum(pos0(nv)*mag(values) - neg(nv)*mag(values));
return true;
}
default:
{
// Fall through to other operations
return processSameTypeValues(values, Sf, weightField);
// Fall through to same-type operations
return processValuesTypeType(values, Sf, weightField, result);
}
}
}
template<>
Foam::vector Foam::functionObjects::fieldValues::surfaceFieldValue::
processValues
bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
(
const Field<vector>& values,
const vectorField& Sf,
const scalarField& weightField
const scalarField& weightField,
scalar& result
) const
{
switch (operation_)
{
case operationType::areaNormalAverage:
{
result = sum(values & Sf)/sum(mag(Sf));
return true;
}
case operationType::areaNormalIntegrate:
{
result = sum(values & Sf);
return true;
}
default:
{
return false;
}
}
}
bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
(
const Field<vector>& values,
const vectorField& Sf,
const scalarField& weightField,
vector& result
) const
{
switch (operation_)
@ -612,31 +639,21 @@ processValues
vector n(dict_.lookup("direction"));
n /= mag(n) + rootVSmall;
const scalarField nv(n & values);
return sum(pos0(nv)*n*(nv));
result = sum(pos0(nv)*n*(nv));
return true;
}
case operationType::sumDirectionBalance:
{
vector n(dict_.lookup("direction"));
n /= mag(n) + rootVSmall;
const scalarField nv(n & values);
return sum(pos0(nv)*n*(nv));
}
case operationType::areaNormalAverage:
{
scalar result = sum(values & Sf)/sum(mag(Sf));
return vector(result, 0.0, 0.0);
}
case operationType::areaNormalIntegrate:
{
scalar result = sum(values & Sf);
return vector(result, 0.0, 0.0);
result = sum(pos0(nv)*n*(nv));
return true;
}
default:
{
// Fall through to other operations
return processSameTypeValues(values, Sf, weightField);
// Fall through to same-type operations
return processValuesTypeType(values, Sf, weightField, result);
}
}
}
@ -792,8 +809,7 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::write()
bool orient = i >= orientedFieldsStart_;
ok = ok || writeValues<scalar>(fieldName, weightField, orient);
ok = ok || writeValues<vector>(fieldName, weightField, orient);
ok = ok
|| writeValues<sphericalTensor>(fieldName, weightField, orient);
ok = ok || writeValues<sphericalTensor>(fieldName, weightField, orient);
ok = ok || writeValues<symmTensor>(fieldName, weightField, orient);
ok = ok || writeValues<tensor>(fieldName, weightField, orient);

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -332,24 +332,67 @@ protected:
const bool applyOrientation = false
) const;
//- Apply the 'operation' to the values. Operation has to
// preserve Type.
template<class Type>
Type processSameTypeValues
//- Apply the operation to the values, and return true if successful.
// Does nothing unless overloaded below.
template<class Type, class ResultType>
bool processValues
(
const Field<Type>& values,
const vectorField& Sf,
const scalarField& weightField
const scalarField& weightField,
ResultType& result
) const;
//- Apply the 'operation' to the values. Wrapper around
// processSameTypeValues. See also template specialisation below.
//- Apply Type -> Type operation to the values. Calls
// processValuesTypeType.
template<class Type>
Type processValues
bool processValues
(
const Field<Type>& values,
const vectorField& Sf,
const scalarField& weightField
const scalarField& weightField,
Type& result
) const;
//- Apply scalar -> scalar operation to the values. Tries to apply
// scalar -> scalar specific operations, otherwise calls
// processValuesTypeType.
bool processValues
(
const Field<scalar>& values,
const vectorField& Sf,
const scalarField& weightField,
scalar& result
) const;
//- Apply vector -> vector operation to the values.
bool processValues
(
const Field<vector>& values,
const vectorField& Sf,
const scalarField& weightField,
scalar& result
) const;
//- Apply vector -> vector operation to the values. Tries to apply
// vector -> vector specific operations, otherwise calls
// processValuesTypeType.
bool processValues
(
const Field<vector>& values,
const vectorField& Sf,
const scalarField& weightField,
vector& result
) const;
//- Apply a Type -> Type operation to the values
template<class Type>
bool processValuesTypeType
(
const Field<Type>& values,
const vectorField& Sf,
const scalarField& weightField,
Type& result
) const;
//- Output file header information
@ -411,6 +454,16 @@ public:
const bool orient
);
//- Templated helper function to output field values
template<class Type, class ResultType>
bool writeValues
(
const word& fieldName,
const scalarField& weightField,
const Field<Type>& values,
const vectorField& Sf
);
//- Filter a surface field according to faceIds
template<class Type>
tmp<Field<Type>> filterField
@ -435,26 +488,6 @@ public:
};
//- Specialisation for scalar
template<>
scalar surfaceFieldValue::processValues
(
const Field<scalar>& values,
const vectorField& Sf,
const scalarField& weightField
) const;
//- Specialisation for vector
template<>
vector surfaceFieldValue::processValues
(
const Field<vector>& values,
const vectorField& Sf,
const scalarField& weightField
) const;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fieldValues

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -132,22 +132,48 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::getFieldValues
}
template<class Type>
Type Foam::functionObjects::fieldValues::surfaceFieldValue::
processSameTypeValues
template<class Type, class ResultType>
bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
(
const Field<Type>& values,
const vectorField& Sf,
const scalarField& weightField
const scalarField& weightField,
ResultType& result
) const
{
return false;
}
template<class Type>
bool Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
(
const Field<Type>& values,
const vectorField& Sf,
const scalarField& weightField,
Type& result
) const
{
return processValuesTypeType(values, Sf, weightField, result);
}
template<class Type>
bool Foam::functionObjects::fieldValues::surfaceFieldValue::
processValuesTypeType
(
const Field<Type>& values,
const vectorField& Sf,
const scalarField& weightField,
Type& result
) const
{
Type result = Zero;
switch (operation_)
{
case operationType::sum:
{
result = sum(values);
break;
return true;
}
case operationType::weightedSum:
{
@ -159,39 +185,17 @@ processSameTypeValues
{
result = sum(values);
}
break;
return true;
}
case operationType::sumMag:
{
result = sum(cmptMag(values));
break;
}
case operationType::sumDirection:
{
FatalErrorInFunction
<< "Operation " << operationTypeNames_[operation_]
<< " not available for values of type "
<< pTraits<Type>::typeName
<< exit(FatalError);
result = Zero;
break;
}
case operationType::sumDirectionBalance:
{
FatalErrorInFunction
<< "Operation " << operationTypeNames_[operation_]
<< " not available for values of type "
<< pTraits<Type>::typeName
<< exit(FatalError);
result = Zero;
break;
return true;
}
case operationType::average:
{
result = sum(values)/values.size();
break;
return true;
}
case operationType::weightedAverage:
{
@ -205,14 +209,14 @@ processSameTypeValues
{
result = sum(values)/values.size();
}
break;
return true;
}
case operationType::areaAverage:
{
const scalarField magSf(mag(Sf));
result = sum(magSf*values)/sum(magSf);
break;
return true;
}
case operationType::weightedAreaAverage:
{
@ -228,14 +232,14 @@ processSameTypeValues
{
result = sum(magSf*values)/sum(magSf);
}
break;
return true;
}
case operationType::areaIntegrate:
{
const scalarField magSf(mag(Sf));
result = sum(magSf*values);
break;
return true;
}
case operationType::weightedAreaIntegrate:
{
@ -249,17 +253,17 @@ processSameTypeValues
{
result = sum(magSf*values);
}
break;
return true;
}
case operationType::min:
{
result = min(values);
break;
return true;
}
case operationType::max:
{
result = max(values);
break;
return true;
}
case operationType::CoV:
{
@ -278,33 +282,20 @@ processSameTypeValues
res = sqrt(sum(magSf*sqr(vals - mean))/sum(magSf))/mean;
}
break;
return true;
}
case operationType::areaNormalAverage:
{}
case operationType::areaNormalIntegrate:
{}
case operationType::none:
{}
{
return true;
}
default:
{
return false;
}
}
return result;
}
template<class Type>
Type Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
(
const Field<Type>& values,
const vectorField& Sf,
const scalarField& weightField
) const
{
return processSameTypeValues(values, Sf, weightField);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
@ -374,16 +365,26 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::writeValues
if (Pstream::master())
{
Type result = processValues(values, Sf, weightField);
// Add to result dictionary, over-writing any previous entry
resultDict_.add(fieldName, result, true);
file() << tab << result;
Log << " " << operationTypeNames_[operation_]
<< "(" << regionName_ << ") of " << fieldName
<< " = " << result << endl;
if
(
!writeValues<Type, scalar>
(fieldName, weightField, values, Sf)
&& !writeValues<Type, vector>
(fieldName, weightField, values, Sf)
&& !writeValues<Type, sphericalTensor>
(fieldName, weightField, values, Sf)
&& !writeValues<Type, symmTensor>
(fieldName, weightField, values, Sf)
&& !writeValues<Type, tensor>
(fieldName, weightField, values, Sf)
)
{
FatalErrorInFunction
<< "Operation " << operationTypeNames_[operation_]
<< " not available for values of type "
<< pTraits<Type>::typeName
<< exit(FatalError);
}
}
}
}
@ -392,6 +393,35 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::writeValues
}
template<class Type, class ResultType>
bool Foam::functionObjects::fieldValues::surfaceFieldValue::writeValues
(
const word& fieldName,
const scalarField& weightField,
const Field<Type>& values,
const vectorField& Sf
)
{
ResultType result;
if (processValues(values, Sf, weightField, result))
{
// Add to result dictionary, over-writing any previous entry
resultDict_.add(fieldName, result, true);
file() << tab << result;
Log << " " << operationTypeNames_[operation_]
<< "(" << regionName_ << ") of " << fieldName
<< " = " << result << endl;
return true;
}
return false;
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::functionObjects::fieldValues::surfaceFieldValue::filterField