functionObjects: fieldsExpression: Type flexibility and new operations

The fieldsExpression function has been generalised to work with a
general operator. Existing functions "add" and "subtract" have been made
to use this system, and two new operations, "multiply" and "divide",
have been added.

The functions can now handle multiple types in both input and output. A
multiply (outer product) operation on two vectors and a scalar will
result in a tensor. If the operation chain is not supported (e.g.,
division by a vector) then a warning will be generated.

In addition, a "uniform" function has been added, which will create a
uniform geometric field of a given type with specified dimensions and
calculated boundary conditions. This is mostly useful for testing
purposes and for conveniently creating simple input fields for the
operation functions described above. The function can be called by
postProcess as follows:

    postProcess -func "uniform(fieldType=volScalarField, name=length, dimensions=[m], value=2)"
This commit is contained in:
Will Bainbridge
2021-07-08 13:49:21 +01:00
parent 056cc20f34
commit 0b68176c60
18 changed files with 968 additions and 150 deletions

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2016-2019 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2016-2021 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -127,9 +127,38 @@ bool Foam::functionObjects::fieldsExpression::execute()
{
if (!calc())
{
Warning
<< " functionObjects::" << type() << " " << name()
<< " cannot find required fields " << fieldNames_ << endl;
DynamicList<word> notFoundFieldNames;
forAll(fieldNames_, i)
{
bool found = false;
#define findFieldType(Type, GeoField) \
found = \
found \
|| mesh_.foundObject<GeoField<Type>>(fieldNames_[i]);
FOR_ALL_FIELD_TYPES(findFieldType, VolField);
FOR_ALL_FIELD_TYPES(findFieldType, SurfaceField);
#undef findFieldType
if (!found)
{
notFoundFieldNames.append(fieldNames_[i]);
}
}
if (!notFoundFieldNames.empty())
{
Warning
<< "functionObjects::" << type() << " " << name()
<< " cannot find fields " << notFoundFieldNames << endl;
}
else
{
Warning
<< "functionObjects::" << type() << " " << name()
<< " fields are not compatible with the " << type()
<< " function" << endl;
}
// Clear the result fields from the objectRegistry if present
clear();

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2012-2020 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2012-2021 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -68,26 +68,74 @@ protected:
// Protected member functions
//- Set the result name
void setResultName
(
const word& functionName,
const wordList& defaultFieldNames = wordList::null()
);
//- Call 'calcFieldType' for the given functionObject
// for 'volField' and 'surfaceField' field types
template<class Type, class FOType>
bool calcFieldTypes(FOType& fo);
//- Operate on the fields and store the result. Supported overload.
template
<
template<class> class GeoField,
template<class ...> class Op,
class TypeA,
class TypeB,
class Enable = Op<TypeA, TypeB>
>
bool opAndStore
(
const GeoField<TypeA>& a,
const GeoField<TypeB>& b
);
//- Call 'calcFieldTypes' for the given 'Type' and functionObject
template<class Type, class FOType>
bool calcType(FOType& fo);
//- Operate on the fields and store the result. Not-supported overload.
template
<
template<class> class GeoField,
template<class ...> class Op,
class ... Args
>
bool opAndStore(const Args& ...);
//- Call 'calcType' for the given functionObject
// for each primitive type
template<class FOType>
bool calcAllTypes(FOType& fo);
//- Fold the fields expression up one place
template
<
template<class> class GeoField,
template<class ...> class Op,
class TypeA,
class TypeB
>
bool foldAB(const label i);
//- Fold the fields expression up one place
template
<
template<class> class GeoField,
template<class ...> class Op,
class TypeA
>
bool foldA(const label i);
//- Fold the fields expression up one place
template
<
template<class> class GeoField,
template<class ...> class Op
>
bool fold(const label i);
//- Calculate and store the fields expression for the given geometric
// field type and operation
template<template<class> class GeoField, template<class ...> class Op>
bool calcGeoFieldOp();
//- Calculate and store the fields expression for the given operation
template<template<class ...> class Op>
bool calcOp();
//- Perform calculation on the list of fields and return success
virtual bool calc() = 0;

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2016-2020 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2016-2021 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -23,57 +23,142 @@ License
\*---------------------------------------------------------------------------*/
#include "fieldsExpression.H"
#include "volFields.H"
#include "surfaceFields.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class Type, class FOType>
bool Foam::functionObjects::fieldsExpression::calcFieldTypes(FOType& fo)
template
<
template<class> class GeoField,
template<class ...> class Op,
class TypeA,
class TypeB,
class Enable
>
bool Foam::functionObjects::fieldsExpression::opAndStore
(
const GeoField<TypeA>& a,
const GeoField<TypeB>& b
)
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
if (foundObject<VolFieldType>(fieldNames_[0]))
{
return store
(
resultName_,
fo.template calcFieldType<VolFieldType>()
);
}
else if (foundObject<SurfaceFieldType>(fieldNames_[0]))
{
return store
(
resultName_,
fo.template calcFieldType<SurfaceFieldType>()
);
}
else
{
return false;
}
return store(resultName_, Op<GeoField<TypeA>, GeoField<TypeB>>()(a, b));
}
template<class Type, class FOType>
bool Foam::functionObjects::fieldsExpression::calcType(FOType& fo)
template
<
template<class> class GeoField,
template<class ...> class Op,
class ... Args
>
bool Foam::functionObjects::fieldsExpression::opAndStore
(
const Args& ...
)
{
return calcFieldTypes<Type>(fo);
return false;
}
template<class FOType>
bool Foam::functionObjects::fieldsExpression::calcAllTypes(FOType& fo)
template
<
template<class> class GeoField,
template<class ...> class Op,
class TypeA,
class TypeB
>
bool Foam::functionObjects::fieldsExpression::foldAB(const label i)
{
bool processed = false;
if
(
i == 0
&& foundObject<GeoField<TypeA>>(fieldNames_[0])
)
{
clearObject(resultName_);
return store
(
resultName_,
lookupObject<GeoField<TypeA>>(fieldNames_[0]).clone()
);
}
#define processType(fieldType, none) \
processed = processed || fo.template calcType<fieldType>(fo);
FOR_ALL_FIELD_TYPES(processType)
if
(
i > 0
&& foundObject<GeoField<TypeA>>(resultName_)
&& foundObject<GeoField<TypeB>>(fieldNames_[i])
)
{
tmp<GeoField<TypeA>> a =
lookupObject<GeoField<TypeA>>(resultName_).clone();
const GeoField<TypeB>& b =
lookupObject<GeoField<TypeB>>(fieldNames_[i]);
return processed;
clearObject(resultName_);
return opAndStore<GeoField, Op>(a(), b);
}
return false;
}
template
<
template<class> class GeoField,
template<class ...> class Op,
class TypeA
>
bool Foam::functionObjects::fieldsExpression::foldA(const label i)
{
bool success = false;
#define processType(Type, none) \
success = success || foldAB<GeoField, Op, TypeA, Type>(i);
FOR_ALL_FIELD_TYPES(processType);
#undef processType
return success;
}
template<template<class> class GeoField, template<class ...> class Op>
bool Foam::functionObjects::fieldsExpression::fold(const label i)
{
bool success = false;
#define processType(Type, none) \
success = success || foldA<GeoField, Op, Type>(i);
FOR_ALL_FIELD_TYPES(processType);
#undef processType
return success;
}
template<template<class> class GeoField, template<class ...> class Op>
bool Foam::functionObjects::fieldsExpression::calcGeoFieldOp()
{
forAll(fieldNames_, i)
{
if (!fold<GeoField, Op>(i))
{
return false;
}
}
return true;
}
template<template<class ...> class Op>
bool Foam::functionObjects::fieldsExpression::calcOp()
{
return
calcGeoFieldOp<VolField, Op>()
|| calcGeoFieldOp<SurfaceField, Op>();
}