Skip to content
Snippets Groups Projects
Commit cd1350a8 authored by Mark OLESEN's avatar Mark OLESEN
Browse files

ENH: support preloading fields for setExpr* utilities (#2014)

- can use either command-line option "-load-fields" or dictionary
  entry "readFields" to specify field names to be preloaded.

  Essentially the same functionality as with a readFields function
  object but with a lot less typing.

- tutorial examples provided by Ryan Danks <ryan.danks@rwdi.com>
  illustrate using setExpr* utilities to calculate a quantity
  as a post-processing step.
parent 6ccc587b
Branches
Tags
No related merge requests found
Showing with 538 additions and 24 deletions
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::readFieldsHandler
Description
A simple field-loader, as per the readFields function object
\*---------------------------------------------------------------------------*/
#ifndef readFieldsHander_H
#define readFieldsHander_H
#include "fvMesh.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "messageStream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class readFieldsHandler Declaration
\*---------------------------------------------------------------------------*/
class readFieldsHandler
{
// Private Data
//- Mesh reference
fvMesh& mesh_;
//- Output logging (verbosity)
bool log;
// Private Member Functions
//- Attempt load from io, store on database if successful
template<class FieldType>
bool loadAndStore(const IOobject& io)
{
if (FieldType::typeName == io.headerClassName())
{
// Store field on mesh database
Log << " Reading " << io.name()
<< " (" << FieldType::typeName << ')' << endl;
mesh_.objectRegistry::store(new FieldType(io, mesh_));
return true;
}
return false;
}
//- Forward to loadAndStore for supported types
template<class Type>
bool loadField(const IOobject& io)
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef typename VolFieldType::Internal IntVolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh>
SurfaceFieldType;
return
(
loadAndStore<VolFieldType>(io)
|| loadAndStore<IntVolFieldType>(io)
|| loadAndStore<SurfaceFieldType>(io)
);
}
//- Load all fields
label loadFields(const UList<word>& fieldSet_)
{
label nLoaded = 0;
for (const word& fieldName : fieldSet_)
{
// Already loaded?
const auto* ptr = mesh_.cfindObject<regIOobject>(fieldName);
if (ptr)
{
++nLoaded;
DebugInfo
<< "readFields : "
<< ptr->name() << " (" << ptr->type()
<< ") already in database" << endl;
continue;
}
// Load field as necessary
IOobject io
(
fieldName,
mesh_.time().timeName(),
mesh_,
IOobject::MUST_READ,
IOobject::NO_WRITE
);
const bool ok =
(
io.typeHeaderOk<regIOobject>(false) // Preload header info
&& !io.headerClassName().empty() // Extra safety
&&
(
loadField<scalar>(io)
|| loadField<vector>(io)
|| loadField<sphericalTensor>(io)
|| loadField<symmTensor>(io)
|| loadField<tensor>(io)
)
);
if (ok)
{
++nLoaded;
}
else
{
DebugInfo
<< "readFields : failed to load " << fieldName
<< endl;
}
}
return nLoaded;
}
public:
static const bool debug = false;
// Constructors
//- Construct
explicit readFieldsHandler(fvMesh& mesh, bool verbose=true)
:
mesh_(mesh),
log(verbose)
{}
// Member Functions
bool execute(const UList<word>& fieldNames)
{
loadFields(fieldNames);
return true;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
#endif
// ************************************************************************* //
......@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -44,10 +44,10 @@ Note
#include "pointMesh.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "surfaceFields.H"
#include "pointFields.H"
#include "patchExprDriver.H"
#include "timeSelector.H"
#include "readFields.H"
using namespace Foam;
......@@ -67,20 +67,25 @@ int main(int argc, char *argv[])
"file",
"Alternative dictionary for setExprBoundaryFieldsDict"
);
argList::addBoolOption
(
"cache-fields",
"Cache fields between calls",
true // Advanced
);
argList::addOption
(
"load-fields",
"wordList",
"Specify field or fields to preload. Eg, 'T' or '(p T U)'",
true // Advanced
);
argList::addBoolOption
(
"backup",
"Preserve sub-entry as .backup",
true // Advanced
);
argList::addBoolOption
(
"dry-run",
......@@ -128,12 +133,29 @@ int main(int argc, char *argv[])
mesh.readUpdate();
// preload fields specified on command-line
if (timei == 0)
{
wordList preloadFields;
args.readListIfPresent("load-fields", preloadFields);
readFieldsHandler(mesh).execute(preloadFields);
}
// preload fields specified in dictionary
{
wordList preloadFields;
setExprDict.readIfPresent("readFields", preloadFields);
readFieldsHandler(mesh).execute(preloadFields);
}
for (const entry& dEntry : setExprDict)
{
if (!dEntry.isDict())
{
Info<< "Ignoring non-dictionary entry "
<< dEntry.keyword() << nl;
if (dEntry.keyword() != "readFields")
{
Info<< "Ignoring non-dictionary entry "
<< dEntry.keyword() << nl;
}
continue;
}
......@@ -193,8 +215,8 @@ int main(int argc, char *argv[])
for (const dictionary& currDict : exprDicts)
{
const word targetName = currDict.get<word>("target");
const word patchName = currDict.get<word>("patch");
const word patchName(currDict.get<word>("patch"));
const word targetName(currDict.get<word>("target"));
dictionary& patchDict = boundaryFieldDict.subDict(patchName);
......
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::readFieldsHandler
Description
A simple field-loader, as per the readFields function object
\*---------------------------------------------------------------------------*/
#ifndef readFieldsHander_H
#define readFieldsHander_H
#include "fvMesh.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "messageStream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class readFieldsHandler Declaration
\*---------------------------------------------------------------------------*/
class readFieldsHandler
{
// Private Data
//- Mesh reference
fvMesh& mesh_;
//- Output logging (verbosity)
bool log;
// Private Member Functions
//- Attempt load from io, store on database if successful
template<class FieldType>
bool loadAndStore(const IOobject& io)
{
if (FieldType::typeName == io.headerClassName())
{
// Store field on mesh database
Log << " Reading " << io.name()
<< " (" << FieldType::typeName << ')' << endl;
mesh_.objectRegistry::store(new FieldType(io, mesh_));
return true;
}
return false;
}
//- Forward to loadAndStore for supported types
template<class Type>
bool loadField(const IOobject& io)
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef typename VolFieldType::Internal IntVolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh>
SurfaceFieldType;
return
(
loadAndStore<VolFieldType>(io)
|| loadAndStore<IntVolFieldType>(io)
|| loadAndStore<SurfaceFieldType>(io)
);
}
//- Load all fields
label loadFields(const UList<word>& fieldSet_)
{
label nLoaded = 0;
for (const word& fieldName : fieldSet_)
{
// Already loaded?
const auto* ptr = mesh_.cfindObject<regIOobject>(fieldName);
if (ptr)
{
++nLoaded;
DebugInfo
<< "readFields : "
<< ptr->name() << " (" << ptr->type()
<< ") already in database" << endl;
continue;
}
// Load field as necessary
IOobject io
(
fieldName,
mesh_.time().timeName(),
mesh_,
IOobject::MUST_READ,
IOobject::NO_WRITE
);
const bool ok =
(
io.typeHeaderOk<regIOobject>(false) // Preload header info
&& !io.headerClassName().empty() // Extra safety
&&
(
loadField<scalar>(io)
|| loadField<vector>(io)
|| loadField<sphericalTensor>(io)
|| loadField<symmTensor>(io)
|| loadField<tensor>(io)
)
);
if (ok)
{
++nLoaded;
}
else
{
DebugInfo
<< "readFields : failed to load " << fieldName
<< endl;
}
}
return nLoaded;
}
public:
static const bool debug = false;
// Constructors
//- Construct
explicit readFieldsHandler(fvMesh& mesh, bool verbose=true)
:
mesh_(mesh),
log(verbose)
{}
// Member Functions
bool execute(const UList<word>& fieldNames)
{
loadFields(fieldNames);
return true;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
#endif
// ************************************************************************* //
......@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -44,12 +44,11 @@ Note
#include "pointMesh.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "surfaceFields.H"
#include "pointFields.H"
#include "exprOps.H"
#include "volumeExprDriver.H"
#include "timeSelector.H"
#include "dlLibraryTable.H"
#include "readFields.H"
using namespace Foam;
......@@ -175,7 +174,7 @@ void setField
if (cond.empty())
{
// No condition
// No condition - set all
output = result;
setCells = output.size();
......@@ -288,12 +287,16 @@ void evaluate
<< "Expression:" << nl
<< ">>>>" << nl
<< expression.c_str() << nl
<< "<<<<" << nl
<< "Condition:" << nl
<< ">>>>" << nl
<< condition.c_str() << nl
<< "<<<<" << nl;
if (condition.size() && condition != "true")
{
Info<< "Condition:" << nl
<< ">>>>" << nl
<< condition.c_str() << nl
<< "<<<<" << nl;
}
if (ctrl.keepPatches)
{
Info<< "Keeping patches unaltered" << endl;
......@@ -542,32 +545,38 @@ int main(int argc, char *argv[])
"file",
"Alternative dictionary for setExprFieldsDict"
);
argList::addBoolOption
(
"dry-run",
"Evaluate but do not write"
);
argList::addBoolOption
(
"verbose",
"Additional verbosity",
true // Advanced option
);
argList::addOption
(
"load-fields",
"wordList",
"Specify field or fields to preload. Eg, 'T' or '(p T U)'",
true // Advanced option
);
argList::addOption
(
"field",
"name",
"The field to overwrite command-line operation)",
"The field to overwrite"
" (command-line operation)",
true // Advanced option
);
argList::addOption
(
"expression",
"expr",
"The expression to evaluate (command-line operation)",
"The expression to evaluate"
" (command-line operation)",
true // Advanced option
);
argList::addOption
......@@ -582,7 +591,7 @@ int main(int argc, char *argv[])
(
"dimension",
"dims",
"The dimensions to apply for created fields"
"The dimensions for created fields"
" (command-line operation)",
true // Advanced option
);
......@@ -601,7 +610,8 @@ int main(int argc, char *argv[])
argList::addBoolOption
(
"create",
"Create a new field (command-line operation)",
"Create a new field"
" (command-line operation)",
true // Advanced option
);
argList::addBoolOption
......@@ -714,7 +724,6 @@ int main(int argc, char *argv[])
exprDictPtr.reset(new IOdictionary(dictIO));
}
forAll(times, timei)
{
runTime.setTime(times[timei], timei);
......@@ -723,6 +732,14 @@ int main(int argc, char *argv[])
mesh.readUpdate();
// preload fields specified on command-line
if (timei == 0)
{
wordList preloadFields;
args.readListIfPresent("load-fields", preloadFieldNames);
readFieldsHandler(mesh).execute(preloadFields);
}
if (args.found("dummy-phi") && !dummyPhi)
{
Info<< "Adding a dummy phi" << endl;
......@@ -806,6 +823,13 @@ int main(int argc, char *argv[])
{
const dictionary& exprDict = *exprDictPtr;
// preload fields specified in dictionary
{
wordList preloadFields;
exprDict.readIfPresent("readFields", preloadFields);
readFieldsHandler(mesh).execute(preloadFields);
}
// Read set construct info from dictionary
PtrList<entry> actions(exprDict.lookup("expressions"));
......
......@@ -14,6 +14,9 @@ FoamFile
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Preload any required fields (optional)
readFields ( U );
pattern
{
field T;
......
......@@ -14,6 +14,9 @@ FoamFile
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Preload any required fields (optional)
readFields ( U );
expressions
(
T
......
......@@ -28,4 +28,8 @@ runApplication reconstructParMesh -constant
runApplication reconstructPar
runApplication setExprFields -latestTime ## -load-fields U
runApplication setExprBoundaryFields -latestTime ## -load-fields '(U)'
#------------------------------------------------------------------------------
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2012 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object setExprBoundaryFieldsDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Preload any required fields (optional)
readFields ( U );
updateBCs
{
field windPowerDensity;
_value1
{
target value;
variables ( "rho=1.2" );
expression #{ 0.5*rho*cbrt(mag(U)) #};
}
expressions
(
{ $_value1; patch inlet; }
{ $_value1; patch outlet; }
{ $_value1; patch sides; }
{ $_value1; patch top; }
);
}
// ************************************************************************* //
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2012 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object setExprFieldsDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Preload any required fields (optional)
readFields ( U );
_value1
{
variables ( "rho=1.2" );
expression #{ 0.5*rho*cbrt(mag(U)) #};
}
expressions
(
windPowerDensity
{
field windPowerDensity;
create yes;
$_value1;
}
);
// ************************************************************************* //
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment