Commit 5105154b authored by Mark Olesen's avatar Mark Olesen
Browse files

ENH: expression versions of Function1 and PatchFunction1 (#1709)

parent 51c2329f
......@@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -34,6 +35,7 @@ Description
#include "fvCFD.H"
#include "Function1.H"
#include "scalarIndList.H"
#include "scalarField.H"
#include "IOdictionary.H"
#include "linearInterpolationWeights.H"
#include "splineInterpolationWeights.H"
......@@ -42,104 +44,121 @@ Description
int main(int argc, char *argv[])
{
#include "setRootCase.H"
#include "createTime.H"
#include "createMesh.H"
argList::noParallel();
{
scalarField samples(4);
samples[0] = 0;
samples[1] = 1;
samples[2] = 2;
samples[3] = 3;
scalarField values(4);
values = 1.0;
//values[0] = 0.0;
//values[1] = 1.0;
linearInterpolationWeights interpolator
//splineInterpolationWeights interpolator
(
samples
);
labelList indices;
scalarField weights;
interpolator.integrationWeights(1.1, 1.2, indices, weights);
Pout<< "indices:" << indices << endl;
Pout<< "weights:" << weights << endl;
scalar baseSum = interpolator.weightedSum
(
weights,
scalarUIndList(values, indices)
);
Pout<< "baseSum=" << baseSum << nl << nl << endl;
// interpolator.integrationWeights(-0.01, 0, indices, weights);
// scalar partialSum = interpolator.weightedSum
// (
// weights,
// scalarUIndList(values, indices)
// );
// Pout<< "partialSum=" << partialSum << nl << nl << endl;
//
//
// interpolator.integrationWeights(-0.01, 1, indices, weights);
// //Pout<< "samples:" << samples << endl;
// //Pout<< "indices:" << indices << endl;
// //Pout<< "weights:" << weights << endl;
// scalar sum = interpolator.weightedSum
// (
// weights,
// scalarUIndList(values, indices)
// );
// Pout<< "integrand=" << sum << nl << nl << endl;
return 1;
}
const word dictName("function1Properties");
IOdictionary function1Properties
(
IOobject
(
"function1Properties",
runTime.constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
);
autoPtr<Function1<scalar>> function1
(
Function1<scalar>::New
(
"function1",
function1Properties
)
);
argList::addBoolOption("all", "Test all functions in function1Properties");
scalar x0 = function1Properties.get<scalar>("x0");
scalar x1 = function1Properties.get<scalar>("x1");
argList::addArgument("function1");
argList::addArgument("...");
argList::addArgument("functionN");
argList::noMandatoryArgs();
Info<< "Data entry type: " << function1().type() << nl << endl;
#include "setRootCase.H"
#include "createTime.H"
{
scalarField samples({0, 1, 2, 3});
Info<< "Inputs" << nl
<< " x0 = " << x0 << nl
<< " x1 = " << x1 << nl
<< endl;
scalarField values(4, scalar(1));
Info<< "Interpolation" << nl
<< " f(x0) = " << function1().value(x0) << nl
<< " f(x1) = " << function1().value(x1) << nl
<< endl;
linearInterpolationWeights interpolator
//splineInterpolationWeights interpolator
(
samples
);
labelList indices;
scalarField weights;
interpolator.integrationWeights(1.1, 1.2, indices, weights);
Pout<< "indices:" << indices << nl
<< "weights:" << weights << nl;
Info<< "Integration" << nl
<< " int(f(x)) lim(x0->x1) = " << function1().integrate(x0, x1) << nl
<< endl;
scalar baseSum = interpolator.weightedSum
(
weights,
scalarUIndList(values, indices)
);
Pout<< "baseSum=" << baseSum << nl << nl << endl;
// interpolator.integrationWeights(-0.01, 0, indices, weights);
// scalar partialSum = interpolator.weightedSum
// (
// weights,
// scalarUIndList(values, indices)
// );
// Pout<< "partialSum=" << partialSum << nl << nl << endl;
// interpolator.integrationWeights(-0.01, 1, indices, weights);
// //Pout<< "samples:" << samples << endl;
// //Pout<< "indices:" << indices << endl;
// //Pout<< "weights:" << weights << endl;
// scalar sum = interpolator.weightedSum
// (
// weights,
// scalarUIndList(values, indices)
// );
// Pout<< "integrand=" << sum << nl << nl << endl;
}
if (args.found("all") || args.size() > 1)
{
#include "setConstantRunTimeDictionaryIO.H"
IOdictionary propsDict(dictIO);
const scalarField xvals(propsDict.lookup("x"));
Info<< "Entries" << flatOutput(propsDict.toc()) << nl << nl;
Info<< "Inputs" << nl
<< " x = " << xvals << nl
<< endl;
DynamicList<word> functionNames;
auto nameFilter = [](const word& val)
{
return !(val == "x" || val.ends_with("Coeffs"));
};
if (args.found("all"))
{
for (const word& f : propsDict.toc())
{
if (nameFilter(f))
{
functionNames.append(f);
}
}
}
else
{
for (label argi=1; argi < args.size(); ++argi)
{
functionNames.append(args[argi]);
}
}
for (const word& funName : functionNames)
{
auto function1 = Function1<scalar>::New(funName, propsDict);
// Info<< "Data entry type: " << function1().type() << nl;
Info<< "////" << nl;
function1().writeData(Info);
Info<< nl;
Info<< "Values" << nl;
for (const scalar& x : xvals)
{
Info<< " f(" << x << ") = " << function1().value(x) << nl;
}
Info<< endl;
}
}
return 0;
}
......
......@@ -15,11 +15,50 @@ FoamFile
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
x0 0.5;
x1 1;
// The 'x' values for evaluation
x
(
0
0.25
0.5
0.75
1
);
function1 table ((0 0)(10 1));
function1 table
(
(0 0)(10 1)
);
function2
{
type expression;
expression #{ sqr(arg()) #};
}
function2b expression;
function2bCoeffs
{
type expression;
expression #{ sqr(arg()) #};
}
stepf1
{
type step;
start 0.24;
duration 0.5;
}
rampf1
{
type linearRamp;
start 0.24;
duration 0.5;
}
// ************************************************************************* //
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object controlDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
application none;
deltaT 1;
writeControl timeStep;
writeInterval 10;
// ************************************************************************* //
......@@ -164,6 +164,8 @@ $(fieldExpr)/fieldExprDriverFields.C
$(fieldExpr)/fieldExprLemonParser.lyy-m4
$(fieldExpr)/fieldExprScanner.cc
$(expr)/Function1/makeFunction1Expression.C
ops = primitives/ops
$(ops)/flipOp.C
......
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 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 "Function1Expression.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
Foam::Function1Types::Function1Expression<Type>::Function1Expression
(
const word& entryName,
const dictionary& dict
)
:
Function1<Type>(entryName),
dict_(dict),
valueExpr_(),
driver_(1, dict_)
{
if (dict.getOrDefault("debug", false))
{
debug |= 1;
}
string expr;
dict.readEntry("expression", expr);
valueExpr_ = expressions::exprString(expr, dict);
// Basic sanity
if (valueExpr_.empty())
{
FatalIOErrorInFunction(dict_)
<< "The expression was not defined!" << nl
<< exit(FatalIOError);
}
driver_.readDict(dict_);
}
template<class Type>
Foam::Function1Types::Function1Expression<Type>::Function1Expression
(
const Function1Expression<Type>& rhs
)
:
Function1<Type>(rhs),
dict_(rhs.dict_),
valueExpr_(rhs.valueExpr_),
driver_(1, rhs.driver_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
Type Foam::Function1Types::Function1Expression<Type>::value
(
const scalar x
) const
{
// Expression evaluation
driver_.clearVariables();
driver_.setArgument(x);
driver_.parse(this->valueExpr_);
expressions::exprResult result(driver_.result());
DebugInfo
<< "Evaluated: " << result << nl;
if (!result.hasValue() || !result.size() || !result.isType<Type>())
{
FatalErrorInFunction
<< "Could not evaluate: " << this->valueExpr_
<< exit(FatalError);
}
return result.cref<Type>().first();
}
template<class Type>
Type Foam::Function1Types::Function1Expression<Type>::integrate
(
const scalar x1,
const scalar x2
) const
{
NotImplemented;
return Zero;
}
template<class Type>
void Foam::Function1Types::Function1Expression<Type>::writeData
(
Ostream& os
) const
{
// Function1-from-subdict so out dictionary contains
// only the relevant entries.
dict_.writeEntry(this->name(), os);
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 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::Function1Types::Function1Expression
Description
Function1 with values supplied by a parsed expression.
Usage
Example:
\verbatim
<patchName>
{
type uniformFixedValue;
uniformValue
{
type expression;
// optional variables for use within the expression
variables
(
"start = 0.5"
"stop = 1"
);
// A step function
expression
#{
mag(arg() > start && arg() < stop) * vector(1, 0, 0)
#};
}
}
\endverbatim
Very much like '#eval' but runtime
See also
Foam::exprFixedValueFvPatchField
SourceFiles
Function1Expression.C
\*---------------------------------------------------------------------------*/
#ifndef Function1Types_expression_H
#define Function1Types_expression_H
#include "Function1.H"
#include "fieldExprDriver.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace Function1Types
{
/*---------------------------------------------------------------------------*\
Class Function1Expression Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
class Function1Expression
:
public Function1<Type>
{
// Private Data
//- Dictionary contents for the function
const dictionary dict_;
//- The expression
expressions::exprString valueExpr_;
//- The expression driver
mutable expressions::fieldExprDriver driver_;
// Private Member Functions
//- No copy assignment
void operator=(const Function1Expression<Type>&) = delete;
public:
//- Runtime type information
TypeName("expression");
// Constructors
//- Construct from patch, entry name and dictionary
// The patch must correspond to an fvPatch!
Function1Expression
(
const word& entryName,
const dictionary& dict
);
//- Copy construct
explicit Function1Expression(const Function1Expression<Type>& rhs);
//- Destructor
virtual ~Function1Expression() = default;
// Member Functions
//- Return value.
// The parameter 'x' is accessible as 'arg' in the function
virtual Type value(const scalar x) const;
//- Integrate between two values
virtual Type integrate
(
const scalar x1,
const scalar x2
) const;
//- Write in dictionary format
virtual void writeData(Ostream& os) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Function1Types
} // End namespace Foam