ENH: add FieldOps with conditionals (assignment, ternary)

This commit is contained in:
Mark Olesen
2019-11-20 20:35:55 +01:00
committed by Andrew Heather
parent fae91edd85
commit 73425eb119
3 changed files with 593 additions and 0 deletions

View File

@ -0,0 +1,157 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 <algorithm>
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
template<class Tout, class T1, class UnaryOp>
void Foam::FieldOps::assign
(
Field<Tout>& result,
const Field<T1>& a,
const UnaryOp& op
)
{
#ifdef FULLDEBUG
if (result.size() != a.size())
{
FatalErrorInFunction
<< "Field sizes do not match: " << result.size() << " ("
<< a.size() << ')' << nl
<< abort(FatalError);
}
#endif
std::transform(a.cbegin(), a.cend(), result.begin(), op);
}
template<class Tout, class T1, class T2, class BinaryOp>
void Foam::FieldOps::assign
(
Field<Tout>& result,
const Field<T1>& a,
const Field<T2>& b,
const BinaryOp& bop
)
{
#ifdef FULLDEBUG
if (result.size() != a.size() || result.size() != b.size())
{
FatalErrorInFunction
<< "Field sizes do not match: " << result.size() << " ("
<< a.size() << ' ' << b.size() << ')' << nl
<< abort(FatalError);
}
#endif
std::transform(a.cbegin(), a.cend(), b.cbegin(), result.begin(), bop);
}
template<class T, class BinaryOp>
void Foam::FieldOps::ternary
(
Field<T>& result,
const Field<T>& a,
const Field<T>& b,
const BinaryOp& bop
)
{
#ifdef FULLDEBUG
if (result.size() != a.size() || result.size() != b.size())
{
FatalErrorInFunction
<< "Field sizes do not match: " << result.size() << " ("
<< a.size() << ' ' << b.size() << ')' << nl
<< abort(FatalError);
}
#endif
forAll(result, i)
{
result[i] = bop(a[i], b[i]) ? a[i] : b[i];
}
}
template<class T, class BoolListType, class FlipOp>
void Foam::FieldOps::ternarySelect
(
Field<T>& result,
const BoolListType& cond,
const Field<T>& a,
const Field<T>& b,
const FlipOp& flip
)
{
#ifdef FULLDEBUG
if (result.size() != a.size() || result.size() != b.size())
{
FatalErrorInFunction
<< "Field sizes do not match: " << result.size() << " ("
<< a.size() << ' ' << b.size() << ')' << nl
<< abort(FatalError);
}
#endif
forAll(result, i)
{
result[i] = flip(cond[i]) ? a[i] : b[i];
}
}
template<class T, class FlipOp>
void Foam::FieldOps::ternarySelect
(
Field<T>& result,
const bitSet& cond,
const Field<T>& a,
const Field<T>& b,
const FlipOp& flip
)
{
#ifdef FULLDEBUG
if (result.size() != a.size() || result.size() != b.size())
{
FatalErrorInFunction
<< "Field sizes do not match: " << result.size() << " ("
<< a.size() << ' ' << b.size() << ')' << nl
<< abort(FatalError);
}
#endif
forAll(result, i)
{
result[i] = flip(cond[i]) ? a[i] : b[i];
}
}
// ************************************************************************* //

View File

