Commit c6ee663e authored by Mark Olesen's avatar Mark Olesen

ENH: minMax, minMaxMag as functions and field functions

- Global functions are unary or combining binary functions, which are
  defined in MinMax.H (MinMaxOps.H).

  There are also global reduction functions (gMinMax, gMinMaxMag)
  as well as supporting 'Op' classes:

  - minMaxOp, minMaxEqOp, minMaxMagOp, minMaxMagEqOp

  Since the result of the functions represents a content reduction
  into a single MinMax<T> value (a min/max pair), field operations
  returning a field simply do not make sense.

- Implemented for lists, fields, field-fields, DimensionedField,
  GeometricField (parallel reducing, with boundaries).

- Since the minMax evaluates during its operation, this makes it more
  efficient for cases where both min/max values are required since it
  avoids looping twice through the data.

  * Changed GeometricField writeMinMax accordingly.

ENH: clip as field function

- clipping provides a more efficient, single-pass operation to apply
  lower/upper limits on single or multiple values.

  Examples,

    scalarMinMax limiter(0, 1);

    limiter.clip(value)

       -> returns a const-ref to the value if within the range, or else
          returns the appropriate lower/upper limit

    limiter.inplaceClip(value)

       -> Modifies the value if necessary to be within lower/upper limit

  Function calls

    clip(value, limiter)

       -> returns a copy after applying lower/upper limit

    clip(values, limiter)

       -> returns a tmp<Field> of clipped values
parent 97f273b1
......@@ -141,8 +141,8 @@ int main(int argc, char *argv[])
}
#include "rhoEqn.H"
Info<< "rhoEqn max/min : " << max(rho).value()
<< " " << min(rho).value() << endl;
Info<< "rho min/max : " << min(rho).value() << " " << max(rho).value()
<< endl;
// --- Pressure-velocity PIMPLE corrector loop
while (pimple.loop())
......
......@@ -121,8 +121,8 @@ int main(int argc, char *argv[])
}
#include "rhoEqn.H"
Info<< "rhoEqn max/min : " << max(rho).value()
<< " " << min(rho).value() << endl;
Info<< "rho min/max : " << min(rho).value() << " " << max(rho).value()
<< endl;
// --- Pressure-velocity PIMPLE corrector loop
while (pimple.loop())
......
......@@ -79,6 +79,6 @@
rho = thermo.rho();
rho.relax();
Info<< "rho max/min : " << max(rho).value() << " " << min(rho).value()
Info<< "rho min/max : " << min(rho).value() << " " << max(rho).value()
<< endl;
}
......@@ -97,8 +97,7 @@ rho = thermo.rho();
rho = max(rho, rhoMin);
rho = min(rho, rhoMax);
rho.relax();
Info<< "rho max/min : " << max(rho).value()
<< " " << min(rho).value() << endl;
Info<< "rho min/max : " << min(rho).value() << " " << max(rho).value() << endl;
U = HbyA - rAU*fvc::grad(p);
U.correctBoundaryConditions();
......
......@@ -97,8 +97,7 @@ rho = thermo.rho();
rho = max(rho, rhoMin);
rho = min(rho, rhoMax);
rho.relax();
Info<< "rho max/min : " << max(rho).value()
<< " " << min(rho).value() << endl;
Info<< "rho min/max : " << min(rho).value() << " " << max(rho).value() << endl;
U = HbyA - rAU*fvc::grad(p);
U.correctBoundaryConditions();
......
......@@ -138,7 +138,23 @@ int main(int argc, char *argv[])
minmax1 += values1;
Pout<<"range: " << minmax1 << endl;
Info<< "Reduced: "<< returnReduce(minmax1, plusOp<scalarMinMax>()) << nl;
Info<< "Reduced: "<< returnReduce(minmax1, minMaxOp<scalar>()) << nl;
// Info<< "gMinMax: "<< gMinMax(values1v) << nl;
vectorField values1v
(
ListOps::create<vector>
(
values1,
[](const scalar s) { return vector(s, 2*s, -2*s); }
)
);
Info<< "gMinMax: " << gMinMax(values1v) << nl;
Info<< "gMinMaxMag: " << gMinMaxMag(values1v) << nl;
{
MinMax<scalar> limiter(10, 200);
......@@ -159,13 +175,14 @@ int main(int argc, char *argv[])
Info<< "clipped : " << val << " = " << clip(val, limiter) << nl;
}
Info<< nl << "inplace clip" << nl;
Info<< nl << "test clip(Field) with limiter: " << limiter << nl;
Info<< "clipped : " << clip(values1, limiter) << nl;
scalarField values2(values1);
Info<< "before: " << flatOutput(values2) << nl;
Info<< nl << "inplace clip" << nl;
Info<< "before: " << flatOutput(values2) << nl;
Info<< "before " << flatOutput(values2) << nl;
for (scalar& val : values2)
{
......@@ -176,7 +193,9 @@ int main(int argc, char *argv[])
Info<< nl << "For list: " << flatOutput(values1) << nl
<< " minMax : " << minMax(values1) << nl
<< " minMaxMag : " << minMaxMag(values1) << nl;
<< " minMaxMag : " << minMaxMag(values1)
<< " = " << mag(minMaxMag(vector(1, 2, 3)))
<< nl;
}
......
Test-minMax2.C
EXE = $(FOAM_USER_APPBIN)/Test-minMax2
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-lmeshTools
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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/>.
Description
Test minMax
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "Time.H"
#include "BitOps.H"
#include "HashOps.H"
#include "ListOps.H"
#include "scalarField.H"
#include "MinMax.H"
#include "dimensionedScalar.H"
#include "dimensionedMinMax.H"
using namespace Foam;
template<class T>
Ostream& printInfo(const MinMax<T>& range)
{
Info<< range << " valid=" << range.valid();
return Info;
}
dimensionedScalarMinMax rhoLimit(const dictionary& dict)
{
Info<< "From " << dict;
dimensionedScalarMinMax range =
makeDimensionedMinMax<scalar>
(
"rhoLimit", dimDensity, scalarMinMax{Zero, GREAT}, dict,
"rhoMin", "rhoMax"
);
Info<< "=> " << range << nl;
return range;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noCheckProcessorDirectories();
#include "setRootCase.H"
Info<< "Test min/max " << nl;
{
scalarMinMax range1(10, 20);
scalarMinMax range2(40, 50);
Info<< range1 << " + " << range2 << " = " << (range1 + range2) <<nl;
}
{
Info<< "Dimensioned range : "
<< dimensioned<scalarMinMax>("velrange", dimVelocity, {1, 20})
<< nl;
dimensioned<scalarMinMax> range1("a", dimVelocity, {10, 20});
dimensioned<scalarMinMax> range2("b", dimVelocity, {40, 50});
Info<< "Dimensioned range : " << (range1 + range2) << endl;
}
{
Info<< nl << "makeDimensionedMinMax:" << nl << nl;
Info
<< makeDimensionedMinMax<scalar>("rhoa", dimDensity, 1, 20)
<< nl;
{
dimensionedScalar minval("min", dimDensity, 0.3);
dimensionedScalar maxval("max", dimDensity, 0.5);
Info
<< makeDimensionedMinMax<scalar>(minval, maxval)
<< nl;
Info
<< makeDimensionedMinMax<scalar>("rhob", minval, maxval)
<< nl;
}
{
dictionary dict1, dict2, dict3, dict4;
dict1.add("rhoMin", dimensionedScalar("", dimDensity, 0.1));
dict2.add("rhoMax", dimensionedScalar("", dimDensity, 20));
dict3.add("rhoMin", dimensionedScalar("", dimDensity, 0.3));
dict3.add("rhoMax", dimensionedScalar("", dimDensity, 30));
dict4.add
(
"rhoLimit",
dimensionedScalarMinMax("", dimDensity, scalarMinMax(0.4, 40))
);
rhoLimit(dict1);
rhoLimit(dict2);
rhoLimit(dict3);
rhoLimit(dict4);
}
}
return 0;
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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/>.
Typedef
Foam::dimensionedScalarMinMax
Description
A dimensioned scalarMinMix (MinMax for scalar quantities).
Typedef
Foam::dimensionedMinMax\<T\>
Description
A templated type alias for dimensioned\<MinMax\<T\>\>
SourceFiles
dimensionedMinMaxTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef dimensionedMinMax_H
#define dimensionedMinMax_H
#include "dimensionedType.H"
#include "MinMax.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// General alias
template<class T>
using dimensionedMinMax = dimensioned<MinMax<T>>;
// Common typedefs
typedef dimensioned<scalarMinMax> dimensionedScalarMinMax;
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
//- Make a dimensionedMinMax from all components
template<class T>
inline dimensioned<MinMax<T>> makeDimensionedMinMax
(
const word& name,
const dimensionSet& dims,
const T& minVal,
const T& maxVal
)
{
return dimensioned<MinMax<T>>(name, dims, MinMax<T>(minVal, maxVal));
}
//- Create a dimensionless "minmax"
template<class T>
inline dimensioned<MinMax<T>> makeDimensionedMinMax
(
const T& minVal,
const T& maxVal
)
{
return
dimensioned<MinMax<T>>
(
"minmax", dimensionSet(), MinMax<T>(minVal, maxVal)
);
}
//- Combine two dimensioned types into a dimensionedMinMax with specified name
template<class T>
inline dimensioned<MinMax<T>> makeDimensionedMinMax
(
const word& name,
const dimensioned<T>& minVal,
const dimensioned<T>& maxVal
)
{
// Dimension check when (dimensionSet::debug)
return dimensioned<MinMax<T>>
(
name,
(minVal.dimensions() + maxVal.dimensions()),
MinMax<T>(minVal.value(), maxVal.value())
);
}
//- Combine two dimensioned types into a dimensionedMinMax "minmax"
template<class T>
inline dimensioned<MinMax<T>> makeDimensionedMinMax
(
const dimensioned<T>& minVal,
const dimensioned<T>& maxVal
)
{
return makeDimensionedMinMax("minmax", minVal, maxVal);
}
//- Construct from components (name, dimensions, value) with an optional
//- dictionary override that can also \e zip together different sub-entries.
//
// The dictionary override can specify separate min/max dictionary entries.
// For example,
// \verbatim
// rhoMin 0.3;
// rhoMax 2.0;
// \endverbatim
//
// Construct as following:
//
// \verbatim
// makeDimensionedMinMax<scalar>
// (
// "rhoMinMax", dimDensity, {Zero, GREAT}, dict, "rhoMin", "rhoMax"
// );
// \endverbatim
template<class T>
dimensioned<MinMax<T>> makeDimensionedMinMax
(
const word& name,
const dimensionSet& dims,
const MinMax<T>& values,
const dictionary& dict,
const word& minName,
const word& maxName
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "dimensionedMinMaxTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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 "dimensionedMinMax.H"
#include "dictionary.H"
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
template<class T>
Foam::dimensioned<Foam::MinMax<T>> Foam::makeDimensionedMinMax
(
const word& name,
const dimensionSet& dims,
const MinMax<T>& values,
const dictionary& dict,
const word& minName,
const word& maxName
)
{
// Normal construction with optional entry
dimensioned<MinMax<T>> range(name, dims, values, dict);
// Optional min specification
if (!minName.empty())
{
dimensioned<T> minVal(minName, dims, values.min(), dict);
range.dimensions() += minVal.dimensions();
range.value().min() = minVal.value();
}
// Optional max specification
if (!maxName.empty())
{
dimensioned<T> maxVal(maxName, dims, values.max(), dict);
range.dimensions() += maxVal.dimensions();
range.value().max() = maxVal.value();
}
return range;
}
// ************************************************************************* //
......@@ -33,6 +33,7 @@ License
#include "dimensionedSphericalTensor.H"
#include "dimensionedSymmTensor.H"
#include "dimensionedTensor.H"
#include "dimensionedMinMax.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......
......@@ -325,6 +325,9 @@ UNARY_REDUCTION_FUNCTION(Type, sum, gSum)
UNARY_REDUCTION_FUNCTION(scalar, sumMag, gSumMag)
UNARY_REDUCTION_FUNCTION(Type, average, gAverage)
UNARY_REDUCTION_FUNCTION(MinMax<Type>, minMax, gMinMax)
UNARY_REDUCTION_FUNCTION(scalarMinMax, minMaxMag, gMinMaxMag)
#undef UNARY_REDUCTION_FUNCTION
......@@ -338,6 +341,8 @@ BINARY_TYPE_FUNCTION(Type, Type, Type, min)
BINARY_TYPE_FUNCTION(Type, Type, Type, cmptMultiply)
BINARY_TYPE_FUNCTION(Type, Type, Type, cmptDivide)
BINARY_TYPE_FUNCTION_FS(Type, Type, MinMax<Type>, clip)
// * * * * * * * * * * * * * * * Global operators * * * * * * * * * * * * * //
......
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -119,6 +119,9 @@ UNARY_REDUCTION_FUNCTION(Type, sum, gSum)
UNARY_REDUCTION_FUNCTION(scalar, sumMag, gSumMag)
UNARY_REDUCTION_FUNCTION(Type, average, gAverage)
UNARY_REDUCTION_FUNCTION(MinMax<Type>, minMax, gMinMax)
UNARY_REDUCTION_FUNCTION(scalarMinMax, minMaxMag, gMinMaxMag)
#undef UNARY_REDUCTION_FUNCTION
......@@ -132,6 +135,8 @@ BINARY_TYPE_FUNCTION(Type, Type, Type, min)
BINARY_TYPE_FUNCTION(Type, Type, Type, cmptMultiply)
BINARY_TYPE_FUNCTION(Type, Type, Type, cmptDivide)
BINARY_TYPE_FUNCTION_FS(Type, Type, MinMax<Type>, clip)
// * * * * * * * * * * * * * * * Global operators * * * * * * * * * * * * * //
......
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -521,6 +521,37 @@ Type average(const FieldField<Field, Type>& f)
TMP_UNARY_FUNCTION(Type, average)
template<template<class> class Field, class Type>
MinMax<Type> minMax(const FieldField<Field, Type>& f)
{
MinMax<Type> result;
forAll(f, i)
{
result += minMax(f[i]);
}
return result;
}
TMP_UNARY_FUNCTION(MinMax<Type>, minMax)
template<template<class> class Field, class Type>
scalarMinMax minMaxMag(const FieldField<Field, Type>& f)
{
scalarMinMax result;
forAll(f, i)
{
result += minMaxMag(f[i]);
}
return result;
}
TMP_UNARY_FUNCTION(scalarMinMax, minMaxMag)
#define G_UNARY_FUNCTION(returnType, gFunc, func, rFunc) \
\
template<template<class> class Field, class Type> \
......@@ -537,6 +568,9 @@ G_UNARY_FUNCTION(Type, gMin, min, min)
G_UNARY_FUNCTION(Type, gSum, sum, sum)
G_UNARY_FUNCTION(scalar, gSumMag, sumMag, sum)
G_UNARY_FUNCTION(MinMax<Type>, gMinMax, minMax, minMax)
G_UNARY_FUNCTION(scalarMinMax, gMinMaxMag, minMaxMag, minMaxMag)
#undef G_UNARY_FUNCTION
......@@ -580,6 +614,8 @@ BINARY_TYPE_FUNCTION(Type, Type, Type, min)
BINARY_TYPE_FUNCTION(Type, Type, Type, cmptMultiply)
BINARY_TYPE_FUNCTION(Type, Type, Type, cmptDivide)