ENH: base fvMesh driver for expressions

This commit is contained in:
Mark Olesen
2019-12-03 12:34:33 +01:00
parent 7e275838ad
commit 019fe7deff
10 changed files with 2869 additions and 0 deletions

View File

@ -250,6 +250,15 @@ $(constraintFvsPatchFields)/wedge/wedgeFvsPatchFields.C
fields/volFields/volFields.C
fields/surfaceFields/surfaceFields.C
expr = expressions
$(expr)/base/exprDriverWriter.C
$(expr)/base/fvExprDriver.C
$(expr)/base/fvExprDriverFields.C
$(expr)/base/fvExprDriverIO.C
$(expr)/base/fvExprDriverNew.C
fvMatrices/fvMatrices.C
fvMatrices/fvScalarMatrix/fvScalarMatrix.C
fvMatrices/solvers/MULES/MULES.C

View File

@ -0,0 +1,100 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
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 "exprDriverWriter.H"
#include "fvExprDriver.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
defineTypeName(exprDriverWriter);
} // namespace expressions
} // namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::expressions::exprDriverWriter::exprDriverWriter
(
const word& name,
fvExprDriver& driver
)
:
regIOobject
(
IOobject
(
name,
driver.mesh().time().timeName(),
"expressions",
driver.mesh().time(),
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
)
),
driver_(driver)
{
if (headerOk())
{
readData(readStream("exprDriverWriter", true));
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::expressions::exprDriverWriter::readData(Istream& is)
{
dictionary dict(is);
// driver_.readDict(is);
driver_.getData(dict);
return !is.bad();
}
bool Foam::expressions::exprDriverWriter::writeData(Ostream& os) const
{
// driver_.writeDict(os);
dictionary dict;
driver_.prepareData(dict);
dict.write(os, false);
return os.good();
}
// ************************************************************************* //

View File

@ -0,0 +1,109 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
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/>.
Class
Foam::expressions::exprDriverWriter
Description
Registered input/output for an expressions::fvExprDriver
SourceFiles
exprDriverWriter.C
\*---------------------------------------------------------------------------*/
#ifndef expressions_exprDriverWriter_H
#define expressions_exprDriverWriter_H
#include "fvExprDriver.H"
#include "regIOobject.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
/*---------------------------------------------------------------------------*\
Class exprDriverWriter Declaration
\*---------------------------------------------------------------------------*/
class exprDriverWriter
:
public regIOobject
{
// Private Data
//- The driver to read/write
fvExprDriver& driver_;
// Private Member Functions
//- No null constructor
exprDriverWriter() = delete;
//- No copy construct
exprDriverWriter(const exprDriverWriter&) = delete;
//- No copy assignment
void operator=(const exprDriverWriter&) = delete;
public:
//- Runtime type information
TypeNameNoDebug("exprDriverWriter");
// Constructors
//- Construct for named driver
exprDriverWriter(const word& name, fvExprDriver& driver);
//- Destructor
virtual ~exprDriverWriter() = default;
// Member Functions
virtual bool readData(Istream& is);
virtual bool writeData(Ostream& os) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,765 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
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 "fvExprDriver.H"
#include "exprDriverWriter.H"
#include "expressionEntry.H"
#include "exprResultGlobals.H"
#include "cellSet.H"
#include "faceSet.H"
#include "pointSet.H"
#include "stringOps.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
defineTypeNameAndDebug(fvExprDriver, 0);
defineRunTimeSelectionTable(fvExprDriver, dictionary);
defineRunTimeSelectionTable(fvExprDriver, idName);
} // End namespace expressions
} // End namespace Foam
// Currently not working?
bool Foam::expressions::fvExprDriver::cacheSets_ = true;
const Foam::fvMesh* Foam::expressions::fvExprDriver::defaultMeshPtr_ = nullptr;
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
const Foam::fvMesh& Foam::expressions::fvExprDriver::defaultMesh()
{
if (!defaultMeshPtr_)
{
FatalErrorInFunction
<< "No default mesh set" << nl
<< "Try the 'fvExprDriverFunctionObject' as a workaround"
<< endl
<< abort(FatalError);
}
return *defaultMeshPtr_;
}
const Foam::fvMesh* Foam::expressions::fvExprDriver::resetDefaultMesh
(
const fvMesh& mesh,
const bool force
)
{
const fvMesh* ptr = defaultMeshPtr_;
if (force || (ptr != nullptr))
{
defaultMeshPtr_ = &mesh;
}
return ptr;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::expressions::fvExprDriver::fvExprDriver
(
bool cacheReadFields,
bool searchInMemory,
bool searchOnDisc,
const dictionary& dict
)
:
expressions::exprDriver
(
cacheReadFields,
searchInMemory,
searchOnDisc,
dict
),
globalScopes_(),
delayedVariables_(),
storedVariables_(),
specialVariablesIndex_(-1),
otherMeshName_(),
libs_(),
writer_(nullptr)
{}
Foam::expressions::fvExprDriver::fvExprDriver
(
const fvExprDriver& rhs
)
:
expressions::exprDriver(rhs),
globalScopes_(rhs.globalScopes_),
delayedVariables_(rhs.delayedVariables_),
storedVariables_(rhs.storedVariables_),
specialVariablesIndex_(rhs.specialVariablesIndex_),
otherMeshName_(),
libs_(),
writer_(nullptr)
{}
Foam::expressions::fvExprDriver::fvExprDriver
(
const dictionary& dict
)
:
fvExprDriver
(
dict.lookupOrDefault("cacheReadFields", false),
dict.lookupOrDefault("searchInMemory", true),
dict.lookupOrDefault("searchOnDisc", false),
dict
)
{
readDict(dict);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::expressions::fvExprDriver::~fvExprDriver()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::expressions::fvExprDriver::readDict
(
const dictionary& dict
)
{
expressions::exprDriver::readDict(dict);
// wordList plugins;
// if (dict.readIfPresent("functionPlugins", plugins))
// {
// for (const word& plugin : plugins)
// {
// libs_.open("libswak" + plugin + "FunctionPlugin.so");
// }
// }
dict.readIfPresent("globalScopes", globalScopes_);
const entry* eptr = nullptr;
// Special variables
if
(
// storedVariables
(eptr = dict.findEntry("storedVariables", keyType::LITERAL))
!= nullptr
)
{
ITstream& is = eptr->stream();
if (writer_.valid() && storedVariables_.size())
{
WarningInFunction
// << "Context: " << driverContext_ << nl
<< "The 'storedVariables' was already read."
<< " No update from " << is
<< endl;
}
else
{
storedVariables_ = List<exprResultStored>(is);
// Check for excess tokens
dict.checkITstream(is, "storedVariables");
}
}
if
(
// delayedVariables
(eptr = dict.findEntry("delayedVariables", keyType::LITERAL))
!= nullptr
)
{
ITstream& is = eptr->stream();
if (writer_.valid() && delayedVariables_.size())
{
WarningInFunction
// << "Context: " << driverContext_ << nl
<< "Seems like 'delayedVariables' was already read."
<< " No update from " << is
<< endl;
}
else
{
List<exprResultDelayed> inputs(is);
// Check for excess tokens
dict.checkITstream(is, "delayedVariables");
for (auto& var : inputs)
{
delayedVariables_.insert(var.name(), var);
}
}
}
return true;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::Time& Foam::expressions::fvExprDriver::runTime() const
{
return this->mesh().time();
}
Foam::word Foam::expressions::fvExprDriver::timeName() const
{
return runTime().timeName();
}
Foam::scalar Foam::expressions::fvExprDriver::timeValue() const
{
return runTime().value();
}
void Foam::expressions::fvExprDriver::updateSpecialVariables(bool force)
{
const bool updated = this->update();
const label eventIndex = mesh().time().timeIndex();
const scalar eventTime = mesh().time().value();
DebugInfo
<< "fvExprDriver::updateSpecialVariables(force="
<< force << ") Updated: " << updated << endl;
if (specialVariablesIndex_ < 0)
{
DebugInfo
<< "First update: " << eventIndex << endl;
specialVariablesIndex_ = eventIndex;
for (exprResultStored& v : storedVariables_)
{
DebugInfo
<< v.name() << " = " << v.initialValueExpression()
<< " (has value "
<< v.hasValue() << ")" << endl;
if (!v.hasValue())
{
DebugInfo
<< "First value: " << v.initialValueExpression()
<< " -> " << v.name() << endl;
parse(v.initialValueExpression());
v = result_;
DebugInfo
<< "Parser size: " << this->size() << nl
<< "Calculated: " << result_ << nl
<< "Stored: " << v << nl;
}
}
}
if (force || specialVariablesIndex_ != eventIndex)
{
DebugInfo
<< "Store variables: " << force << ' '
<< specialVariablesIndex_ << ' '
<< eventIndex << endl;
for (exprResultStored& v : storedVariables_)
{
if (variables_.found(v.name()))
{
DebugInfo
<< "Storing variable: " << v.name() << " "
<< variables_[v.name()] << endl;
v = variables_[v.name()];
}
}
specialVariablesIndex_ = eventIndex;
}
forAllIters(delayedVariables_, iter)
{
DebugInfo
<< "Updating delayed variable " << iter().name() << endl;
if (!iter().updateReadValue(eventTime))
{
const exprString& expr = iter().startupValueExpression();
DebugInfo
<< "Evaluate: " << expr << endl;
parse(expr);
iter().setReadValue(result_);
DebugInfo
<< "Value " << iter() << nl
<< "Type " << iter().valueType() << "("
<< result_.valueType() << ")" << endl;
}
else
{
DebugInfo
<< iter().name() << " updated without problem" << endl;
}
}
}
void Foam::expressions::fvExprDriver::clearVariables()
{
DebugInfo
<< "Clearing variables" << endl;
const scalar eventTime = mesh().time().value();
(void)this->update();
updateSpecialVariables();
variables_.clear();
for (exprResultStored& v : storedVariables_)
{
variables_.insert(v.name(), v);
}
addVariables(variableStrings_, false);
forAllIters(delayedVariables_, iter)
{
iter().storeValue(eventTime);
}
}
void Foam::expressions::fvExprDriver::evaluateVariable
(
const word& varName,
const expressions::exprString& expr
)
{
const regIOobject* objPtr = mesh().findObject<regIOobject>(varName);
if (!allowShadowing_ && objPtr)
{
WarningInFunction
// << "Context: " << driverContext_ << nl
<< "Field '" << varName << "' (type " << objPtr->headerClassName()
<< ") is shadowed by a variable of the same name." << nl
<< "This may lead to trouble" << nl
<< "If this is OK set 'allowShadowing'"
<< " in the relevant parser" << nl
<< endl;
}
parse(expr);
result_.testIfSingleValue();
DebugInfo
<< "Evaluating: " << expr << " -> " << varName << endl
<< result_;
// Assign
if (delayedVariables_.found(varName))
{
// Avoid potential conflicts?
variables_.erase(varName);
DebugInfo
<< varName << " is delayed" << endl;
// Copy assignment
delayedVariables_[varName] = result_;
}
else
{
// Overwrite with a copy
variables_.set(varName, exprResult(result_));
}
}
void Foam::expressions::fvExprDriver::evaluateVariableRemote
(
string remote,
const word& varName,
const expressions::exprString& expr
)
{
DebugInfo
<< "Evaluating remote " << remote.c_str()
<< " : " << expr << " -> " << varName << endl;
word driverType("patch"); // default is patch
word identName, regionName;
const auto slashPos = remote.find('/');
if (slashPos != std::string::npos)
{
regionName = word::validate(remote.substr(slashPos+1));
remote.resize(slashPos);
}
const auto quotePos = remote.find('\'');
if (quotePos != std::string::npos)
{
driverType = word::validate(remote.substr(0, quotePos));
identName = word::validate(remote.substr(quotePos+1));
}
else
{
identName = word::validate(remote);
}
if
(
driverType == "patch"
&&
(
identName.empty()
|| identName == "volume"
|| identName == "internalField"
)
)
{
driverType = "internalField";
}
const fvMesh* pRegion = &(this->mesh());
if (!regionName.empty())
{
pRegion = pRegion->time().cfindObject<fvMesh>(regionName);
if (!pRegion)
{
FatalErrorInFunction
<< "Cannot resolve mesh region: " << regionName << nl
<< exit(FatalError);
}
}
DebugInfo
<< "Call other with ("
<< driverType << ", " << identName << ", " << regionName << ")\n";
autoPtr<fvExprDriver> otherDriver =
fvExprDriver::New(driverType, identName, *pRegion);
otherDriver->setSearchBehaviour(*this);
otherDriver->setGlobalScopes(this->globalScopes_);
otherDriver->parse(expr);
exprResult otherResult(this->getRemoteResult(*otherDriver));
// Check / re-check for uniform. Not normally needed
if (!otherResult.isUniform())
{
otherResult.testIfSingleValue();
}
DebugInfo
<< "Remote result: " << otherResult << nl;
// Assign
if (delayedVariables_.found(varName))
{
// Avoid potential conflicts?
variables_.erase(varName);
DebugInfo
<< varName << " is delayed - setting" << nl;
// Move assignment
delayedVariables_[varName] = std::move(otherResult);
}
else
{
// Overwrite with a copy
variables_.set(varName, std::move(otherResult));
}
}
const Foam::fvMesh&
Foam::expressions::fvExprDriver::regionMesh
(
const dictionary& dict,
const fvMesh& mesh,
bool readIfNecessary
)
{
word regionName;
if (!dict.readIfPresent("region", regionName))
{
DebugInFunction << "Using original mesh " << nl;
return mesh;
}
DebugInFunction << "Using mesh " << regionName << endl;
fvMesh* meshPtr = mesh.time().getObjectPtr<fvMesh>(regionName);
if (!meshPtr && readIfNecessary)
{
WarningInFunction
<< "Region " << regionName
<< " not in memory. Loading it" << endl;
meshPtr = new fvMesh
(
IOobject
(
regionName,
mesh.time().constant(),
mesh.time(),
IOobject::MUST_READ
)
);
meshPtr->polyMesh::store();
}
if (!meshPtr)
{
FatalErrorInFunction
<< "No mesh region loaded: " << regionName
<< endl;
}
return *meshPtr;
}
Foam::word Foam::expressions::fvExprDriver::getTypeOfField
(
const word& fieldName
) const
{
return getHeaderClassName(this->mesh(), fieldName);
}
Foam::word Foam::expressions::fvExprDriver::getFieldClassName
(
const word& name
) const
{
if (searchInMemory())
{
const regIOobject* ioptr = this->mesh().findObject<regIOobject>(name);
if (ioptr)
{
return ioptr->type();
}
}
if (searchOnDisc())
{
return getHeaderClassName(this->mesh(), name);
}
return word::null;
}
Foam::topoSetSource::sourceType
Foam::expressions::fvExprDriver::topoSetType(const word& setName) const
{
IOobject io(topoSet::findIOobject(mesh(), setName));
if (cellSet::typeName == io.headerClassName())
{
return topoSetSource::sourceType::CELLSET_SOURCE;
}
if (faceSet::typeName == io.headerClassName())
{
return topoSetSource::sourceType::FACESET_SOURCE;
}
if (pointSet::typeName == io.headerClassName())
{
return topoSetSource::sourceType::POINTSET_SOURCE;
}
return topoSetSource::sourceType::UNKNOWN_SOURCE;
}
Foam::topoSetSource::sourceType
Foam::expressions::fvExprDriver::topoZoneType(const word& setName) const
{
if (mesh().cellZones().findZoneID(setName) >= 0)
{
return topoSetSource::sourceType::CELLZONE_SOURCE;
}
if (mesh().faceZones().findZoneID(setName) >= 0)
{
return topoSetSource::sourceType::FACEZONE_SOURCE;
}
if (mesh().pointZones().findZoneID(setName) >= 0)
{
return topoSetSource::sourceType::POINTZONE_SOURCE;
}
return topoSetSource::sourceType::UNKNOWN_SOURCE;
}
Foam::topoSetSource::sourceType
Foam::expressions::fvExprDriver::topoSourceType(const word& setName) const
{
auto setType = topoZoneType(setName);
if (topoSetSource::sourceType::UNKNOWN_SOURCE == setType)
{
setType = topoSetType(setName);
}
return setType;
}
bool Foam::expressions::fvExprDriver::isCellSet(const word& setName) const
{
return
(
topoSetSource::sourceType::CELLSET_SOURCE
== topoSetType(setName)
);
}
bool Foam::expressions::fvExprDriver::isFaceSet(const word& setName) const
{
return
(
topoSetSource::sourceType::FACESET_SOURCE
== topoSetType(setName)
);
}
bool Foam::expressions::fvExprDriver::isPointSet(const word& setName) const
{
return
(
topoSetSource::sourceType::POINTSET_SOURCE
== topoSetType(setName)
);
}
bool Foam::expressions::fvExprDriver::isCellZone(const word& name) const
{
return (mesh().cellZones().findZoneID(name) >= 0);
}
bool Foam::expressions::fvExprDriver::isFaceZone(const word& name) const
{
return (mesh().faceZones().findZoneID(name) >= 0);
}
bool Foam::expressions::fvExprDriver::isPointZone(const word& name) const
{
return (mesh().pointZones().findZoneID(name) >= 0);
}
const Foam::expressions::exprResult&
Foam::expressions::fvExprDriver::lookupGlobal
(
const word& name
) const
{
return exprResultGlobals::New(this->mesh()).get(name, globalScopes_);
}
bool Foam::expressions::fvExprDriver::hasDataToWrite() const
{
return (!storedVariables_.empty() || !delayedVariables_.empty());
}
void Foam::expressions::fvExprDriver::getData
(
const dictionary& dict
)
{
dict.readIfPresent("storedVariables", storedVariables_);
}
void Foam::expressions::fvExprDriver::prepareData
(
dictionary& dict
) const
{
auto& driver = const_cast<fvExprDriver&>(*this);
(void)driver.update();
if (storedVariables_.size())
{
driver.updateSpecialVariables(true);
dict.add("storedVariables", storedVariables_);
}
}
// ************************************************************************* //

View File

@ -0,0 +1,646 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Original code Copyright (C) 2010-2018 Bernhard Gschaider
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/>.
Class
Foam::expressions::fvExprDriver
Description
Base driver for parsing value expressions associated with an fvMesh.
Largely based on code and ideas from swak4foam
Properties
\table
Property | Description | Required | Default
variables | List of variables for expressions | no | ()
delayedVariables | List of delayed variables | no | ()
storedVariables | List of stored variables | no | ()
globalScopes | Scopes for global variables | no | ()
allowShadowing | Allow variables to shadow field names | no | false
\endtable
Debug Properties
\table
Property | Description | Required | Default
debugBaseDriver | Debug level (int) for base driver | no |
debugScanner | Add debug for scanner | no | false
debugParser | Add debug for parser | no | false
\endtable
SourceFiles
fvExprDriverI.H
fvExprDriver.C
fvExprDriverFields.C
fvExprDriverIO.C
fvExprDriverNew.C
fvExprDriverTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef expressions_fvExprDriver_H
#define expressions_fvExprDriver_H
#include "exprDriver.H"
#include "exprResultDelayed.H"
#include "exprResultStored.H"
#include "pointMesh.H"
#include "volFields.H"
#include "topoSetSource.H"
#include "dlLibraryTable.H"
#include "runTimeSelectionTables.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
// Forward Declarations
class exprDriverWriter;
/*---------------------------------------------------------------------------*\
Class fvExprDriver Declaration
\*---------------------------------------------------------------------------*/
class fvExprDriver
:
public expressions::exprDriver
{
// Static Data
//- Pointer to the "default" mesh
static const fvMesh *defaultMeshPtr_;
//- Cache cellSets, faceSets insted of reading from disc each time
static bool cacheSets_;
// Protected Data
// Stored Data
//- The scopes for global variables
List<word> globalScopes_;
//- The (delayed) variables table
HashTable<exprResultDelayed> delayedVariables_;
//- Stored expressions. Read from dictionary and updated as required
List<exprResultStored> storedVariables_;
//- Time index when handling special variables
label specialVariablesIndex_;
//- The name of the other mesh (if it is to be required)
word otherMeshName_;
//- Additional libraries
dlLibraryTable libs_;
//- Writing and restoring
autoPtr<exprDriverWriter> writer_;
// Private Member Functions
//- Read the IOobject and return the headerClassName
static word getHeaderClassName
(
const polyMesh& mesh,
const word& name
);
//- Read the set IOobject and return its headerClassName
static word getSetClassName
(
const polyMesh& mesh,
const word& name
);
//- No copy assignment
void operator=(const fvExprDriver&) = delete;
protected:
// Static Member Functions
//- Determine mesh or region mesh as specified in the dictionary
//- with the keyword "region"
static const fvMesh& regionMesh
(
const dictionary& dict,
const fvMesh& mesh,
bool readIfNecessary
);
//- Default boundary type is calculated
template<class T>
static inline word defaultBoundaryType(const T&)
{
return "calculated";
}
//- Default boundary type for volume fields is zeroGradient
template<class Type>
static inline word defaultBoundaryType
(
const GeometricField<Type, fvPatchField, volMesh>&
)
{
return "zeroGradient";
}
//- Apply correctBoundaryConditions (volume fields only)
template<class T>
static inline void correctField(T&) {}
template<class Type>
static inline void correctField
(
GeometricField<Type, fvPatchField, volMesh>& fld
)
{
fld.correctBoundaryConditions();
}
// Protected Member Functions
// Mesh related
//- The mesh we are attached to
virtual const fvMesh& mesh() const = 0;
// Variables
//- Define scopes for global variables
void setGlobalScopes(const wordUList& scopes)
{
globalScopes_ = scopes;
}
//- Non-const access to the named variable (sub-classes only)
inline virtual exprResult& variable(const word& name);
//- Test existence of a global variable
template<class T>
bool isGlobalVariable
(
const word& name,
bool isPointVal,
label expectedSize = -1
) const;
//- Return the global variable if available or a null result
const exprResult& lookupGlobal(const word& name) const;
// Fields
//- Test for the existence of a mesh field
template<class Type>
bool isField
(
const word& name,
bool isPointVal = false,
label expectSize = -1 //!< ignored
) const;
//- Retrieve field from memory or disk
template<class GeomField>
inline tmp<GeomField> getOrReadField
(
const word& name,
bool mandatory = true,
bool getOldTime = false
);
//- Retrieve point field from memory or disk
template<class GeomField>
inline tmp<GeomField> getOrReadPointField
(
const word& name,
bool mandatory = true,
bool getOldTime = false
);
//- Retrieve field from memory or disk (implementation)
template<class GeomField, class MeshRef>
tmp<GeomField> getOrReadFieldImpl
(
const word& name,
const MeshRef& meshRef,
bool mandatory = true,
bool getOldTime = false
);
//- Helper function for getOrReadField
template<class GeomField, class MeshRef>
inline tmp<GeomField> readAndRegister
(
const word& name,
const MeshRef& meshRef
);
//- Create a random field
//
// \param field the field to populate
// \param seed the seed value. If zero or negative, use as an offset
// to the current timeIndex
// \param gaussian generate a Gaussian distribution
void fill_random
(
scalarField& field,
label seed = 0,
const bool gaussian = false
) const;
// Sets
//- The origin of the topoSet
enum SetOrigin { INVALID = 0, NEW, FILE, MEMORY, CACHE };
//- Get topoSet
template<class T>
autoPtr<T> getTopoSet
(
const fvMesh& mesh,
const word& setName,
SetOrigin& origin
) const;
//- Update topoSet
template<class T>
inline bool updateSet
(
autoPtr<T>& setPtr,
const word& setName,
SetOrigin origin
) const;
// Updating
//- Examine current variable values and update stored variables
virtual void updateSpecialVariables(bool force=false);
//- Do we need a data file to be written
virtual bool hasDataToWrite() const;
//- Prepare/update special variables and add to dictionary,
//- normally via the reader/writer
virtual void prepareData(dictionary& dict) const;
//- Read data from dictionary, normally via the reader/writer
virtual void getData(const dictionary& dict);
public:
// Friends
friend class exprDriverWriter;
// Static Member Functions
//- Get the default mesh, if one is defined
static const fvMesh& defaultMesh();
//- Set the default mesh (if not already set)
static const fvMesh* resetDefaultMesh
(
const fvMesh& mesh,
const bool force = false //!< Force reset, even if already set
);
//- Runtime type information
TypeName("fvExprDriver");
// Run-time selection
declareRunTimeSelectionTable
(
autoPtr,
fvExprDriver,
dictionary,
(
const dictionary& dict,
const fvMesh& mesh
),
(dict,mesh)
);
declareRunTimeSelectionTable
(
autoPtr,
fvExprDriver,
idName,
(
const word& ident,
const fvMesh& mesh
),
(ident, mesh)
);
// Constructors
//- Null constructor, and null construct with search preferences
explicit fvExprDriver
(
bool cacheReadFields = false,
bool searchInMemory = true,
bool searchOnDisc = false,
const dictionary& dict = dictionary::null
);
//- Copy construct
fvExprDriver(const fvExprDriver&);
//- Construct from a dictionary
explicit fvExprDriver(const dictionary& dict);
//- Return a reference to the selected value driver
static autoPtr<fvExprDriver> New
(
const dictionary& dict,
const fvMesh& mesh
);
//- Return a reference to the selected value driver
static autoPtr<fvExprDriver> New
(
const dictionary& dict
);
//- Return a reference to the selected value driver
static autoPtr<fvExprDriver> New
(
const word& type,
const word& id,
const fvMesh& mesh
);
//- Clone
virtual autoPtr<fvExprDriver> clone() const = 0;
//- Destructor
virtual ~fvExprDriver();
// Public Member Functions
//- The underlying field size for the expression
virtual label size() const = 0;
//- The underlying point field size for the expression
virtual label pointSize() const = 0;
// Mesh Related
//- The Time associated with the mesh
const Time& runTime() const;
//- The current time name
virtual word timeName() const;
//- The current time value
virtual scalar timeValue() const;
// General Controls
//- Status of cache-sets (static variable)
bool cacheSets() const { return cacheSets_; }
// Variables
//- Clear temporary variables and resets from expression strings
virtual void clearVariables();
//- True if named variable exists
inline virtual bool hasVariable(const word& name) const;
//- Return const-access to the named variable
inline virtual const exprResult& variable(const word& name) const;
//- Test for existence of a local/global variable or a field
template<class Type>
inline bool isVariableOrField
(
const word& name,
bool isPointVal = false,
label expectSize = -1
) const;
//- Retrieve local/global variable as a tmp field
//
// \param name The name of the local/global field
// \param expectSize The size check on the variable, -1 to ignore
// \param mandatory A missing variable is Fatal, or return
// an invalid tmp
template<class Type>
tmp<Field<Type>> getVariable
(
const word& name,
label expectSize,
const bool mandatory = true
) const;
//- Lookup the field class name (memory or read from disk)
//
// Return empty if the name cannot be resolved.
word getFieldClassName(const word& name) const;
// Types
//- Return cell/face/point set type or unknown
topoSetSource::sourceType topoSetType(const word& name) const;
//- Return cell/face/point zone type or unknown
topoSetSource::sourceType topoZoneType(const word& name) const;
//- Return cell/face/point zone/set type or unknown
topoSetSource::sourceType topoSourceType(const word& name) const;
//- Read and return labels associated with the topo set
labelList getTopoSetLabels
(
const word& name,
enum topoSetSource::sourceType setType
) const;
//- Test if name is a known cellZone
bool isCellZone(const word& name) const;
//- Test if name is a known faceZone
bool isFaceZone(const word& name) const;
//- Test if name is a known pointZone
bool isPointZone(const word& name) const;
//- Test if name is a known cellSet
bool isCellSet(const word& name) const;
//- Test if name is a known faceSet
bool isFaceSet(const word& name) const;
//- Test if name is a known pointSet
bool isPointSet(const word& name) const;
// Evaluation
//- Evaluate the expression
//- and save as the specified named variable
virtual void evaluateVariable
(
const word& varName,
const expressions::exprString& expr
);
//- Evaluate an expression on a remote
//- and save as the specified named variable
//
// The fully qualified form of the remote is given as follows
// \verbatim
// type'name/region
// \endverbatim
//
// If not specified, the default type is "patch", which means the
// following are equivalent
// \verbatim
// patch'name/region
// name/region
// \endverbatim
//
// If region is identical to the current region, it can be omitted:
// \verbatim
// patch'name
// name (default is patch)
// \endverbatim
virtual void evaluateVariableRemote
(
string remote,
const word& varName,
const expressions::exprString& expr
);
// Fields
//- Test existence of a local/global variable
template<class Type>
inline bool isVariable
(
const word& name,
bool isPointVal = false,
label expectSize = -1
) const;
//- Test if specified field can be found in memory or disk
template<class Type>
bool foundField(const word& name) const;
//- Read the IOobject for fieldName and return its headerClassName
// Empty if the field could not be found.
word getTypeOfField(const word& fieldName) const;
// Handling remote data (future)
// //- Access the other mesh name (future)
// const word& otherMeshName() const { return otherMeshName_; }
//
// //- Access the other mesh name (future)
// word& otherMeshName() { return otherMeshName_; }
// Reading
//- Read variables, tables etc.
// Also usable for objects not constructed from a dictionary.
virtual bool readDict(const dictionary& dict);
// Writing
//- Write "variables", "storedVariables", "delayedVariables",
//- "globalScopes" if they are present.
Ostream& writeCommon(Ostream& os, bool debug=false) const;
//- Create a writer for this object
void createWriterAndRead(const word& name);
//- Write data if apropriate
//- Should enable exact restarts
void tryWrite() const;
// Plugins (future)
/// //- Tests for a plugin-function
/// virtual bool hasPlugin(const word& name) = 0;
///
/// //- Return a new plugin-function
/// virtual autoPtr<CommonPluginFunction>
/// getPlugin(const word& name) = 0;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "fvExprDriverI.H"
#ifdef NoRepository
#include "fvExprDriverTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,49 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
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 "fvExprDriver.H"
#include "Time.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::expressions::fvExprDriver::fill_random
(
scalarField& field,
label seed,
const bool gaussian
) const
{
exprDriver::fill_random
(
field, (seed <= 0 ? (runTime().timeIndex() - seed) : seed),
gaussian
);
}
// ************************************************************************* //

View File

@ -0,0 +1,179 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
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 "Time.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline bool Foam::expressions::fvExprDriver::hasVariable
(
const word& name
) const
{
return delayedVariables_.found(name) || variables_.found(name);
}
inline const Foam::expressions::exprResult&
Foam::expressions::fvExprDriver::variable
(
const word& name
) const
{
if (delayedVariables_.found(name))
{
return delayedVariables_[name];
}
return variables_[name];
}
inline Foam::expressions::exprResult&
Foam::expressions::fvExprDriver::variable
(
const word& name
)
{
if (delayedVariables_.found(name))
{
return delayedVariables_[name];
}
return variables_[name];
}
template<class Type>
inline bool Foam::expressions::fvExprDriver::isVariable
(
const word& name,
bool isPointVal,
label expectedSize
) const
{
return
(
this->isLocalVariable<Type>(name, isPointVal, expectedSize)
|| this->isGlobalVariable<Type>(name, isPointVal, expectedSize)
);
}
template<class Type>
inline bool Foam::expressions::fvExprDriver::isVariableOrField
(
const word& name,
bool isPointVal,
label expectedSize
)
const
{
return
(
this->isVariable<Type>(name, isPointVal, expectedSize)
|| this->isField<Type>(name, isPointVal)
);
}
template<class GeomField>
inline Foam::tmp<GeomField>
Foam::expressions::fvExprDriver::getOrReadField
(
const word& name,
bool mandatory,
bool getOldTime
)
{
return this->getOrReadFieldImpl<GeomField>
(
name,
this->mesh(),
mandatory,
getOldTime
);
}
template<class GeomField>
inline Foam::tmp<GeomField>
Foam::expressions::fvExprDriver::getOrReadPointField
(
const word& name,
bool mandatory,
bool getOldTime
)
{
return this->getOrReadFieldImpl<GeomField>
(
name,
pointMesh::New(this->mesh()),
mandatory,
getOldTime
);
}
template<class GeomField, class Mesh>
inline Foam::tmp<GeomField>
Foam::expressions::fvExprDriver::readAndRegister
(
const word& name,
const Mesh& meshRef
)
{
GeomField* ptr = new GeomField
(
IOobject
(
name,
meshRef.thisDb().time().timeName(),
meshRef.thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE,
false // Unregistered
),
meshRef
);
if (cacheReadFields())
{
DebugInfo
<< "Registering a copy of " << name << " with mesh" << nl;
// This is clunky
ptr->checkIn();
return tmp<GeomField>(regIOobject::store(ptr));
}
return tmp<GeomField>(ptr);
}
// ************************************************************************* //

View File

@ -0,0 +1,280 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
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 "fvExprDriver.H"
#include "exprDriverWriter.H"
#include "cellSet.H"
#include "faceSet.H"
#include "pointSet.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
Foam::labelList Foam::expressions::fvExprDriver::getTopoSetLabels
(
const word& name,
enum topoSetSource::sourceType setType
) const
{
// Zones first - they are cheap to handle (no IO)
switch (setType)
{
case topoSetSource::sourceType::CELLZONE_SOURCE:
{
const auto& zones = mesh().cellZones();
const word& zoneTypeName = cellZone::typeName;
const label zoneID = zones.findZoneID(name);
if (zoneID < 0)
{
FatalErrorInFunction
<< "No " << zoneTypeName << " named "
<< name << "found. Has zones: " << zones.names() << endl
<< exit(FatalError);
}
return zones[zoneID];
break;
}
case topoSetSource::sourceType::FACEZONE_SOURCE:
{
const auto& zones = mesh().faceZones();
const word& zoneTypeName = faceZone::typeName;
const label zoneID = zones.findZoneID(name);
if (zoneID < 0)
{
FatalErrorInFunction
<< "No " << zoneTypeName << " named "
<< name << "found. Has zones: " << zones.names() << endl
<< exit(FatalError);
}
return zones[zoneID];
break;
}
case topoSetSource::sourceType::POINTZONE_SOURCE:
{
const auto& zones = mesh().pointZones();
const word& zoneTypeName = pointZone::typeName;
const label zoneID = zones.findZoneID(name);
if (zoneID < 0)
{
FatalErrorInFunction
<< "No " << zoneTypeName << " named "
<< name << "found. Has zones: " << zones.names() << endl
<< exit(FatalError);
}
return zones[zoneID];
break;
}
default:
break;
}
IOobject io(topoSet::findIOobject(mesh(), name));
switch (setType)
{
case topoSetSource::sourceType::CELLSET_SOURCE:
{
typedef cellSet classType;
if (classType::typeName != io.headerClassName())
{
FatalErrorInFunction
<< "Error reading " << classType::typeName
<< " <" << name << "> : found "
<< io.headerClassName() << nl
<< exit(FatalError);
}
classType set(io);
return set.sortedToc();
break;
}
case topoSetSource::sourceType::FACESET_SOURCE:
{
typedef faceSet classType;
if (classType::typeName != io.headerClassName())
{
FatalErrorInFunction
<< "Error reading " << classType::typeName
<< " <" << name << "> : found "
<< io.headerClassName() << nl
<< exit(FatalError);
}
classType set(io);
return set.sortedToc();
break;
}
case topoSetSource::sourceType::POINTSET_SOURCE:
{
typedef pointSet classType;
if (classType::typeName != io.headerClassName())
{
FatalErrorInFunction
<< "Error reading " << classType::typeName
<< " <" << name << "> : found "
<< io.headerClassName() << nl
<< exit(FatalError);
}
classType set(io);
return set.sortedToc();
break;
}
default:
{
FatalErrorInFunction
<< "Unexpected sourceType: " << int(setType) << nl
<< " for set <" << name << ">" << nl
<< exit(FatalError);
break;
}
}
return labelList::null();
}
Foam::word Foam::expressions::fvExprDriver::getHeaderClassName
(
const polyMesh& mesh,
const word& name
)
{
IOobject io
(
name,
mesh.time().timeName(),
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
);
io.typeHeaderOk<IOobject>(false);
DebugInfo
<< "Registry: " << mesh.path()
<< " Name: " << name
<< " Time: " << mesh.time().timeName()
<< " Path: " << io.localFilePath(io.headerClassName())
<< " Class: " << io.headerClassName() << endl;
return io.headerClassName();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::Ostream& Foam::expressions::fvExprDriver::writeCommon
(
Ostream& os,
bool debug
) const
{
// Write "variables", even if empty
writeVariableStrings(os, "variables");
if (debug)
{
os.writeEntry("variableValues", variables_);
}
if (!storedVariables_.empty() || !delayedVariables_.empty())
{
const_cast<fvExprDriver&>
(
*this
).updateSpecialVariables(true);
}
if (!storedVariables_.empty())
{
os.writeEntry("storedVariables", storedVariables_);
}
if (!delayedVariables_.empty())
{
List<exprResultDelayed> list(delayedVariables_.size());
auto outIter = list.begin();
forAllConstIters(delayedVariables_, iter)
{
*outIter = *iter;
++outIter;
}
os.writeEntry("delayedVariables", list);
}
if (!globalScopes_.empty())
{
os.writeEntry("globalScopes", globalScopes_);
}
// writeTable(os, "timelines", lines_);
// writeTable(os, "lookuptables", lookup_);
// writeTable(os, "lookuptables2D", lookup2D_);
return os;
}
void Foam::expressions::fvExprDriver::createWriterAndRead(const word& name)
{
if (hasDataToWrite() && !writer_.valid())
{
writer_.set(new exprDriverWriter(name + "_" + this->type(), *this));
}
}
void Foam::expressions::fvExprDriver::tryWrite() const
{
if (writer_.valid() && mesh().time().outputTime())
{
writer_->write();
}
}
// ************************************************************************* //

View File

@ -0,0 +1,105 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
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 "fvExprDriver.H"
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
Foam::autoPtr<Foam::expressions::fvExprDriver>
Foam::expressions::fvExprDriver::New
(
const dictionary& dict
)
{
return fvExprDriver::New
(
dict,
defaultMesh()
);
}
Foam::autoPtr<Foam::expressions::fvExprDriver>
Foam::expressions::fvExprDriver::New
(
const dictionary& dict,
const fvMesh& mesh
)
{
const word driverType(dict.get<word>("valueType"));
auto cstrIter = dictionaryConstructorTablePtr_->cfind(driverType);
if (!cstrIter.found())
{
FatalIOErrorInLookup
(
dict,
"valueType",
driverType,
*dictionaryConstructorTablePtr_
) << exit(FatalIOError);
}
DebugInFunction << "Creating driver of type " << driverType << endl;
resetDefaultMesh(mesh, false); // lazy
return autoPtr<fvExprDriver>(cstrIter()(dict, mesh));
}
Foam::autoPtr<Foam::expressions::fvExprDriver>
Foam::expressions::fvExprDriver::New
(
const word& driverType,
const word& id,
const fvMesh& mesh
)
{
auto cstrIter = idNameConstructorTablePtr_->cfind(driverType);
if (!cstrIter.found())
{
FatalErrorInLookup
(
"valueType",
driverType,
*idNameConstructorTablePtr_
) << exit(FatalError);
}
DebugInFunction << "Creating driver of type " << driverType << endl;
resetDefaultMesh(mesh, false); // lazy
return autoPtr<fvExprDriver>(cstrIter()(id, mesh));
}
// ************************************************************************* //

View File

@ -0,0 +1,627 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
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 "surfaceMesh.H"
#include "fvsPatchField.H"
#include "pointPatchField.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class Type>
bool Foam::expressions::fvExprDriver::isGlobalVariable
(
const word& name,
bool isPointVal,
label expectedSize
) const
{
DebugInfo
<< "Looking for global" << (isPointVal ? " point" : "")
<< " field name:" << name;
const exprResult& result = lookupGlobal(name);
DebugInfo
<< " - found (" << result.valueType() << ' ' << result.isPointValue() << ')';
bool good = (result.isType<Type>() && result.isPointValue(isPointVal));
// Do size checking if requested
if (good && expectedSize >= 0)
{
good = (result.size() == expectedSize);
reduce(good, andOp<bool>());
if (debug && !good)
{
Info<< " size is";
}
}
DebugInfo << (good ? " good" : " bad") << endl;
return good;
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::expressions::fvExprDriver::getVariable
(
const word& name,
label expectedSize,
const bool mandatory
) const
{
tmp<Field<Type>> tresult;
bool isSingleValue = false;
if (hasVariable(name) && variable(name).isType<Type>())
{
isSingleValue = variable(name).isUniform();
tresult = variable(name).cref<Type>().clone();
}
else if (isGlobalVariable<Type>(name, false))
{
const exprResult& var = lookupGlobal(name);
isSingleValue = var.isUniform();
tresult = var.cref<Type>().clone();
}
if (tresult.valid())
{
if
(
expectedSize < 0
|| returnReduce((tresult->size() == expectedSize), andOp<bool>())
)
{
return tresult;
}
if (!isSingleValue)
{
WarningInFunction
<< "Variable " << name
<< " is not a single value and does not fit the size "
<< expectedSize << ". Using average" << endl;
}
return tmp<Field<Type>>::New(expectedSize, gAverage(tresult()));
}
if (mandatory)
{
FatalErrorInFunction
<< "Variable (" << name << ") not found." << nl
<< exit(FatalError);
}
return nullptr;
}
template<class Type>
bool Foam::expressions::fvExprDriver::foundField
(
const word& name
) const
{
if (debug)
{
Info<< "fvExprDriver::foundField. Name: " << name
<< " Type: " << Type::typeName
<< " search memory:" << searchInMemory()
<< " disc:" << searchOnDisc() << endl;
}
// if (std::is_void<Type>::value) ...
if (searchInMemory())
{
const regIOobject* ioptr =
this->mesh().findObject<regIOobject>(name);
if (this->mesh().foundObject<Type>(name))
{
if (debug)
{
Info<< "Found " << name << " in memory" << endl;
}
return true;
}
if (debug)
{
Info<< "No " << name << " of type " << Type::typeName
<< " found in memory";
if (ioptr)
{
Info<< " but of type " << ioptr->headerClassName();
}
Info<< endl;
}
}
if (searchOnDisc() && getTypeOfField(name) == Type::typeName)
{
if (debug)
{
Info<< "Found " << name << " on disc" << endl;
}
return true;
}
else
{
if (debug)
{
Info<< name << " not found" << endl;
}
}
return false;
}
template<class Type>
bool Foam::expressions::fvExprDriver::isField
(
const word& name,
bool isPointVal,
label
) const
{
if (debug)
{
Info<< "fvExprDriver::isField <" << name << '>' << endl;
}
typedef GeometricField<Type, fvPatchField, volMesh> vfieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> sfieldType;
typedef GeometricField<Type, pointPatchField, pointMesh> pfieldType;
return
(
isPointVal
? this->foundField<pfieldType>(name)
:
(
this->foundField<vfieldType>(name)
|| this->foundField<sfieldType>(name)
)
);
}
template<class GeomField, class Mesh>
Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
(
const word& name,
const Mesh& meshRef,
bool mandatory,
bool getOldTime
)
{
typedef typename GeomField::value_type Type;
if (debug)
{
Info<< "fvExprDriver::getOrReadField <" << name
<< "> Type: " << GeomField::typeName << endl;
}
tmp<GeomField> tfield;
if
(
(hasVariable(name) && variable(name).isType<Type>())
|| isGlobalVariable<Type>(name, false)
)
{
if (debug)
{
Info<< "Getting " << name << " from variables" << endl;
}
if (debug)
{
Info<< "Creating field " << name << " of type "
<< GeomField::typeName << nl;
}
tfield.reset
(
GeomField::New(name, meshRef, dimensioned<Type>(Zero))
);
GeomField& fld = tfield.ref();
if (debug)
{
Info<< "New field: " << name << " ownedByRegistry"
<< fld.ownedByRegistry() << endl;
}
Field<Type> vals;
if (hasVariable(name) && variable(name).isType<Type>())
{
vals = variable(name).cref<Type>();
}
else
{
vals = lookupGlobal(name).cref<Type>();
}
if (debug)
{
Pout<< "sizes: " << vals.size() << ' ' << fld.size() << endl;
}
if (returnReduce((vals.size() == fld.size()), andOp<bool>()))
{
fld.primitiveFieldRef() = vals;
}
else
{
Type avg = gAverage(vals);
bool noWarn = false;
if (!noWarn)
{
MinMax<Type> range = gMinMax(vals);
if (range.mag() > SMALL)
{
WarningInFunction
<< "The min/max ranges differ " << range
<< " - using average " << avg << nl;
}
}
fld.primitiveFieldRef() = avg;
}
correctField(fld);
return tfield;
}
const objectRegistry& obr = meshRef.thisDb();
if (searchInMemory() && obr.foundObject<GeomField>(name))
{
if (debug)
{
Info<< "Getting " << name << " from memory" << endl;
}
const GeomField& origFld = obr.lookupObject<GeomField>(name);
// Avoid shadowing the original object
tfield.reset
(
GeomField::New(name + "_exprDriverCopy", origFld)
);
if (getOldTime)
{
if (debug)
{
Info<< "Getting oldTime of " << name << " has "
<< origFld.nOldTimes() << endl;
}
if (!origFld.nOldTimes() && this->prevIterIsOldTime())
{
if (debug)
{
Info<< "No oldTime, using previous iteration" << endl;
}
tfield.ref().oldTime() = origFld.prevIter();
}
}
}
else if (searchOnDisc() && getTypeOfField(name) == GeomField::typeName)
{
if (debug)
{
Info<< "Reading " << name << " from disc" << endl;
}
tfield.reset
(
this->readAndRegister<GeomField>(name, meshRef)
);
// oldTime automatically read
}
if (debug)
{
Info<< "field: valid()=" << tfield.valid() << endl;
}
if (tfield.valid())
{
GeomField& fld = tfield.ref();
if (debug)
{
Info<< "Valid " << name << " found. Removing dimensions" << nl;
}
fld.dimensions().clear();
if (fld.nOldTimes())
{
if (debug)
{
Info<< "Removing dimensions of oldTime of " << name
<< " has " << fld.nOldTimes() << nl;
}
// Switch dimension checking off
const int oldDebug = dimensionSet::debug;
dimensionSet::debug = 0;
// go through ALL old times
GeomField* fp = &(fld);
while (fp->nOldTimes())
{
fp = &(fp->oldTime());
fp->dimensions().clear();
}
// Restore old value of dimension checking
dimensionSet::debug = oldDebug;
}
}
else if (mandatory)
{
FatalErrorInFunction
<< "Could not find field " << name
<< " in memory or on disc" << endl
<< exit(FatalError);
}
return tfield;
}
template<class T>
Foam::autoPtr<T> Foam::expressions::fvExprDriver::getTopoSet
(
const fvMesh& mesh,
const word& name,
SetOrigin& origin
) const
{
// Avoid possible name clashes
const word regName = name + "RegisteredNameFor" + T::typeName;
if (debug)
{
Info<< "Looking for " << T::typeName << " named " << name;
Info<< " or registered as " << regName << " with mesh "
<< "Caching:" << cacheSets()
<< " Found:" << (mesh.foundObject<T>(name))
<< " Found registered:" << mesh.foundObject<T>(regName)
<< endl;
}
origin = SetOrigin::INVALID;
autoPtr<T> setPtr;
if
(
!cacheSets()
||
(
!mesh.thisDb().foundObject<T>(regName)
&& !mesh.thisDb().foundObject<T>(name)
)
)
{
if (debug)
{
Info<< "Constructing new " << T::typeName << ' ' << name << nl;
if (debug > 1)
{
Pout<< mesh.thisDb().names();
}
}
origin = SetOrigin::FILE;
setPtr.reset(new T(mesh, name, IOobject::MUST_READ));
if (cacheSets())
{
if (debug)
{
Info<< "Registering a copy of " << name << " with mesh" << nl;
}
autoPtr<T> toCache(new T(mesh, regName, *setPtr));
toCache->store(toCache);
}
}
else
{
const T* ptr = mesh.thisDb().findObject<T>(name);
if (ptr)
{
if (debug)
{
Info<< "Getting existing " << name << endl;
}
origin = SetOrigin::MEMORY;
setPtr.reset(new T(mesh, name, *ptr));
}
else
{
if (debug)
{
Info<< "Getting existing " << regName << endl;
}
origin = SetOrigin::CACHE;
setPtr.reset(new T(mesh, name, mesh.lookupObject<T>(regName)));
}
}
return setPtr;
}
template<class T>
bool Foam::expressions::fvExprDriver::updateSet
(
autoPtr<T>& setPtr,
const word& name,
SetOrigin origin
) const
{
const label oldSize = setPtr->size();
bool updated = false;
const polyMesh& mesh = dynamic_cast<const polyMesh&>(setPtr->db());
if (debug)
{
Info<< "UpdateSet: " << setPtr->name() << " Id: " << name
<< " Origin: " << int(origin) << endl;
}
switch (origin)
{
case SetOrigin::FILE:
{
IOobject header
(
name,
mesh.time().timeName(),
polyMesh::meshSubDir/"sets",
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
);
if (header.typeHeaderOk<T>())
{
if (debug)
{
Pout<< "Rereading from "
<< header.localFilePath(T::typeName) << endl;
}
setPtr.reset(new T(header));
updated = true;
}
break;
}
case SetOrigin::NEW:
case SetOrigin::MEMORY:
case SetOrigin::CACHE:
{
if (origin == SetOrigin::NEW)
{
WarningInFunction
<< "State NEW shouldn't exist"
<< endl;
}
word sName = name;
const T* ptr = mesh.thisDb().findObject<T>(name);
if (ptr)
{
if (debug)
{
Info<< "Found " << name
<< " and rereading it" << endl;
}
setPtr.reset(new T(mesh, name, *ptr));
}
else
{
FatalErrorInFunction
<< name << " Not found" << endl
<< "In registry: " << mesh.thisDb().names() << endl
<< exit(FatalError);
}
updated = true;
break;
}
case INVALID:
{
FatalErrorInFunction
<< T::typeName << ' ' << name << " is invalid" << endl
<< exit(FatalError);
break;
}
default:
{
if (debug)
{
Info<< "Origin " << int(origin) << " not implemented" << endl;
}
break;
}
}
if (debug)
{
Pout<< name << " old size " << oldSize << " new: "
<< setPtr->size() << endl;
}
return updated;
}
// ************************************************************************* //