@ -0,0 +1,208 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
Namespace
Foam::FieldOps
Description
Various utility functions to work on Fields
SourceFiles
FieldOps.C
\*---------------------------------------------------------------------------*/
#ifndef FieldOps_H
#define FieldOps_H
#include "flipOp.H"
#include "ListOps.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace FieldOps
{
/*---------------------------------------------------------------------------*\
Namespace FieldOps Declarations
\*---------------------------------------------------------------------------*/
//- Populate a field as the result of a unary operation on an input.
// It is permissible for inputs/outputs to refer to the same field(s),
// but partially overlapping regions are ill-defined.
//
// Examples,
// \code
// boolField result(sfield1.size());
//
// FieldOps::assign(result, sfield1, lessOp1<scalar>(0.5));
// FieldOps::assign(result, lfield1, std::logical_not<bool>());
// \endcode
//
// Example of using the Random::uniformGeneratorOp unary operator
// to populate a random field,
// \code
// FieldOps::assign
// (
// sfield,
// sfield,
// Random::uniformGeneratorOp<scalar>(-15, 25)
// );
// \endcode
//
// \note wraps std::transform
template<class Tout, class T1, class UnaryOp>
void assign
(
Field<Tout>& result,
const Field<T1>& a,
const UnaryOp& op
);
//- Populate a field as the result of a binary operation on two inputs.
// It is permissible for inputs/outputs to refer to the same field(s),
// but partially overlapping regions are ill-defined.
//
// Examples,
// \code
// FieldOps::assign(result, sfield1, sfield2, std::less<scalar>());
// FieldOps::assign(result, lfield1, lfield2, std::logical_or<bool>());
// \endcode
//
// \note wraps std::transform
template<class Tout, class T1, class T2, class BinaryOp>
void assign
(
Field<Tout>& result,
const Field<T1>& a,
const Field<T2>& b,
const BinaryOp& bop
);
//- Emulate a ternary operation, selecting values from a or b
//- depending on the binary predicate.
//
// Examples,
// \code
// FieldOps::ternary(result, sfield1, sfield2, std::less<scalar>());
// \endcode
template<class T, class BinaryOp>
void ternary
(
Field<T>& result,
const Field<T>& a,
const Field<T>& b,
const BinaryOp& bop
);
//- Emulate a ternary operation, selecting values from a or b
//- depending on the conditional.
//
// The meaning of the conditional is adjusted by the flip operation,
// which is typically Foam::noOp() or Foam::flipBoolOp()
//
// Similar parameter requirements as Foam::subset()
//
// Examples,
// \code
// FieldOps::ternarySelect(result, selector, sfield1, sfield2);
// \endcode
template<class T, class BoolListType, class FlipOp>
void ternarySelect
(
Field<T>& result,
const BoolListType& cond,
const Field<T>& a,
const Field<T>& b,
const FlipOp& flip
);
//- Emulate a ternary operation, selecting values from a or b
//- depending on the conditional.
//
// The meaning of the conditional is adjusted by the flip operation,
// which is typically Foam::noOp() or Foam::flipBoolOp()
template<class T, class FlipOp>
void ternarySelect
(
Field<T>& result,
const bitSet& cond,
const Field<T>& a,
const Field<T>& b,
const FlipOp& flip
);
//- Emulated ternary operation, without condition flipping
template<class T, class BoolListType>
void ternarySelect
(
Field<T>& result,
const BoolListType& cond,
const Field<T>& a,
const Field<T>& b
)
{
ternarySelect(result, cond, a, b, noOp());
}
//- Emulated ternary operation, without condition flipping
template<class T>
void ternarySelect
(
Field<T>& result,
const bitSet& cond,
const Field<T>& a,
const Field<T>& b
)
{
ternarySelect(result, cond, a, b, noOp());
}
} // End namespace FieldOps
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "FieldOps.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,228 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
InNamespace
Foam::FieldOps
Description
Various utility functions to work on geometric fields
SourceFiles
GeometricFieldOps.H
\*---------------------------------------------------------------------------*/
#ifndef GeometricFieldOps_H
#define GeometricFieldOps_H
#include "FieldOps.H"
#include "GeometricField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace FieldOps
{
/*---------------------------------------------------------------------------*\
Namespace FieldOps Declarations
\*---------------------------------------------------------------------------*/
//- Populate a geometric field as the result of a unary operation on an input.
// It is permissible for inputs/outputs to refer to the same field(s),
// but partially overlapping regions are ill-defined.
template
<
class Tout, class T1, class UnaryOp,
template<class> class PatchField, class GeoMesh
>
void assign
(
GeometricField<Tout, PatchField, GeoMesh>& result,
const GeometricField<T1, PatchField, GeoMesh>& a,
const UnaryOp& op
)
{
FieldOps::assign
(
result.primitiveFieldRef(),
a.primitiveField(),
op
);
auto& bfld = result.boundaryFieldRef();
const label len = bfld.size();
for (label i = 0; i < len; ++i)
{
FieldOps::assign
(
bfld[i],
a.boundaryField()[i],
op
);
}
}
//- Populate a geometric field from the binary operation on two inputs.
// It is permissible for inputs/outputs to refer to the same field(s),
// but partially overlapping regions are ill-defined.
template
<
class Tout, class T1, class T2, class BinaryOp,
template<class> class PatchField, class GeoMesh
>
void assign
(
GeometricField<Tout, PatchField, GeoMesh>& result,
const GeometricField<T1, PatchField, GeoMesh>& a,
const GeometricField<T1, PatchField, GeoMesh>& b,
const BinaryOp& bop
)
{
FieldOps::assign
(
result.primitiveFieldRef(),
a.primitiveField(),
b.primitiveField(),
bop
);
auto& bfld = result.boundaryFieldRef();
const label len = bfld.size();
for (label i = 0; i < len; ++i)
{
FieldOps::assign
(
bfld[i],
a.boundaryField()[i],
b.boundaryField()[i],
bop
);
}
}
//- Emulate a ternary operation, selecting values from a or b
//- depending on the binary predicate.
template
<
class T, class BinaryOp,
template<class> class PatchField, class GeoMesh
>
void ternary
(
GeometricField<T, PatchField, GeoMesh>& result,
const GeometricField<T, PatchField, GeoMesh>& a,
const GeometricField<T, PatchField, GeoMesh>& b,
const BinaryOp& bop
)
{
FieldOps::ternary
(
result.primitiveFieldRef(),
a.primitiveField(),
b.primitiveField(),
bop
);
auto& bfld = result.boundaryFieldRef();
const label len = bfld.size();
for (label i = 0; i < len; ++i)
{
FieldOps::ternary
(
bfld[i],
a.boundaryField()[i],
b.boundaryField()[i],
bop
);
}
}
//- Emulate a ternary operation, selecting field values from a or b
//- depending on the conditional.
//
// Since boolean fields are not normally used, a flip operation is
// a general requirement.
template
<
class T, class BoolType, class FlipOp,
template<class> class PatchField, class GeoMesh
>
void ternarySelect
(
GeometricField<T, PatchField, GeoMesh>& result,
const GeometricField<BoolType, PatchField, GeoMesh>& cond,
const GeometricField<T, PatchField, GeoMesh>& a,
const GeometricField<T, PatchField, GeoMesh>& b,
const FlipOp& flip
)
{
FieldOps::ternarySelect
(
result.primitiveFieldRef(),
cond.primitiveField(),
a.primitiveField(),
b.primitiveField(),
flip
);
auto& bfld = result.boundaryFieldRef();
const label len = bfld.size();
for (label i = 0; i < len; ++i)
{
FieldOps::ternarySelect
(
bfld[i],
cond.boundaryField()[i],
a.boundaryField()[i],
b.boundaryField()[i],
flip
);
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace FieldOps
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //