mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: norm: add new field function object
The 'norm' function object normalises an input field with a chosen norm, and outputs a new normalised field.
This commit is contained in:
@ -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
|
||||
|
||||
142
src/functionObjects/field/norm/norm.C
Normal file
142
src/functionObjects/field/norm/norm.C
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
285
src/functionObjects/field/norm/norm.H
Normal file
285
src/functionObjects/field/norm/norm.H
Normal 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
|
||||
|
||||
// ************************************************************************* //
|
||||
160
src/functionObjects/field/norm/normImpl.C
Normal file
160
src/functionObjects/field/norm/normImpl.C
Normal 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_);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user