From 019fe7deff523143f9854fe12a3a190766838f7e Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Tue, 3 Dec 2019 12:34:33 +0100 Subject: [PATCH] ENH: base fvMesh driver for expressions --- src/finiteVolume/Make/files | 9 + .../expressions/base/exprDriverWriter.C | 100 +++ .../expressions/base/exprDriverWriter.H | 109 +++ .../expressions/base/fvExprDriver.C | 765 ++++++++++++++++++ .../expressions/base/fvExprDriver.H | 646 +++++++++++++++ .../expressions/base/fvExprDriverFields.C | 49 ++ .../expressions/base/fvExprDriverI.H | 179 ++++ .../expressions/base/fvExprDriverIO.C | 280 +++++++ .../expressions/base/fvExprDriverNew.C | 105 +++ .../expressions/base/fvExprDriverTemplates.C | 627 ++++++++++++++ 10 files changed, 2869 insertions(+) create mode 100644 src/finiteVolume/expressions/base/exprDriverWriter.C create mode 100644 src/finiteVolume/expressions/base/exprDriverWriter.H create mode 100644 src/finiteVolume/expressions/base/fvExprDriver.C create mode 100644 src/finiteVolume/expressions/base/fvExprDriver.H create mode 100644 src/finiteVolume/expressions/base/fvExprDriverFields.C create mode 100644 src/finiteVolume/expressions/base/fvExprDriverI.H create mode 100644 src/finiteVolume/expressions/base/fvExprDriverIO.C create mode 100644 src/finiteVolume/expressions/base/fvExprDriverNew.C create mode 100644 src/finiteVolume/expressions/base/fvExprDriverTemplates.C diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files index 18d5b7c57b..20497d102d 100644 --- a/src/finiteVolume/Make/files +++ b/src/finiteVolume/Make/files @@ -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 diff --git a/src/finiteVolume/expressions/base/exprDriverWriter.C b/src/finiteVolume/expressions/base/exprDriverWriter.C new file mode 100644 index 0000000000..eb2aa82b82 --- /dev/null +++ b/src/finiteVolume/expressions/base/exprDriverWriter.C @@ -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 + 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 . + +\*---------------------------------------------------------------------------*/ + +#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(); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/exprDriverWriter.H b/src/finiteVolume/expressions/base/exprDriverWriter.H new file mode 100644 index 0000000000..10fe296e1f --- /dev/null +++ b/src/finiteVolume/expressions/base/exprDriverWriter.H @@ -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 + 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 . + +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 + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriver.C b/src/finiteVolume/expressions/base/fvExprDriver.C new file mode 100644 index 0000000000..2dbd08757b --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriver.C @@ -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 + 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 . + +\*---------------------------------------------------------------------------*/ + +#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(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 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(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(regionName); + + if (!pRegion) + { + FatalErrorInFunction + << "Cannot resolve mesh region: " << regionName << nl + << exit(FatalError); + } + } + + DebugInfo + << "Call other with (" + << driverType << ", " << identName << ", " << regionName << ")\n"; + + autoPtr 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(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(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(*this); + + (void)driver.update(); + + if (storedVariables_.size()) + { + driver.updateSpecialVariables(true); + + dict.add("storedVariables", storedVariables_); + } +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriver.H b/src/finiteVolume/expressions/base/fvExprDriver.H new file mode 100644 index 0000000000..7a941440fc --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriver.H @@ -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 . + +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 globalScopes_; + + //- The (delayed) variables table + HashTable delayedVariables_; + + //- Stored expressions. Read from dictionary and updated as required + List 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 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 + static inline word defaultBoundaryType(const T&) + { + return "calculated"; + } + + //- Default boundary type for volume fields is zeroGradient + template + static inline word defaultBoundaryType + ( + const GeometricField& + ) + { + return "zeroGradient"; + } + + + //- Apply correctBoundaryConditions (volume fields only) + template + static inline void correctField(T&) {} + + template + static inline void correctField + ( + GeometricField& 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 + 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 + bool isField + ( + const word& name, + bool isPointVal = false, + label expectSize = -1 //!< ignored + ) const; + + + //- Retrieve field from memory or disk + template + inline tmp getOrReadField + ( + const word& name, + bool mandatory = true, + bool getOldTime = false + ); + + //- Retrieve point field from memory or disk + template + inline tmp getOrReadPointField + ( + const word& name, + bool mandatory = true, + bool getOldTime = false + ); + + //- Retrieve field from memory or disk (implementation) + template + tmp getOrReadFieldImpl + ( + const word& name, + const MeshRef& meshRef, + bool mandatory = true, + bool getOldTime = false + ); + + //- Helper function for getOrReadField + template + inline tmp 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 + autoPtr getTopoSet + ( + const fvMesh& mesh, + const word& setName, + SetOrigin& origin + ) const; + + //- Update topoSet + template + inline bool updateSet + ( + autoPtr& 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 New + ( + const dictionary& dict, + const fvMesh& mesh + ); + + //- Return a reference to the selected value driver + static autoPtr New + ( + const dictionary& dict + ); + + //- Return a reference to the selected value driver + static autoPtr New + ( + const word& type, + const word& id, + const fvMesh& mesh + ); + + //- Clone + virtual autoPtr 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 + 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 + tmp> 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 + 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 + 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 + /// getPlugin(const word& name) = 0; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace expressions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "fvExprDriverI.H" + +#ifdef NoRepository + #include "fvExprDriverTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriverFields.C b/src/finiteVolume/expressions/base/fvExprDriverFields.C new file mode 100644 index 0000000000..d2610385a8 --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriverFields.C @@ -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 + 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 . + +\*---------------------------------------------------------------------------*/ + +#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 + ); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriverI.H b/src/finiteVolume/expressions/base/fvExprDriverI.H new file mode 100644 index 0000000000..004871bc5d --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriverI.H @@ -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 + 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 . + +\*---------------------------------------------------------------------------*/ + +#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 +inline bool Foam::expressions::fvExprDriver::isVariable +( + const word& name, + bool isPointVal, + label expectedSize +) const +{ + return + ( + this->isLocalVariable(name, isPointVal, expectedSize) + || this->isGlobalVariable(name, isPointVal, expectedSize) + ); +} + + +template +inline bool Foam::expressions::fvExprDriver::isVariableOrField +( + const word& name, + bool isPointVal, + label expectedSize +) +const +{ + return + ( + this->isVariable(name, isPointVal, expectedSize) + || this->isField(name, isPointVal) + ); +} + + +template +inline Foam::tmp +Foam::expressions::fvExprDriver::getOrReadField +( + const word& name, + bool mandatory, + bool getOldTime +) +{ + return this->getOrReadFieldImpl + ( + name, + this->mesh(), + mandatory, + getOldTime + ); +} + + +template +inline Foam::tmp +Foam::expressions::fvExprDriver::getOrReadPointField +( + const word& name, + bool mandatory, + bool getOldTime +) +{ + return this->getOrReadFieldImpl + ( + name, + pointMesh::New(this->mesh()), + mandatory, + getOldTime + ); +} + + +template +inline Foam::tmp +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(regIOobject::store(ptr)); + } + + return tmp(ptr); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriverIO.C b/src/finiteVolume/expressions/base/fvExprDriverIO.C new file mode 100644 index 0000000000..3a25df5bdb --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriverIO.C @@ -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 + 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 . + +\*---------------------------------------------------------------------------*/ + +#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(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 + ( + *this + ).updateSpecialVariables(true); + } + + if (!storedVariables_.empty()) + { + os.writeEntry("storedVariables", storedVariables_); + } + + if (!delayedVariables_.empty()) + { + List 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(); + } +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriverNew.C b/src/finiteVolume/expressions/base/fvExprDriverNew.C new file mode 100644 index 0000000000..f2abd79e7b --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriverNew.C @@ -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 + 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 . + +\*---------------------------------------------------------------------------*/ + +#include "fvExprDriver.H" + +// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * // + +Foam::autoPtr +Foam::expressions::fvExprDriver::New +( + const dictionary& dict +) +{ + return fvExprDriver::New + ( + dict, + defaultMesh() + ); +} + + +Foam::autoPtr +Foam::expressions::fvExprDriver::New +( + const dictionary& dict, + const fvMesh& mesh +) +{ + const word driverType(dict.get("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(cstrIter()(dict, mesh)); +} + + +Foam::autoPtr +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(cstrIter()(id, mesh)); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriverTemplates.C b/src/finiteVolume/expressions/base/fvExprDriverTemplates.C new file mode 100644 index 0000000000..498c398bfc --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriverTemplates.C @@ -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 + 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 . + +\*---------------------------------------------------------------------------*/ + +#include "surfaceMesh.H" +#include "fvsPatchField.H" +#include "pointPatchField.H" + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +template +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() && result.isPointValue(isPointVal)); + + // Do size checking if requested + if (good && expectedSize >= 0) + { + good = (result.size() == expectedSize); + reduce(good, andOp()); + + if (debug && !good) + { + Info<< " size is"; + } + } + + DebugInfo << (good ? " good" : " bad") << endl; + + return good; +} + + +template +Foam::tmp> +Foam::expressions::fvExprDriver::getVariable +( + const word& name, + label expectedSize, + const bool mandatory +) const +{ + tmp> tresult; + + bool isSingleValue = false; + + if (hasVariable(name) && variable(name).isType()) + { + isSingleValue = variable(name).isUniform(); + tresult = variable(name).cref().clone(); + } + else if (isGlobalVariable(name, false)) + { + const exprResult& var = lookupGlobal(name); + + isSingleValue = var.isUniform(); + + tresult = var.cref().clone(); + } + + if (tresult.valid()) + { + if + ( + expectedSize < 0 + || returnReduce((tresult->size() == expectedSize), andOp()) + ) + { + return tresult; + } + + if (!isSingleValue) + { + WarningInFunction + << "Variable " << name + << " is not a single value and does not fit the size " + << expectedSize << ". Using average" << endl; + } + + return tmp>::New(expectedSize, gAverage(tresult())); + } + + if (mandatory) + { + FatalErrorInFunction + << "Variable (" << name << ") not found." << nl + << exit(FatalError); + } + + return nullptr; +} + + +template +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::value) ... + + if (searchInMemory()) + { + const regIOobject* ioptr = + this->mesh().findObject(name); + + if (this->mesh().foundObject(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 +bool Foam::expressions::fvExprDriver::isField +( + const word& name, + bool isPointVal, + label +) const +{ + if (debug) + { + Info<< "fvExprDriver::isField <" << name << '>' << endl; + } + + typedef GeometricField vfieldType; + typedef GeometricField sfieldType; + typedef GeometricField pfieldType; + + return + ( + isPointVal + ? this->foundField(name) + : + ( + this->foundField(name) + || this->foundField(name) + ) + ); +} + + +template +Foam::tmp 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 tfield; + + if + ( + (hasVariable(name) && variable(name).isType()) + || isGlobalVariable(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(Zero)) + ); + + GeomField& fld = tfield.ref(); + + if (debug) + { + Info<< "New field: " << name << " ownedByRegistry" + << fld.ownedByRegistry() << endl; + } + + Field vals; + + if (hasVariable(name) && variable(name).isType()) + { + vals = variable(name).cref(); + } + else + { + vals = lookupGlobal(name).cref(); + } + + if (debug) + { + Pout<< "sizes: " << vals.size() << ' ' << fld.size() << endl; + } + + if (returnReduce((vals.size() == fld.size()), andOp())) + { + fld.primitiveFieldRef() = vals; + } + else + { + Type avg = gAverage(vals); + + bool noWarn = false; + + if (!noWarn) + { + MinMax 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(name)) + { + if (debug) + { + Info<< "Getting " << name << " from memory" << endl; + } + + const GeomField& origFld = obr.lookupObject(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(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 +Foam::autoPtr 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(name)) + << " Found registered:" << mesh.foundObject(regName) + << endl; + } + + + origin = SetOrigin::INVALID; + autoPtr setPtr; + + if + ( + !cacheSets() + || + ( + !mesh.thisDb().foundObject(regName) + && !mesh.thisDb().foundObject(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 toCache(new T(mesh, regName, *setPtr)); + toCache->store(toCache); + } + } + else + { + const T* ptr = mesh.thisDb().findObject(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(regName))); + } + } + + + return setPtr; +} + + +template +bool Foam::expressions::fvExprDriver::updateSet +( + autoPtr& setPtr, + const word& name, + SetOrigin origin +) const +{ + const label oldSize = setPtr->size(); + + bool updated = false; + const polyMesh& mesh = dynamic_cast(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()) + { + 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(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; +} + + +// ************************************************************************* //