ENH: add coded Function1 (#2282)

- update coded templates with qualified names

GIT: add in missing PatchFunction1 constant() method

- was missed in a previous commit
This commit is contained in:
Mark Olesen
2021-12-03 15:33:07 +01:00
parent 8624d65c5a
commit 9a5125111e
31 changed files with 883 additions and 112 deletions

View File

@ -0,0 +1,247 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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 "dynamicCode.H"
#include "dynamicCodeContext.H"
#include "dictionaryContent.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class Type>
Foam::dlLibraryTable&
Foam::Function1Types::CodedFunction1<Type>::libs() const
{
return this->time().libs();
}
template<class Type>
Foam::string
Foam::Function1Types::CodedFunction1<Type>::description() const
{
return "CodedFunction1 " + redirectName_;
}
template<class Type>
void Foam::Function1Types::CodedFunction1<Type>::clearRedirect() const
{
redirectFunctionPtr_.reset(nullptr);
}
template<class Type>
const Foam::dictionary&
Foam::Function1Types::CodedFunction1<Type>::codeContext() const
{
// What else would make sense?
return dict_;
}
template<class Type>
const Foam::dictionary&
Foam::Function1Types::CodedFunction1<Type>::codeDict
(
const dictionary& dict
) const
{
// Use named subdictionary if present to provide the code.
// This allows running with multiple Function1s
return
(
dict.found("code")
? dict
: dict.subDict(redirectName_)
);
}
template<class Type>
const Foam::dictionary&
Foam::Function1Types::CodedFunction1<Type>::codeDict() const
{
return codeDict(dict_);
}
template<class Type>
void Foam::Function1Types::CodedFunction1<Type>::prepare
(
dynamicCode& dynCode,
const dynamicCodeContext& context
) const
{
if (context.code().empty())
{
FatalIOErrorInFunction(dict_)
<< "No code section in input dictionary for Function1 "
<< " name " << redirectName_
<< exit(FatalIOError);
}
// Take no chances - typeName must be identical to redirectName_
dynCode.setFilterVariable("typeName", redirectName_);
// Set TemplateType and FieldType filter variables
dynCode.setFieldTemplates<Type>();
// Compile filtered C template
dynCode.addCompileFile(codeTemplateC);
// Copy filtered H template
dynCode.addCopyFile(codeTemplateH);
#ifdef FULLDEBUG
dynCode.setFilterVariable("verbose", "true");
DetailInfo
<<"compile " << redirectName_ << " sha1: " << context.sha1() << endl;
#endif
// Define Make/options
dynCode.setMakeOptions
(
"EXE_INC = -g \\\n"
"-I$(LIB_SRC)/meshTools/lnInclude \\\n"
+ context.options()
+ "\n\nLIB_LIBS = \\\n"
" -lOpenFOAM \\\n"
" -lmeshTools \\\n"
+ context.libs()
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
Foam::Function1Types::CodedFunction1<Type>::CodedFunction1
(
const word& entryName,
const dictionary& dict,
const objectRegistry* obrPtr
)
:
Function1<Type>(entryName, dict, obrPtr),
codedBase(),
dict_(dict),
redirectName_(dict.getOrDefault<word>("name", entryName))
{
this->codedBase::setCodeContext(dict_);
// No additional code chunks...
updateLibrary(redirectName_);
}
template<class Type>
Foam::Function1Types::CodedFunction1<Type>::CodedFunction1
(
const CodedFunction1<Type>& rhs
)
:
Function1<Type>(rhs),
codedBase(),
dict_(rhs.dict_),
redirectName_(rhs.redirectName_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
const Foam::Function1<Type>&
Foam::Function1Types::CodedFunction1<Type>::redirectFunction() const
{
if (!redirectFunctionPtr_)
{
dictionary constructDict;
// Force 'redirectName_' sub-dictionary into existence
dictionary& coeffs = constructDict.subDictOrAdd(redirectName_);
coeffs = dict_; // Copy input code and coefficients
coeffs.remove("name"); // Redundant
coeffs.set("type", redirectName_); // Specify our new (redirect) type
redirectFunctionPtr_.reset
(
Function1<Type>::New
(
redirectName_,
constructDict,
this->whichDb()
)
);
// Forward copy of codeContext to the code template
auto* contentPtr =
dynamic_cast<dictionaryContent*>(redirectFunctionPtr_.get());
if (contentPtr)
{
contentPtr->dict(this->codeContext());
}
else
{
WarningInFunction
<< redirectName_ << " Did not derive from dictionaryContent"
<< nl << nl;
}
}
return *redirectFunctionPtr_;
}
template<class Type>
Type Foam::Function1Types::CodedFunction1<Type>::value
(
const scalar x
) const
{
// Ensure library containing user-defined code is up-to-date
updateLibrary(redirectName_);
return redirectFunction().value(x);
}
template<class Type>
void Foam::Function1Types::CodedFunction1<Type>::writeData
(
Ostream& os
) const
{
// Should really only output only relevant entries but since using
// Function1-from-subdict upon construction our dictionary contains
// only the relevant entries.
dict_.writeEntry(this->name(), os);
}
// ************************************************************************* //

View File

@ -0,0 +1,225 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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::CodedFunction1
Description
Function1 with the code supplied by an on-the-fly compiled C++
expression.
The code entries:
\plaintable
codeInclude | include files
codeOptions | compiler line: added to EXE_INC (Make/options)
codeLibs | linker line: added to LIB_LIBS (Make/options)
localCode | c++; local static functions
code | c++; return the patch values at (scalar x)
\endplaintable
Usage
Example:
\verbatim
<patchName>
{
type uniformFixedValue;
uniformValue
{
type coded;
name myExpression; // Name of generated PatchFunction1
code
#{
const polyPatch& pp = this->patch();
Pout<< "** Patch size:" << pp.size() << endl;
return tmp<vectorField>::New(pp.size(), vector(1, 0, 0))
#};
//codeInclude
//#{
// #include "volFields.H"
//#};
//codeOptions
//#{
// -I$(LIB_SRC)/finiteVolume/lnInclude
//#};
}
}
\endverbatim
Note
The code context dictionary is simply the dictionary used to specify
the PatchFunction1 coefficients.
See also
Foam::dynamicCode
Foam::codedFixedValue
Foam::functionEntries::codeStream
SourceFiles
CodedFunction1.C
\*---------------------------------------------------------------------------*/
#ifndef Function1Types_CodedFunction1_H
#define Function1Types_CodedFunction1_H
#include "Function1.H"
#include "codedBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace Function1Types
{
/*---------------------------------------------------------------------------*\
Class CodedFunction1 Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
class CodedFunction1
:
public Function1<Type>,
protected codedBase
{
// Private Data
//- Dictionary contents for the function
const dictionary dict_;
const word redirectName_;
mutable autoPtr<Function1<Type>> redirectFunctionPtr_;
// Private Member Functions
//- Get reference to the underlying Function1
const Function1<Type>& redirectFunction() const;
protected:
// Protected Member Functions
//- Mutable access to the loaded dynamic libraries
virtual dlLibraryTable& libs() const;
//- Description (type + name) for the output
virtual string description() const;
//- Clear redirected object(s)
virtual void clearRedirect() const;
//- Additional 'codeContext' dictionary to pass through
virtual const dictionary& codeContext() const;
// Get the code (sub)dictionary
virtual const dictionary& codeDict(const dictionary& dict) const;
// Get the code dictionary
virtual const dictionary& codeDict() const;
//- Adapt the context for the current object
virtual void prepare(dynamicCode&, const dynamicCodeContext&) const;
// Generated Methods
//- No copy assignment
void operator=(const CodedFunction1<Type>&) = delete;
public:
// Static Data Members
//- Name of the C code template to be used
static constexpr const char* const codeTemplateC
= "codedFunction1Template.C";
//- Name of the H code template to be used
static constexpr const char* const codeTemplateH
= "codedFunction1Template.H";
//- Runtime type information
TypeName("coded");
// Constructors
//- Construct from entry name, dictionary and optional registry
CodedFunction1
(
const word& entryName,
const dictionary& dict,
const objectRegistry* obrPtr = nullptr
);
//- Copy construct
explicit CodedFunction1(const CodedFunction1<Type>& rhs);
//- Construct and return a clone
virtual tmp<Function1<Type>> clone() const
{
return tmp<Function1<Type>>(new CodedFunction1<Type>(*this));
}
//- Destructor
virtual ~CodedFunction1() = default;
// Member Functions
//- Return value at current time
virtual inline Type value(const scalar x) const;
// Integrate etc are not implemented!
//- Write in dictionary format
virtual void writeData(Ostream& os) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Function1Types
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "CodedFunction1.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -78,7 +78,7 @@ void Foam::Function1Types::FunctionObjectTrigger<Type>::writeEntries
) const
{
os.writeKeyword("triggers");
flatOutput(triggers_);
os << flatOutput(triggers_);
os.endEntry();
if (defaultValue_)

View File

@ -26,6 +26,7 @@ License
\*---------------------------------------------------------------------------*/
#include "CodedFunction1.H"
#include "Constant.H"
#include "Uniform.H"
#include "ZeroConstant.H"
@ -48,6 +49,7 @@ License
#define makeFunction1s(Type) \
makeFunction1(Type); \
makeFunction1Type(CodedFunction1, Type); \
makeFunction1Type(Constant, Type); \
makeFunction1Type(Uniform, Type); \
makeFunction1Type(None, Type); \