Merge branch 'feature-norm-function-object' into 'develop'

ENH: norm: add new field function object

See merge request Development/openfoam!539
This commit is contained in:
Andrew Heather
2022-05-27 11:58:43 +00:00
58 changed files with 743 additions and 53 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -518,6 +518,21 @@ Foam::dimensionSet Foam::hypot(const dimensionSet& ds1, const dimensionSet& ds2)
}
Foam::dimensionSet Foam::stabilise
(
const dimensionSet& ds1,
const dimensionSet& ds2
)
{
if (dimensionSet::checking())
{
checkDims("stabilise(a, b)", ds1, ds2);
}
return ds1;
}
Foam::dimensionSet Foam::transform(const dimensionSet& ds)
{
return ds;

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -397,6 +397,9 @@ dimensionSet atan2(const dimensionSet& ds1, const dimensionSet& ds2);
//- Arguments need the same dimensions. Does not change the dimension.
dimensionSet hypot(const dimensionSet& ds1, const dimensionSet& ds2);
//- Arguments need the same dimensions. Does not change the dimension.
dimensionSet stabilise(const dimensionSet& ds1, const dimensionSet& ds2);
//- Return the argument; transformations do not change the dimensions
dimensionSet transform(const dimensionSet& ds);

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -338,6 +338,21 @@ dimensionedScalar hypot
}
dimensionedScalar stabilise
(
const dimensionedScalar& x,
const dimensionedScalar& y
)
{
return dimensionedScalar
(
"stabilise(" + x.name() + ',' + y.name() + ')',
stabilise(x.dimensions(), y.dimensions()),
stabilise(x.value(), y.value())
);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -102,6 +102,7 @@ dimensionedScalar jn(const int, const dimensionedScalar&);
dimensionedScalar y0(const dimensionedScalar&);
dimensionedScalar y1(const dimensionedScalar&);
dimensionedScalar yn(const int, const dimensionedScalar&);
dimensionedScalar stabilise(const dimensionedScalar&, const dimensionedScalar&);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -84,6 +84,7 @@ Curle/Curle.C
reference/reference.C
log/log.C
pow/pow.C
norm/norm.C
fieldsExpression/fieldsExpression.C
add/add.C

View File

@ -0,0 +1,142 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "norm.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
defineTypeNameAndDebug(norm, 0);
addToRunTimeSelectionTable(functionObject, norm, dictionary);
}
}
const Foam::Enum
<
Foam::functionObjects::norm::normType
>
Foam::functionObjects::norm::normTypeNames
({
{ normType::L1 , "L1" },
{ normType::L2 , "L2" },
{ normType::LP , "Lp" },
{ normType::MAX , "max" },
{ normType::COMPOSITE , "composite" },
{ normType::FIELD , "divisorField" }
});
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Implementation
#include "normImpl.C"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::functionObjects::norm::calc()
{
return
(
calcNorm<scalar>()
|| calcNorm<vector>()
|| calcNorm<sphericalTensor>()
|| calcNorm<symmTensor>()
|| calcNorm<tensor>()
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::norm::norm
(
const word& name,
const Time& runTime,
const dictionary& dict
)
:
fieldExpression(name, runTime, dict),
norm_(normType::L1),
divisorPtr_(nullptr),
divisorFieldName_(word::null),
p_(-1)
{
read(dict);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::functionObjects::norm::read(const dictionary& dict)
{
if (!fieldExpression::read(dict))
{
return false;
}
norm_ = normTypeNames.get("norm", dict);
if (norm_ == normType::LP)
{
p_ = dict.getCheck<scalar>("p", scalarMinMax::ge(1));
}
if (norm_ == normType::COMPOSITE)
{
divisorPtr_ = Function1<scalar>::New("divisor", dict, &mesh_);
if (!divisorPtr_)
{
FatalIOErrorInFunction(dict)
<< "The norm 'composite' needs the input entry 'divisor'."
<< abort(FatalIOError);
}
}
if (norm_ == normType::FIELD)
{
divisorFieldName_ = dict.get<word>("divisorField");
if (divisorFieldName_ == word::null)
{
FatalIOErrorInFunction(dict)
<< "The norm 'field' needs the input entry 'divisorField'."
<< abort(FatalIOError);
}
}
return true;
}
// ************************************************************************* //

View File

@ -0,0 +1,285 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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::functionObjects::norm
Group
grpFieldFunctionObjects
Description
Normalises an input field with a chosen norm,
and outputs a new normalised field.
Operands:
\table
Operand | Type | Location
input | {vol,surface,polySurface}\<Type\>Field <!--
--> | \<case\>/\<time\>/\<inpField\>
output file | - | -
output field | {vol,surface,polySurface}\<Type\>Field <!--
--> | \<case\>/\<time\>/\<outField\>
\endtable
where \c \<Type\>=Scalar/Vector/SphericalTensor/SymmTensor/Tensor.
Usage
Minimal example by using \c system/controlDict.functions:
\verbatim
norm1
{
// Mandatory entries
type norm;
libs (fieldFunctionObjects);
field <word>;
norm <word>;
// Conditional entries
// when norm == Lp
p <scalar>;
// when norm == composite
divisor <Function1<scalar>>;
// when norm == divisorField
divisorField <word>;
// Inherited entries
...
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Reqd | Deflt
type | Type name: norm | word | yes | -
libs | Library name: fieldFunctionObjects | word | yes | -
field | Name of the operand field | word | yes | -
norm | Name of normalisation operation | word | yes | -
p | Norm exponent for the p-norm | scalar | cndtnl | -
divisor | Norm divisor for the composite norm <!--
--> | Function1\<scalar\> | cndtnl | -
divisorField | Divisor scalar field for the field norm <!--
--> | word | cndtnl | -
\endtable
Options for the \c norm entry:
\verbatim
L1 | L1/Taxicab norm
L2 | L2/Euclidean norm
Lp | p norm
max | Maximum norm
composite | Composite norm comprising Function1 divisor
divisorField | Normalise by a given field
\endverbatim
The inherited entries are elaborated in:
- \link functionObject.H \endlink
- \link fieldExpression.H \endlink
- \link Function1.H \endlink
The normalisations are held according to the following expressions:
- \c L1:
\f[
\mathbf{y} = \frac{\mathbf{x}}{\Sigma_{i=1}^n |x_i|}
\f]
- \c L2:
\f[
\mathbf{y} = \frac{\mathbf{x}}{\sqrt{x_1^2 + ... + x_n^2}}
\f]
- \c Lp:
\f[
\mathbf{y} = \frac{\mathbf{x}}{(\Sigma_{i=1}^n |x_i|^p)^{1/p}}
\f]
- \c max:
\f[
\mathbf{y} = \frac{\mathbf{x}}{max|x_i|}
\f]
- \c composite:
\f[
\mathbf{y} = \frac{\mathbf{x}}{f(t)}
\f]
- \c divisorField:
\f[
\mathbf{y} = \frac{\mathbf{x}}{\mathbf{z}}
\f]
Note
- Divisor quantity is perturbed by \c SMALL value to prevent any divisions
by zero irrespective of whether the quantity is close to zero or not.
SourceFiles
norm.C
normImpl.C
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_norm_H
#define functionObjects_norm_H
#include "fieldExpression.H"
#include "Function1.H"
#include "polySurfaceFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
/*---------------------------------------------------------------------------*\
Class norm Declaration
\*---------------------------------------------------------------------------*/
class norm
:
public fieldExpression
{
// Private Enumerations
//- Options for the norm algorithm
enum normType : char
{
L1, //!< "L1/Taxicab norm"
L2, //!< "L2/Euclidean norm"
LP, //!< "p norm"
MAX, //!< "Maximum norm"
COMPOSITE, //!< "Composite norm"
FIELD //!< "Normalise by a given field"
};
//- Names for normType
static const Enum<normType> normTypeNames;
// Private Data
//- Norm algorithm
enum normType norm_;
//- Norm divisor for the composite norm
autoPtr<Function1<scalar>> divisorPtr_;
//- Divisor scalar field for the field norm
word divisorFieldName_;
//- Norm exponent for the p norm
scalar p_;
// Private Member Functions
//- Calculate the chosen norm of the field and register the result
template<class Type>
bool calcNorm();
//- Return the chosen norm of the field
template<class GeoFieldType>
tmp<GeoFieldType> calcNormType();
//- Return the divisor volScalarField
template<class Type>
tmp<volScalarField> fieldNorm
(
const GeometricField<Type, fvPatchField, volMesh>&
);
//- Return the divisor surfaceScalarField
template<class Type>
tmp<surfaceScalarField> fieldNorm
(
const GeometricField<Type, fvsPatchField, surfaceMesh>&
);
//- Return the divisor polySurfaceScalarField
template<class Type>
tmp<polySurfaceScalarField> fieldNorm
(
const DimensionedField<Type, polySurfaceGeoMesh>&
);
//- Calculate the chosen norm of the field and return true if successful
virtual bool calc();
public:
//- Runtime type information
TypeName("norm");
// Constructors
//- Construct from name, Time and dictionary
norm
(
const word& name,
const Time& runTime,
const dictionary& dict
);
//- No copy construct
norm(const norm&) = delete;
//- No copy assignment
void operator=(const norm&) = delete;
//- Destructor
virtual ~norm() = default;
// Member Functions
//- Read the dictionary data
virtual bool read(const dictionary&);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace functionObjects
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,160 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "volFields.H"
#include "surfaceFields.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
bool Foam::functionObjects::norm::calcNorm()
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, polySurfaceGeoMesh> SurfFieldType;
if (mesh_.foundObject<VolFieldType>(fieldName_))
{
return store
(
resultName_,
calcNormType<VolFieldType>()
);
}
else if (mesh_.foundObject<SurfaceFieldType>(fieldName_))
{
return store
(
resultName_,
calcNormType<SurfaceFieldType>()
);
}
else if (mesh_.foundObject<SurfFieldType>(fieldName_))
{
return store
(
resultName_,
calcNormType<SurfFieldType>()
);
}
return false;
}
template<class GeoFieldType>
Foam::tmp<GeoFieldType> Foam::functionObjects::norm::calcNormType()
{
const GeoFieldType& field = mesh_.lookupObject<GeoFieldType>(fieldName_);
const dimensionedScalar perturb(field.dimensions(), SMALL);
switch (norm_)
{
case normType::L1:
{
return field/stabilise(sumMag(field), perturb);
}
case normType::L2:
{
return field/stabilise(mag(field), perturb);
}
case normType::LP:
{
return
field
/stabilise
(
pow(pow(mag(field), p_), scalar(1)/p_),
perturb
);
}
case normType::MAX:
{
return field/stabilise(max(mag(field)), perturb);
}
case normType::COMPOSITE:
{
const scalar t = mesh_.time().timeOutputValue();
const dimensionedScalar divisor
(
field.dimensions(),
divisorPtr_->value(t)
);
return field/stabilise(divisor, perturb);
}
case normType::FIELD:
{
return field/stabilise(fieldNorm(field), perturb);
}
default:
break;
}
return nullptr;
}
template<class Type>
Foam::tmp<Foam::volScalarField> Foam::functionObjects::norm::fieldNorm
(
const GeometricField<Type, fvPatchField, volMesh>&
)
{
return mesh_.lookupObject<volScalarField>(divisorFieldName_);
}
template<class Type>
Foam::tmp<Foam::surfaceScalarField> Foam::functionObjects::norm::fieldNorm
(
const GeometricField<Type, fvsPatchField, surfaceMesh>&
)
{
return mesh_.lookupObject<surfaceScalarField>(divisorFieldName_);
}
template<class Type>
Foam::tmp<Foam::polySurfaceScalarField> Foam::functionObjects::norm::fieldNorm
(
const DimensionedField<Type, polySurfaceGeoMesh>&
)
{
return mesh_.lookupObject<polySurfaceScalarField>(divisorFieldName_);
}
// ************************************************************************* //

View File

@ -0,0 +1,68 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2112 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
norm_U_L1
{
// Mandatory entries
type norm;
libs (fieldFunctionObjects);
field U;
norm L1;
// Inherited entries
result norm_U_L1;
region region0;
enabled true;
log true;
timeStart 0;
timeEnd 1000;
executeControl writeTime;
writeControl writeTime;
}
norm_U_L2
{
$norm_U_L1;
norm L2;
result norm_U_L2;
}
norm_U_Lp
{
$norm_U_L1;
norm Lp;
p 3;
result norm_U_Lp;
}
norm_U_max
{
$norm_U_L1;
norm max;
result norm_U_max;
}
norm_U_composite
{
$norm_U_L1;
norm composite;
divisor constant 2;
result norm_U_composite;
}
norm_k_field
{
$norm_U_L1;
field k;
norm divisorField;
divisorField p;
result norm_k_field;
}
// ************************************************************************* //

View File

@ -48,57 +48,57 @@ runTimeModifiable true;
functions
{
// field function objects
#include "FOfieldAverage"
#include "FOadd"
#include "FOblendingFactor"
#include "FOcomponents"
#include "FOCourantNo"
#include "FOcontinuityError"
#include "FOddt"
#include "FOddt2"
#include "FOdiv"
#include "FOenstrophy"
#include "FOflowType"
#include "FOflux"
#include "FOgrad"
#include "FOhistogram"
#include "FOLambda2"
#include "FOLambVector"
#include "FOlimitFields"
#include "FOlog"
#include "FOmag"
#include "FOmagSqr"
#include "FOmultiFieldValue"
#include "FOmultiply"
#include "FOmomentum"
#include "FOnearWallFields"
#include "FOPecletNo"
#include "FOpressure"
#include "FOprocessorField"
#include "FOproudmanAcousticPower"
#include "FOpow"
#include "FOQ"
#include "FOrandomise"
#include "FOreadFields"
#include "FOsetFlow"
#include "FOstreamFunction"
#include "FOstreamLine"
#include "FOsubtract"
//#include "FOsurfaceDistance"
#include "FOsurfaceInterpolate"
#include "FOturbulenceFields"
#include "FOvalueAverage"
#include "FOvolFieldValue"
#include "FOvorticity"
#include "FOreference"
#include "FOwallShearStress"
#include "FOwriteCellCentres"
#include "FOwriteCellVolumes"
#include "FOyPlus"
#include "FOzeroGradient"
#include "FOs/FOfieldAverage"
#include "FOs/FOadd"
#include "FOs/FOblendingFactor"
#include "FOs/FOcomponents"
#include "FOs/FOCourantNo"
#include "FOs/FOcontinuityError"
#include "FOs/FOddt"
#include "FOs/FOddt2"
#include "FOs/FOdiv"
#include "FOs/FOenstrophy"
#include "FOs/FOflowType"
#include "FOs/FOflux"
#include "FOs/FOgrad"
#include "FOs/FOhistogram"
#include "FOs/FOLambda2"
#include "FOs/FOLambVector"
#include "FOs/FOlimitFields"
#include "FOs/FOlog"
#include "FOs/FOmag"
#include "FOs/FOmagSqr"
#include "FOs/FOmultiply"
#include "FOs/FOmomentum"
#include "FOs/FOnearWallFields"
#include "FOs/FOPecletNo"
#include "FOs/FOpressure"
#include "FOs/FOprocessorField"
#include "FOs/FOproudmanAcousticPower"
#include "FOs/FOpow"
#include "FOs/FOQ"
#include "FOs/FOrandomise"
#include "FOs/FOreadFields"
#include "FOs/FOsetFlow"
#include "FOs/FOstreamFunction"
#include "FOs/FOstreamLine"
#include "FOs/FOsubtract"
//#include "FOs/FOsurfaceDistance"
#include "FOs/FOsurfaceInterpolate"
#include "FOs/FOturbulenceFields"
#include "FOs/FOvalueAverage"
#include "FOs/FOvolFieldValue"
#include "FOs/FOvorticity"
#include "FOs/FOreference"
#include "FOs/FOwallShearStress"
#include "FOs/FOwriteCellCentres"
#include "FOs/FOwriteCellVolumes"
#include "FOs/FOyPlus"
#include "FOs/FOzeroGradient"
#include "FOs/FOnorm"
// utility function objects
#include "FOsolverInfo"
#include "FOs/FOsolverInfo"
}