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

ENH: runTime calculation of zeroGradient volume fields (issue #235)

Extrapolate internal field to walls for post-processing.
Uses as new syntax for handling the naming of multiple fields.

The input fields are selected via a wordReList.
For example,

    fields      (U "(T|k|epsilon|omega)");

The names of the resulting output fields use placeholder tokens for
flexibility. For example,

    result      zeroGradient(@@);

The '@@' placeholder is replaced by the name of the input field.
Eg,
    fields      (U T);
    result      zeroGradient(@@);
->  zeroGradient(U), zeroGradient(T)

Or,
    fields      (U T);
    result      @@nearWall;
->  UnearWall, TnearWall

NOTE:
    The function object will skip over fields that only have
    processor, empty, zeroGradient patches. The operation does not
    make much sense for these, and it avoids inadvertently
    re-processing fields twice.
parent 3aa54d11
Branches
Tags
No related merge requests found
......@@ -54,6 +54,9 @@ wallShearStress/wallShearStressFunctionObject.C
yPlus/yPlus.C
yPlus/yPlusFunctionObject.C
zeroGradient/zeroGradient.C
zeroGradient/zeroGradientFunctionObject.C
setTimeStep/setTimeStepFunctionObject.C
reactionSensitivityAnalysis/reactionsSensitivityAnalysisFunctionObject.C
......
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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/>.
Typedef
Foam::IOzeroGradient
Description
Instance of the generic IOOutputFilter for zeroGradient.
\*---------------------------------------------------------------------------*/
#ifndef IOzeroGradient_H
#define IOzeroGradient_H
#include "zeroGradient.H"
#include "IOOutputFilter.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
typedef IOOutputFilter<zeroGradient> IOzeroGradient;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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 "zeroGradient.H"
#include "volFields.H"
#include "dictionary.H"
#include "symmetryFvPatchField.H"
#include "symmetryPlaneFvPatchField.H"
#include "zeroGradientFvPatchField.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(zeroGradient, 0);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::zeroGradient::checkFormatName(const word& str)
{
if (str.find("@@") == string::npos)
{
WarningInFunction
<< "Bad result naming "
<< "(no '@@' token found), deactivating."
<< nl << endl;
return false;
}
else if (str == "@@")
{
WarningInFunction
<< "Bad result naming "
<< "(only a '@@' token found), deactivating."
<< nl
<< endl;
return false;
}
else
{
return true;
}
}
void Foam::zeroGradient::uniqWords(wordReList& lst)
{
boolList retain(lst.size());
wordHashSet uniq;
forAll(lst, i)
{
const wordRe& select = lst[i];
retain[i] =
(
select.isPattern()
|| uniq.insert(static_cast<const word&>(select))
);
}
inplaceSubset(retain, lst);
}
template<class Type>
bool Foam::zeroGradient::accept
(
const GeometricField<Type, fvPatchField, volMesh>& input
)
{
const typename GeometricField<Type, fvPatchField, volMesh>
::GeometricBoundaryField& patches = input.boundaryField();
forAll(patches, patchi)
{
const fvPatchField<Type>& p = patches[patchi];
const polyPatch& pp = p.patch().patch();
bool ignore =
(
isA<emptyPolyPatch>(pp)
|| isA<processorPolyPatch>(pp)
|| isA<zeroGradientFvPatchField<Type>>(p)
|| isA<symmetryFvPatchField<Type>>(p)
|| isA<symmetryPlaneFvPatchField<Type>>(p)
);
if (!ignore)
{
return true;
}
}
return false;
}
template<class Type>
int Foam::zeroGradient::apply
(
const fvMesh& mesh,
const word& inputName,
int& state
)
{
typedef GeometricField<Type, fvPatchField, volMesh> vfType;
// state: return 0 (not-processed), -1 (skip), +1 ok
// already done, or not available
if (state || !mesh.foundObject<vfType>(inputName))
{
return state;
}
const vfType& input = mesh.lookupObject<vfType>(inputName);
if (!returnReduce(accept(input), orOp<bool>()))
{
state = -1;
return state;
}
word outputName(resultName_);
outputName.replace("@@", inputName);
// also save the field-type, just in case we want it later
results_.set(outputName, vfType::typeName);
if (!mesh.foundObject<vfType>(outputName))
{
mesh.objectRegistry::store
(
new vfType
(
IOobject
(
outputName,
mesh.time().timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh,
dimensioned<Type>("0", input.dimensions(), Zero),
zeroGradientFvPatchField<Type>::typeName
)
);
}
vfType& output = const_cast<vfType&>(mesh.lookupObject<vfType>(outputName));
output = input;
output.correctBoundaryConditions();
state = +1;
return state;
}
int Foam::zeroGradient::process(const fvMesh& mesh, const word& fieldName)
{
int state = 0;
apply<scalar>(mesh, fieldName, state);
apply<vector>(mesh, fieldName, state);
apply<sphericalTensor>(mesh, fieldName, state);
apply<symmTensor>(mesh, fieldName, state);
apply<tensor>(mesh, fieldName, state);
return state;
}
void Foam::zeroGradient::process(const fvMesh& mesh)
{
results_.clear();
wordHashSet candidates = subsetStrings(selectFields_, mesh.names());
DynamicList<word> missing(selectFields_.size());
DynamicList<word> ignored(selectFields_.size());
// check exact matches first
forAll(selectFields_, i)
{
const wordRe& select = selectFields_[i];
if (!select.isPattern())
{
const word& fieldName = static_cast<const word&>(select);
if (!candidates.erase(fieldName))
{
missing.append(fieldName);
}
else if (process(mesh, fieldName) < 1)
{
ignored.append(fieldName);
}
}
}
forAllConstIter(wordHashSet, candidates, iter)
{
process(mesh, iter.key());
}
if (missing.size())
{
WarningInFunction
<< "Missing field " << missing << endl;
}
if (ignored.size())
{
WarningInFunction
<< "Unprocessed field " << ignored << endl;
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::zeroGradient::zeroGradient
(
const word& name,
const objectRegistry& obr,
const dictionary& dict,
const bool loadFromFiles
)
:
name_(name),
obr_(obr),
active_(true),
selectFields_(),
resultName_(string::null),
results_(),
log_(false)
{
// Check if the available mesh is an fvMesh, otherwise deactivate
if (!isA<fvMesh>(obr_))
{
active_ = false;
WarningInFunction
<< "No fvMesh available, deactivating." << nl
<< endl;
}
read(dict);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::zeroGradient::~zeroGradient()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::zeroGradient::read(const dictionary& dict)
{
if (active_)
{
log_ = dict.lookupOrDefault<Switch>("log", false);
dict.lookup("fields") >> selectFields_;
uniqWords(selectFields_);
resultName_ = dict.lookupOrDefault<word>
(
"result",
type() + "(@@)"
);
active_ = checkFormatName(resultName_);
}
}
void Foam::zeroGradient::execute()
{
results_.clear();
if (active_)
{
process(refCast<const fvMesh>(obr_));
}
}
void Foam::zeroGradient::write()
{
if (active_)
{
// consistent output order
const wordList outputList = results_.sortedToc();
forAll(outputList, i)
{
const word& fieldName = outputList[i];
if (obr_.foundObject<regIOobject>(fieldName))
{
const regIOobject& io =
obr_.lookupObject<regIOobject>(fieldName);
if (log_)
{
Info<< type() << " " << name_
<< " output: writing field " << fieldName << endl;
}
io.write();
}
}
}
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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::zeroGradient
Group
grpFVFunctionObjects
Description
This function object creates a volume field with zero-gradient
boundary conditions from another volume field.
The result can be used, for example, to post-process near-wall
field values.
Example of function object specification:
\verbatim
zeroGrad
{
type zeroGradient;
functionObjectLibs ("libutilityFunctionObjects.so");
fields (U "(T|k|epsilon|omega)");
result @@nearWall;
...
}
\endverbatim
\heading Function object usage
\table
Property | Description | Required | Default value
type | type name: zeroGradient | yes |
fields | Name of fields to process | yes |
result | Name of results | no | zeroGradient(@@)
log | Log to standard output | no | no
\endtable
A list of fields can contain exact names or regular expressions.
The token '\@\@' in the result name is replaced by the name of the source
field.
The function object will skip over fields that would not benefit
- ie, only processor, empty, zeroGradient, symmetry patches.
This check should also prevent processing fields multiple times.
SourceFiles
zeroGradient.C
zeroGradientFunctionObject.C
IOzeroGradient.H
\*---------------------------------------------------------------------------*/
#ifndef zeroGradient_H
#define zeroGradient_H
#include "volFieldsFwd.H"
#include "OFstream.H"
#include "wordReList.H"
#include "Switch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class objectRegistry;
class dictionary;
class fvMesh;
class polyMesh;
class mapPolyMesh;
/*---------------------------------------------------------------------------*\
Class zeroGradient Declaration
\*---------------------------------------------------------------------------*/
class zeroGradient
{
// Private data
//- Name of this zeroGradient object
word name_;
//- Reference to the database
const objectRegistry& obr_;
//- On/off switch
bool active_;
//- Name of fields to process
wordReList selectFields_;
//- Formatting for the result fields.
word resultName_;
//- Hashed names of result fields, and their type
HashTable<word> results_;
//- Switch to send output to Info as well as to file
Switch log_;
// Private Member Functions
//- Check that the word contains the appropriate substitution token(s).
static bool checkFormatName(const word&);
//- Eliminate duplicate 'word' entries
static void uniqWords(wordReList&);
//- Accept unless field only has empty/zero-gradient/processor patches
template<class Type>
static bool accept(const GeometricField<Type, fvPatchField, volMesh>&);
//- Apply for the volume field type
template<class Type>
int apply(const fvMesh& mesh, const word& inputName, int& state);
//- Process by trying to apply for various volume field types.
int process(const fvMesh& mesh, const word& inputName);
//- Calculate the zeroGradient fields
void process(const fvMesh& mesh);
//- Disallow default bitwise copy construct
zeroGradient(const zeroGradient&) = delete;
//- Disallow default bitwise assignment
void operator=(const zeroGradient&) = delete;
public:
//- Runtime type information
TypeName("zeroGradient");
// Constructors
//- Construct for given objectRegistry and dictionary.
// Allow the possibility to load fields from files
zeroGradient
(
const word& name,
const objectRegistry&,
const dictionary&,
const bool loadFromFiles = false
);
//- Destructor
virtual ~zeroGradient();
// Member Functions
//- Return name of the zeroGradient function object
virtual const word& name() const
{
return name_;
}
//- Read the zeroGradient specification
virtual void read(const dictionary&);
//- Calculate the zeroGradient fields
virtual void execute();
//- Execute at the final time-loop, currently does nothing
virtual void end()
{}
//- Called when time was set at the end of the Time::operator++
virtual void timeSet()
{}
//- Write the zeroGradient fields
virtual void write();
//- Update for changes of mesh
virtual void updateMesh(const mapPolyMesh&)
{}
//- Update for changes of mesh
virtual void movePoints(const polyMesh&)
{}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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 "zeroGradientFunctionObject.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineNamedTemplateTypeNameAndDebug(zeroGradientFunctionObject, 0);
addToRunTimeSelectionTable
(
functionObject,
zeroGradientFunctionObject,
dictionary
);
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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/>.
Typedef
Foam::zeroGradientFunctionObject
Description
FunctionObject wrapper around zeroGradient to allow it to be created
via the functions entry within controlDict.
SourceFiles
zeroGradientFunctionObject.C
\*---------------------------------------------------------------------------*/
#ifndef zeroGradientFunctionObject_H
#define zeroGradientFunctionObject_H
#include "zeroGradient.H"
#include "OutputFilterFunctionObject.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
typedef OutputFilterFunctionObject<zeroGradient>
zeroGradientFunctionObject;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment