diff --git a/applications/test/dimensionSet/Test-dimensionSet.C b/applications/test/dimensionSet/Test-dimensionSet.C index 52374f0e40..638ffe84f2 100644 --- a/applications/test/dimensionSet/Test-dimensionSet.C +++ b/applications/test/dimensionSet/Test-dimensionSet.C @@ -110,8 +110,7 @@ unsigned checkDimensions try { - // min(a, b); - clip(a, b); + min(a, b); dimsOk = true; } catch (const Foam::error& err) diff --git a/applications/test/minMax1/Test-minMax1.C b/applications/test/minMax1/Test-minMax1.C index f5b762a7fc..86ff65d720 100644 --- a/applications/test/minMax1/Test-minMax1.C +++ b/applications/test/minMax1/Test-minMax1.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2019-2022 OpenCFD Ltd. + Copyright (C) 2019-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -83,6 +83,9 @@ int main(int argc, char *argv[]) Info<<"Construct zero : "; printInfo(MinMax(Zero)) << nl; + Info<<"Construct zero_one : "; + printInfo(MinMax(zero_one{})) << nl; + Info<<"Construct range : "; printInfo(MinMax(1, 20)) << nl; @@ -92,6 +95,26 @@ int main(int argc, char *argv[]) Info<<"A 0-1 vector range : "; printInfo(MinMax::zero_one()) << nl; + { + vector a(0, 1, 20); + vector b(2, 1, 0); + vector c(4, 10, 12); + + Info<< "vectors:" + << " a = " << a + << " b = " << b + << " c = " << c << nl; + + Info<< "min max = " << min(max(a, b), c) << nl; + Info<< "range clamp= " << MinMax(b, c).clamp(a) << nl; + Info<< "clamp = " << clamp(a, b, c) << nl; + + Info<< "clamp 0/1 = " << clamp(a, vector::zero, vector::one) << nl; + } + + // Scalar promotion + Info<< "clamp (scalar) = " << clamp(15.0, -1, 1) << nl; + { scalarMinMax range1(10, 20); @@ -180,6 +203,9 @@ int main(int argc, char *argv[]) { MinMax limiter(10, 200); + clampOp clipper(limiter); + // clampOp clipper(zero_one{}); + // clampOp clipper(10, 200); Info<< nl << "Test clipping limiter: " << limiter << nl @@ -196,7 +222,10 @@ int main(int argc, char *argv[]) Info<< nl << "test clip() with limiter: " << limiter << nl; for (const scalar& val : values1) { - Info<< "clipped : " << val << " = " << clip(val, limiter) << nl; + Info<< "clipped : " << val << " = " + << clip(val, limiter) + << " or " << clip(val, limiter) + << " or " << clipper(val) << nl; } Info<< nl << "test clip(Field) with limiter: " << limiter << nl; @@ -208,9 +237,15 @@ int main(int argc, char *argv[]) Info<< "before " << flatOutput(values2) << nl; + // Too much clutter + // for (scalar& val : values2) + // { + // clampEqOp{limiter}(val); + // } + for (scalar& val : values2) { - clipEqOp()(val, limiter); + val = clipper(val); } Info<< "after: " << flatOutput(values2) << nl; diff --git a/applications/test/minMax2/Test-minMax2.C b/applications/test/minMax2/Test-minMax2.C index 95a3ced198..201b0548d6 100644 --- a/applications/test/minMax2/Test-minMax2.C +++ b/applications/test/minMax2/Test-minMax2.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -24,7 +24,7 @@ License along with OpenFOAM. If not, see . Description - Test minMax + Test-minMax2 \*---------------------------------------------------------------------------*/ @@ -37,6 +37,7 @@ Description #include "MinMax.H" #include "dimensionedScalar.H" #include "dimensionedMinMax.H" +#include "Random.H" using namespace Foam; @@ -78,7 +79,6 @@ int main(int argc, char *argv[]) Info<< "Test min/max " << nl; - { scalarMinMax range1(10, 20); scalarMinMax range2(40, 50); @@ -140,7 +140,34 @@ int main(int argc, char *argv[]) } } + { + scalarField someField(25); + Random rnd(4567); + for (scalar& val : someField) + { + val = rnd.position(-0.2, 1.2); + } + + Info<< nl + << "field: " << flatOutput(someField) << nl; + Info<< "clamp01: " + << flatOutput(clamp(someField, scalarMinMax(zero_one{}))()) << nl; + + Info<< "clamp01: " + << clamp(tmp(someField), scalarMinMax(zero_one{}))<< nl; + + scalarField result(10); + clamp(result, someField, scalarMinMax(zero_one{})); + + Info<< "result: " << result << nl; + + someField.clamp(zero_one{}); + + Info<< "inplace: " << someField << nl; + } + + Info<< nl << "\nDone\n" << endl; return 0; } diff --git a/applications/utilities/preProcessing/PDR/pdrFields/PDRarraysCalc.C b/applications/utilities/preProcessing/PDR/pdrFields/PDRarraysCalc.C index 7db3730924..fa84546b41 100644 --- a/applications/utilities/preProcessing/PDR/pdrFields/PDRarraysCalc.C +++ b/applications/utilities/preProcessing/PDR/pdrFields/PDRarraysCalc.C @@ -1279,7 +1279,7 @@ void write_scalarField continue; } - os << limits.clip(fld(cellIdx)) << nl; + os << limits.clamp(fld(cellIdx)) << nl; } os << token::END_LIST << token::END_STATEMENT << nl; diff --git a/applications/utilities/preProcessing/PDR/pdrFields/obstacles/PDRobstacleTypes.C b/applications/utilities/preProcessing/PDR/pdrFields/obstacles/PDRobstacleTypes.C index 078b5a7df0..31c559d86f 100644 --- a/applications/utilities/preProcessing/PDR/pdrFields/obstacles/PDRobstacleTypes.C +++ b/applications/utilities/preProcessing/PDR/pdrFields/obstacles/PDRobstacleTypes.C @@ -58,12 +58,11 @@ namespace Foam { // Read porosity, change to blockage. Clamp values [0-1] silently -static const scalarMinMax limits01(scalarMinMax::zero_one()); // Volume porosity -> blockage inline scalar getPorosity(const dictionary& dict) { - return 1 - limits01.clip(dict.getOrDefault("porosity", 0)); + return 1 - clamp(dict.getOrDefault("porosity", 0), 0, 1); } // Direction porosities -> blockage @@ -75,7 +74,7 @@ inline vector getPorosities(const dictionary& dict) { for (scalar& val : blockage) { - val = 1 - limits01.clip(val); + val = 1 - clamp(val, 0, 1); } } diff --git a/src/OpenFOAM/dimensionSet/dimensionSet.C b/src/OpenFOAM/dimensionSet/dimensionSet.C index 4dddfb7a69..f7dc05d350 100644 --- a/src/OpenFOAM/dimensionSet/dimensionSet.C +++ b/src/OpenFOAM/dimensionSet/dimensionSet.C @@ -253,36 +253,38 @@ bool Foam::dimensionSet::operator/=(const dimensionSet& ds) // * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * // -Foam::dimensionSet Foam::min(const dimensionSet& ds1, const dimensionSet& ds2) +Foam::dimensionSet Foam::min(const dimensionSet& a, const dimensionSet& b) { if (dimensionSet::checking()) { - checkDims("min(a, b)", ds1, ds2); + checkDims("min(a, b)", a, b); } - return ds1; + return a; } -Foam::dimensionSet Foam::max(const dimensionSet& ds1, const dimensionSet& ds2) +Foam::dimensionSet Foam::max(const dimensionSet& a, const dimensionSet& b) { if (dimensionSet::checking()) { - checkDims("max(a, b)", ds1, ds2); + checkDims("max(a, b)", a, b); } - return ds1; + return a; } -Foam::dimensionSet Foam::clip(const dimensionSet& ds1, const dimensionSet& ds2) +Foam::dimensionSet Foam::clamp(const dimensionSet& a, const dimensionSet& range) { - if (dimensionSet::checking()) + // In may cases the min/max range will be created from raw values + // (no dimension) so accept those without error + if (dimensionSet::checking() && !range.dimensionless()) { - checkDims("clip(a, b)", ds1, ds2); + checkDims("clamp(a, b)", a, range); } - return ds1; + return a; } diff --git a/src/OpenFOAM/dimensionSet/dimensionSet.H b/src/OpenFOAM/dimensionSet/dimensionSet.H index a579c7b5bc..8bc491d6f1 100644 --- a/src/OpenFOAM/dimensionSet/dimensionSet.H +++ b/src/OpenFOAM/dimensionSet/dimensionSet.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2017-2022 OpenCFD Ltd. + Copyright (C) 2017-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -354,9 +354,9 @@ Ostream& operator<<(Ostream& os, const dimensionSet& ds); // Global Functions -dimensionSet min(const dimensionSet& ds1, const dimensionSet& ds2); -dimensionSet max(const dimensionSet& ds1, const dimensionSet& ds2); -dimensionSet clip(const dimensionSet& ds1, const dimensionSet& ds2); +dimensionSet min(const dimensionSet& a, const dimensionSet& b); +dimensionSet max(const dimensionSet& a, const dimensionSet& b); +dimensionSet clamp(const dimensionSet& a, const dimensionSet& range); dimensionSet cmptMultiply(const dimensionSet& ds1, const dimensionSet& ds2); dimensionSet cmptDivide(const dimensionSet& ds1, const dimensionSet& ds2); diff --git a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.H b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.H index 1e609ea6e8..72ee48bb72 100644 --- a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.H +++ b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.H @@ -421,6 +421,8 @@ public: const tmp>& tdf ); + // Inherits clamp, clamp_min, clamp_max (without dimensions) from Field + //- Return the field transpose (only defined for second rank tensors) tmp> T() const; diff --git a/src/OpenFOAM/fields/FieldFields/FieldField/FieldField.C b/src/OpenFOAM/fields/FieldFields/FieldField/FieldField.C index 16d16264e4..5566474746 100644 --- a/src/OpenFOAM/fields/FieldFields/FieldField/FieldField.C +++ b/src/OpenFOAM/fields/FieldFields/FieldField/FieldField.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2019-2022 OpenCFD Ltd. + Copyright (C) 2019-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -282,6 +282,65 @@ void FieldField::replace } +template class Field, class Type> +void FieldField::clamp +( + const Type& lower, + const Type& upper +) +{ + if (lower < upper) + { + for (auto& ff : *this) + { + ff.clamp(lower, upper); + } + } +} + + +template class Field, class Type> +void FieldField::clamp +( + const MinMax& range +) +{ + if (range.min() < range.max()) + { + for (auto& ff : *this) + { + ff.clamp(range.min(), range.max()); + } + } +} + + +template class Field, class Type> +void FieldField::clamp_min +( + const Type& lower +) +{ + for (auto& ff : *this) + { + ff.clamp_min(lower); + } +} + + +template class Field, class Type> +void FieldField::clamp_max +( + const Type& upper +) +{ + for (auto& ff : *this) + { + ff.clamp_max(upper); + } +} + + template class Field, class Type> tmp> FieldField::T() const { diff --git a/src/OpenFOAM/fields/FieldFields/FieldField/FieldField.H b/src/OpenFOAM/fields/FieldFields/FieldField/FieldField.H index 2227f295fa..11504cbe79 100644 --- a/src/OpenFOAM/fields/FieldFields/FieldField/FieldField.H +++ b/src/OpenFOAM/fields/FieldFields/FieldField/FieldField.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2022 OpenCFD Ltd. + Copyright (C) 2022-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -149,6 +149,20 @@ public: //- Replace a component field of the field void replace(const direction, const cmptType&); + //- Clamp field values (in-place) to the specified range. + // A no-op for an invalid range. + void clamp(const Type& lower, const Type& upper); + + //- Clamp field values (in-place) to the specified range. + // A no-op for an invalid range. + void clamp(const MinMax& range); + + //- Impose lower (floor) clamp on the field values (in-place) + void clamp_min(const Type& lower); + + //- Impose upper (ceiling) clamp on the field values (in-place) + void clamp_max(const Type& upper); + //- Return the field transpose (only defined for second rank tensors) tmp> T() const; diff --git a/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.C b/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.C index 41c4cd93fe..9be878df3d 100644 --- a/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.C +++ b/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.C @@ -673,7 +673,7 @@ 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, clip) +BINARY_TYPE_FUNCTION_FS(Type, Type, MinMax, clamp) /* * * * * * * * * * * * * * * * Global operators * * * * * * * * * * * * * */ diff --git a/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.H b/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.H index b4c6fdf25f..a9a7084e97 100644 --- a/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.H +++ b/src/OpenFOAM/fields/FieldFields/FieldField/FieldFieldFunctions.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -287,7 +287,7 @@ 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, clip) +BINARY_TYPE_FUNCTION_FS(Type, Type, MinMax, clamp) /* * * * * * * * * * * * * * * * Global operators * * * * * * * * * * * * * */ diff --git a/src/OpenFOAM/fields/Fields/Field/Field.C b/src/OpenFOAM/fields/Fields/Field/Field.C index d303761a7f..fe237c8283 100644 --- a/src/OpenFOAM/fields/Fields/Field/Field.C +++ b/src/OpenFOAM/fields/Fields/Field/Field.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2015-2022 OpenCFD Ltd. + Copyright (C) 2015-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -625,6 +625,50 @@ void Foam::Field::replace } +template +void Foam::Field::clamp(const Type& lower, const Type& upper) +{ + // Use free functions min(), max() to impose component-wise clamping + if (lower < upper) + { + // std::for_each + for (auto& val : *this) + { + val = min(max(val, lower), upper); + } + } +} + +template +void Foam::Field::clamp(const MinMax& range) +{ + clamp(range.min(), range.max()); +} + + +template +void Foam::Field::clamp_min(const Type& lower) +{ + // Use free function max() [sic] to impose component-wise clamp_min + // std::for_each + for (auto& val : *this) + { + val = max(val, lower); + } +} + +template +void Foam::Field::clamp_max(const Type& upper) +{ + // Use free function min() [sic] to impose component-wise clamp_max + // std::for_each + for (auto& val : *this) + { + val = min(val, upper); + } +} + + template template VSForm Foam::Field::block(const label start) const diff --git a/src/OpenFOAM/fields/Fields/Field/Field.H b/src/OpenFOAM/fields/Fields/Field/Field.H index 2cbdb712e1..aa91c3de16 100644 --- a/src/OpenFOAM/fields/Fields/Field/Field.H +++ b/src/OpenFOAM/fields/Fields/Field/Field.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2015-2022 OpenCFD Ltd. + Copyright (C) 2015-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -415,6 +415,20 @@ public: //- Replace a component field of the field void replace(const direction, const cmptType&); + //- Clamp field values (in-place) to the specified range. + // A no-op for an invalid range. + void clamp(const Type& lower, const Type& upper); + + //- Clamp field values (in-place) to the specified range. + // A no-op for an invalid range. + void clamp(const MinMax& range); + + //- Impose lower (floor) clamp on the field values (in-place) + void clamp_min(const Type& lower); + + //- Impose upper (ceiling) clamp on the field values (in-place) + void clamp_max(const Type& upper); + template VSForm block(const label start) const; diff --git a/src/OpenFOAM/fields/Fields/Field/FieldFunctions.C b/src/OpenFOAM/fields/Fields/Field/FieldFunctions.C index 00bd0cc54e..bfcc7860d3 100644 --- a/src/OpenFOAM/fields/Fields/Field/FieldFunctions.C +++ b/src/OpenFOAM/fields/Fields/Field/FieldFunctions.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -656,6 +656,64 @@ TMP_UNARY_FUNCTION(Type, gAverage) #undef TMP_UNARY_FUNCTION +template +void clamp +( + Field& result, + const UList& f1, + const MinMax& range +) +{ + if (result.cdata() == f1.cdata()) + { + // Apply in-place + result.clamp(range); + } + else + { + if (range.good()) + { + std::transform + ( + f1.cbegin(), + f1.cbegin(result.size()), + result.begin(), + clampOp(range) + ); + } + else + { + // No clamping + std::copy(f1.cbegin(), f1.cbegin(result.size()), result.begin()); + } + } +} + +template +tmp> clamp +( + const UList& f1, + const MinMax& range +) +{ + auto tres = tmp>::New(f1.size()); + clamp(tres.ref(), f1, range); + return tres; +} + +template +tmp> clamp +( + const tmp>& tf1, + const MinMax& range +) +{ + auto tres = reuseTmp::New(tf1); + clamp(tres.ref(), tf1(), range); + tf1.clear(); + return tres; +} + BINARY_FUNCTION(Type, Type, Type, max) BINARY_FUNCTION(Type, Type, Type, min) @@ -667,10 +725,10 @@ 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, clip) +BINARY_TYPE_FUNCTION_FS(Type, Type, MinMax, clip) // Same as clamp -/* * * * * * * * * * * * * * * * Global operators * * * * * * * * * * * * * */ +/* * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * */ UNARY_OPERATOR(Type, Type, -, negate) diff --git a/src/OpenFOAM/fields/Fields/Field/FieldFunctions.H b/src/OpenFOAM/fields/Fields/Field/FieldFunctions.H index e57e56b93e..57a0c5db18 100644 --- a/src/OpenFOAM/fields/Fields/Field/FieldFunctions.H +++ b/src/OpenFOAM/fields/Fields/Field/FieldFunctions.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -313,10 +313,11 @@ 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, clip) +BINARY_TYPE_FUNCTION_FS(Type, Type, MinMax, clamp) +BINARY_TYPE_FUNCTION_FS(Type, Type, MinMax, clip) // Same as clamp -// * * * * * * * * * * * * * * * Global operators * * * * * * * * * * * * * // +// * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * // UNARY_OPERATOR(Type, Type, -, negate) diff --git a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C index 14ab696745..0f39b3f116 100644 --- a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C +++ b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2015-2022 OpenCFD Ltd. + Copyright (C) 2015-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -1250,60 +1250,88 @@ void Foam::GeometricField::replace template class PatchField, class GeoMesh> -void Foam::GeometricField::min +void Foam::GeometricField::clamp ( - const dimensioned& dt + const Type& lower, + const Type& upper ) { - Foam::min(primitiveFieldRef(), primitiveField(), dt.value()); - Foam::min(boundaryFieldRef(), boundaryField(), dt.value()); + primitiveFieldRef().clamp(lower, upper); + boundaryFieldRef().clamp(lower, upper); } template class PatchField, class GeoMesh> -void Foam::GeometricField::max +void Foam::GeometricField::clamp ( - const dimensioned& dt + const MinMax& range ) { - Foam::max(primitiveFieldRef(), primitiveField(), dt.value()); - Foam::max(boundaryFieldRef(), boundaryField(), dt.value()); + primitiveFieldRef().clamp(range.min(), range.max()); + boundaryFieldRef().clamp(range.min(), range.max()); } template class PatchField, class GeoMesh> -void Foam::GeometricField::clip +void Foam::GeometricField::clamp +( + const dimensioned& lower, + const dimensioned& upper +) +{ + this->clamp(lower.value(), upper.value()); +} + + +template class PatchField, class GeoMesh> +void Foam::GeometricField::clamp ( const dimensioned>& range ) { - Foam::clip(primitiveFieldRef(), primitiveField(), range.value()); - Foam::clip(boundaryFieldRef(), boundaryField(), range.value()); + this->clamp(range.value()); } template class PatchField, class GeoMesh> -void Foam::GeometricField::clip +void Foam::GeometricField::clamp_min ( - const dimensioned& minVal, - const dimensioned& maxVal + const Type& lower ) { - MinMax range(minVal.value(), maxVal.value()); - - Foam::clip(primitiveFieldRef(), primitiveField(), range); - Foam::clip(boundaryFieldRef(), boundaryField(), range); + primitiveFieldRef().clamp_min(lower); + boundaryFieldRef().clamp_min(lower); } template class PatchField, class GeoMesh> -void Foam::GeometricField::maxMin +void Foam::GeometricField::clamp_max ( - const dimensioned& minVal, - const dimensioned& maxVal + const Type& upper ) { - this->clip(minVal, maxVal); + primitiveFieldRef().clamp_max(upper); + boundaryFieldRef().clamp_max(upper); +} + + +template class PatchField, class GeoMesh> +void Foam::GeometricField::clamp_min +( + const dimensioned& lower +) +{ + this->clamp_min(lower.value()); +} + + +template class PatchField, class GeoMesh> +void Foam::GeometricField::clamp_max +( + const dimensioned& upper +) +{ + this->clamp_max(upper.value()); } diff --git a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H index 7098d4b834..cf4a09c683 100644 --- a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H +++ b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2015-2022 OpenCFD Ltd. + Copyright (C) 2015-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -134,7 +134,6 @@ private: //- Read the field - create the field dictionary on-the-fly void readFields(); - public: //- Runtime type information @@ -630,32 +629,39 @@ public: const dimensioned& ds ); - //- Use the minimum of the field and specified value - // This sets the \em ceiling on the field values - void min(const dimensioned& dt); + //- Clamp field values (in-place) to the specified range. + // A no-op for an invalid range. + void clamp(const Type& lower, const Type& upper); - //- Use the maximum of the field and specified value - // This sets the \em floor on the field values - void max(const dimensioned& dt); + //- Clamp field values (in-place) to the specified range. + // A no-op for an invalid range. + void clamp(const MinMax& range); - //- Clip the field to be bounded within the specified range - void clip(const dimensioned>& range); - - //- Clip the field to be bounded within the specified range - void clip + //- Clamp field values (in-place) to the specified range. + // A no-op for an invalid range. No dimension checking. + void clamp ( - const dimensioned& minVal, - const dimensioned& maxVal + const dimensioned& lower, + const dimensioned& upper ); - //- Deprecated(2019-01) identical to clip() - // \deprecated(2019-01) identical to clip() - FOAM_DEPRECATED_FOR(2019-01, "clip() method") - void maxMin - ( - const dimensioned& minVal, - const dimensioned& maxVal - ); + //- Clamp field values (in-place) to the specified range. + // A no-op for an invalid range. No dimension checking. + void clamp(const dimensioned>& range); + + //- Impose lower (floor) clamp on the field values (in-place) + void clamp_min(const Type& lower); + + //- Impose upper (ceiling) clamp on the field values (in-place) + void clamp_max(const Type& upper); + + //- Impose lower (floor) clamp on the field values (in-place) + // No dimension checking + void clamp_min(const dimensioned& lower); + + //- Impose upper (ceiling) clamp on the field values (in-place) + // No dimension checking + void clamp_max(const dimensioned& upper); // Member Operators @@ -691,7 +697,7 @@ public: void operator/=(const dimensioned&); - // Ostream operators + // Ostream Operators friend Ostream& operator<< ( @@ -704,6 +710,41 @@ public: Ostream&, const tmp>& ); + + + // Housekeeping + + //- Clamp field values (in-place) to the specified range. + // \deprecated(2023-01) prefer clamp() naming + void clip(const dimensioned>& range) + { + this->clamp(range); + } + + //- Clamp field values (in-place) to the specified range. + // \deprecated(2023-01) prefer clamp() naming + void clip(const dimensioned& lo, const dimensioned& hi) + { + this->clamp(lo.value(), hi.value()); + } + + //- Use minimum of the field and specified value. ie, clamp_max(). + // This sets the \em ceiling on the field values + // \deprecated(2023-01) prefer clamp_max() + void min(const dimensioned& upper) { this->clamp_max(upper); } + + //- Use maximum of the field and specified value. ie, clamp_min(). + // This sets the \em floor on the field values + // \deprecated(2023-01) prefer clamp_min() + void max(const dimensioned& lower) { this->clamp_min(lower); } + + //- Deprecated(2019-01) identical to clamp() + // \deprecated(2019-01) identical to clamp() + FOAM_DEPRECATED_FOR(2019-01, "clamp() method") + void maxMin(const dimensioned& lo, const dimensioned& hi) + { + return this->clamp(lo.value(), hi.value()); + } }; diff --git a/src/OpenFOAM/primitives/Scalar/Scalar.H b/src/OpenFOAM/primitives/Scalar/Scalar.H index e19a7e7d6f..2a4159c4a0 100644 --- a/src/OpenFOAM/primitives/Scalar/Scalar.H +++ b/src/OpenFOAM/primitives/Scalar/Scalar.H @@ -294,6 +294,13 @@ inline bool notEqual(const Scalar a, const Scalar b) } +// Fast implementation, and with scalar promotion of upper/lower limits +inline Scalar clamp(const Scalar& val, const Scalar& lower, const Scalar& upper) +{ + return (val < lower) ? lower : (upper < val) ? upper : val; +} + + inline Scalar limit(const Scalar s1, const Scalar s2) { return (mag(s1) < mag(s2)) ? s1: 0.0; diff --git a/src/OpenFOAM/primitives/ints/label/label.H b/src/OpenFOAM/primitives/ints/label/label.H index 5afa10789f..bf5e105eb0 100644 --- a/src/OpenFOAM/primitives/ints/label/label.H +++ b/src/OpenFOAM/primitives/ints/label/label.H @@ -141,6 +141,15 @@ inline bool equal(const T& a, const T& b) return (a == b); } +//- Return value clamped between upper and lower limits. +// Unlike the std::clamp, which selects between references, this version +// wraps the min/max free functions for component-wise clamping +template +inline T clamp(const T& val, const T& lower, const T& upper) +{ + return min(max(val, lower), upper); +} + /*---------------------------------------------------------------------------*\ Struct labelOp Declaration diff --git a/src/OpenFOAM/primitives/ranges/MinMax/MinMax.H b/src/OpenFOAM/primitives/ranges/MinMax/MinMax.H index 403a5b22da..3738f8847a 100644 --- a/src/OpenFOAM/primitives/ranges/MinMax/MinMax.H +++ b/src/OpenFOAM/primitives/ranges/MinMax/MinMax.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2019-2022 OpenCFD Ltd. + Copyright (C) 2019-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -67,30 +67,16 @@ Description Info<< "values values in range " << mask << nl; \endverbatim - One particular advantage offered by MinMax is to clip or limit values + One advantage offered by MinMax is to clamp or limit values to a particular range. For example, \verbatim scalarMinMax range(lower, upper); scalar val; - val = range.clip(val) .. return clip values + val = range.clamp(val) .. return clamped values // vs. - val = min(max(value, lower, upper)) - \endverbatim - - Or when working on lists, the values can be limited in a single pass - of the data without intermediate memory allocation. - \verbatim - scalarField values = ...; - - for (scalar& val : values) - { - range.inplaceClip(val); - } - - // vs. - values = min(max(values, lower, upper)) + val = min(max(value, lower), upper) \endverbatim \*---------------------------------------------------------------------------*/ @@ -112,6 +98,7 @@ namespace Foam // Forward Declarations template class MinMax; class zero; +class zero_one; // Common min/max types typedef MinMax