functionObjects::fluidMaxDeltaT: New functionObject to set the maximum Courant number and time-step

at Function1s of time.

Underlying this new functionObject is a generalisation of the handling of the
maximum time-step in the modular solvers to allow complex user-specification of
the maximum time-step used in a simulation, not just the time-dependency
provided by fluidMaxDeltaT but functions of anything in the simulation by
creating a specialised functionObject in which the maxDeltaT function is
defined.

The chemical and combustion time-scale functionObjects adjustTimeStepToChemistry
and adjustTimeStepToCombustion have been updated and simplified using the above
mechanism.
This commit is contained in:
Henry Weller
2023-07-20 14:37:18 +01:00
parent 634b8d1cee
commit 2779442d2a
20 changed files with 432 additions and 111 deletions

View File

@ -1,3 +1,4 @@
fluidSolver.C
functionObjects/fluidMaxDeltaT/fluidMaxDeltaT.C
LIB = $(FOAM_LIBBIN)/libfluidSolver

View File

@ -44,12 +44,8 @@ namespace solvers
void Foam::solvers::fluidSolver::readControls()
{
maxCo =
runTime.controlDict().lookupOrDefault<scalar>("maxCo", 1.0);
maxDeltaT_ =
runTime.controlDict().lookupOrDefault<scalar>("maxDeltaT", vGreat);
if (mesh.solution().modified())
{
correctPhi = pimple.dict().lookupOrDefault
(
"correctPhi",
@ -61,6 +57,7 @@ void Foam::solvers::fluidSolver::readControls()
"checkMeshCourantNo",
false
);
}
}
@ -101,7 +98,7 @@ void Foam::solvers::fluidSolver::correctCoNum
fvc::surfaceSum(mag(phi))().primitiveField()/rho.primitiveField()
);
CoNum = 0.5*gMax(sumPhi/mesh.V().field())*runTime.deltaTValue();
CoNum_ = 0.5*gMax(sumPhi/mesh.V().field())*runTime.deltaTValue();
const scalar meanCoNum =
0.5*(gSum(sumPhi)/gSum(mesh.V().field()))*runTime.deltaTValue();
@ -192,8 +189,17 @@ void Foam::solvers::fluidSolver::continuityErrors
Foam::solvers::fluidSolver::fluidSolver(fvMesh& mesh)
:
solver(mesh),
maxCo
(
mesh.time().controlDict().lookupOrDefault<scalar>("maxCo", vGreat)
),
maxDeltaT_
(
mesh.time().controlDict().lookupOrDefault<scalar>("maxDeltaT", vGreat)
),
cumulativeContErr(0),
CoNum(0)
CoNum_(0),
CoNum(CoNum_)
{
// Read the controls
readControls();
@ -212,7 +218,7 @@ Foam::scalar Foam::solvers::fluidSolver::maxDeltaT() const
{
scalar deltaT = min(fvModels().maxDeltaT(), maxDeltaT_);
if (CoNum > small)
if (maxCo < vGreat && CoNum > small)
{
deltaT = min(deltaT, maxCo/CoNum*runTime.deltaTValue());
}

View File

@ -96,7 +96,7 @@ protected:
bool correctPhi;
//- Current maximum Courant number for time-step control
scalar CoNum;
scalar CoNum_;
//- Read controls
void readControls();
@ -129,6 +129,14 @@ protected:
);
public:
// Public Data
//- Current maximum Courant number for time-step control
const scalar& CoNum;
public:
//- Runtime type information

View File

@ -0,0 +1,113 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2023 OpenFOAM Foundation
\\/ 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 "fluidMaxDeltaT.H"
#include "fluidSolver.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
defineTypeNameAndDebug(fluidMaxDeltaT, 0);
addToRunTimeSelectionTable
(
functionObject,
fluidMaxDeltaT,
dictionary
);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::fluidMaxDeltaT::fluidMaxDeltaT
(
const word& name,
const Time& runTime,
const dictionary& dict
)
:
fvMeshFunctionObject(name, runTime, dict)
{
read(dict);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::functionObjects::fluidMaxDeltaT::~fluidMaxDeltaT()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::functionObjects::fluidMaxDeltaT::read(const dictionary& dict)
{
fvMeshFunctionObject::read(dict);
maxCoPtr_ = Function1<scalar>::New("maxCo", dict);
maxDeltaTPtr_ = Function1<scalar>::New("maxDeltaT", dict);
return true;
}
bool Foam::functionObjects::fluidMaxDeltaT::execute()
{
return true;
}
bool Foam::functionObjects::fluidMaxDeltaT::write()
{
return true;
}
Foam::scalar Foam::functionObjects::fluidMaxDeltaT::maxDeltaT() const
{
scalar deltaT =
time_.userTimeToTime(maxDeltaTPtr_().value(time_.userTimeValue()));
const scalar CoNum =
mesh_.lookupObject<solvers::fluidSolver>(solver::typeName).CoNum;
if (CoNum > small)
{
const scalar maxCo = maxCoPtr_().value(time_.userTimeValue());
deltaT = min(deltaT, maxCo/CoNum*time_.deltaTValue());
}
return deltaT;
}
// ************************************************************************* //

View File

@ -0,0 +1,153 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2022-2023 OpenFOAM Foundation
\\/ 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::functionObjects::fluidMaxDeltaT
Description
Returns the maximum time-step evaluated from time-dependent
maximum Courant number and maximum time-step specifications.
The \c maxCo and \c maxDeltaT are provided as \c Function1 of time,
supporting constant, tabulated and functional specifications.
Usage
Example of a time-dependent maximum Courant number:
\verbatim
fluidMaxDeltaT
{
type fluidMaxDeltaT;
maxCo table
(
(0 0.2)
(0.6 0.2)
(0.7 0.1)
);
maxDeltaT 1;
}
\endverbatim
See also
Foam::functionObject
Foam::functionObjects::fvMeshFunctionObject
Foam::Function1
SourceFiles
fluidMaxDeltaT.C
\*---------------------------------------------------------------------------*/
#ifndef fluidMaxDeltaT_H
#define fluidMaxDeltaT_H
#include "fvMeshFunctionObject.H"
#include "Function1.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
/*---------------------------------------------------------------------------*\
Class fluidMaxDeltaT Declaration
\*---------------------------------------------------------------------------*/
class fluidMaxDeltaT
:
public fvMeshFunctionObject
{
// Private Data
//- Max Courant number function/table
autoPtr<Function1<scalar>> maxCoPtr_;
//- Max time-step function/table
autoPtr<Function1<scalar>> maxDeltaTPtr_;
public:
//- Runtime type information
TypeName("fluidMaxDeltaT");
// Constructors
//- Construct from Time and dictionary
fluidMaxDeltaT
(
const word& name,
const Time& runTime,
const dictionary& dict
);
//- Disallow default bitwise copy construction
fluidMaxDeltaT(const fluidMaxDeltaT&) = delete;
//- Destructor
virtual ~fluidMaxDeltaT();
// Member Functions
//- Read the controls
virtual bool read(const dictionary&);
//- Return the list of fields required
virtual wordList fields() const
{
return wordList::null();
}
//- Execute, currently does nothing
virtual bool execute();
//- Write the time step value
virtual bool write();
//- Return the maximum time-step for stable operation
virtual scalar maxDeltaT() const;
// Member Operators
//- Disallow default bitwise assignment
void operator=(const fluidMaxDeltaT&) = delete;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace functionObjects
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -79,7 +79,7 @@ void Foam::solvers::multiphaseEuler::correctCoNum()
);
}
CoNum = 0.5*gMax(sumPhi/mesh.V().field())*runTime.deltaTValue();
CoNum_ = 0.5*gMax(sumPhi/mesh.V().field())*runTime.deltaTValue();
const scalar meanCoNum =
0.5*(gSum(sumPhi)/gSum(mesh.V().field()))*runTime.deltaTValue();

View File

@ -50,7 +50,7 @@ void Foam::solvers::shockFluid::correctCoNum(const surfaceScalarField& amaxSf)
{
const scalarField sumAmaxSf(fvc::surfaceSum(amaxSf)().primitiveField());
CoNum = 0.5*gMax(sumAmaxSf/mesh.V().field())*runTime.deltaTValue();
CoNum_ = 0.5*gMax(sumAmaxSf/mesh.V().field())*runTime.deltaTValue();
const scalar meanCoNum =
0.5*(gSum(sumAmaxSf)/gSum(mesh.V().field()))*runTime.deltaTValue();

View File

@ -47,6 +47,11 @@ void Foam::setDeltaT(Time& runTime, const PtrList<solver>& solvers)
}
}
if (transient)
{
deltaT = min(deltaT, runTime.functionObjects().maxDeltaT());
}
if (transient && deltaT < rootVGreat)
{
runTime.setDeltaT(min(runTime.deltaTValue(), deltaT));
@ -72,6 +77,11 @@ void Foam::adjustDeltaT(Time& runTime, const PtrList<solver>& solvers)
}
}
if (transient)
{
deltaT = min(deltaT, runTime.functionObjects().maxDeltaT());
}
if (transient && deltaT < rootVGreat)
{
runTime.setDeltaT

View File

@ -34,10 +34,15 @@ void Foam::setDeltaT(Time& runTime, const solver& solver)
runTime.timeIndex() == 0
&& runTime.controlDict().lookupOrDefault("adjustTimeStep", false)
&& solver.transient()
&& solver.maxDeltaT() < rootVGreat
)
{
runTime.setDeltaT(min(runTime.deltaTValue(), solver.maxDeltaT()));
const scalar deltaT =
min(solver.maxDeltaT(), runTime.functionObjects().maxDeltaT());
if (deltaT < rootVGreat)
{
runTime.setDeltaT(min(runTime.deltaTValue(), deltaT));
}
}
}
@ -49,19 +54,20 @@ void Foam::adjustDeltaT(Time& runTime, const solver& solver)
(
runTime.controlDict().lookupOrDefault("adjustTimeStep", false)
&& solver.transient()
&& solver.maxDeltaT() < rootVGreat
)
{
const scalar deltaT =
min(solver.maxDeltaT(), runTime.functionObjects().maxDeltaT());
if (deltaT < rootVGreat)
{
runTime.setDeltaT
(
min
(
solver::deltaTFactor*runTime.deltaTValue(),
solver.maxDeltaT()
)
min(solver::deltaTFactor*runTime.deltaTValue(), deltaT)
);
Info<< "deltaT = " << runTime.deltaTValue() << endl;
}
}
}

View File

@ -163,6 +163,12 @@ Foam::scalar Foam::functionObject::timeToNextAction()
}
Foam::scalar Foam::functionObject::maxDeltaT() const
{
return vGreat;
}
void Foam::functionObject::movePoints(const polyMesh&)
{}

View File

@ -249,6 +249,9 @@ public:
// time. Returns the write time, or vGreat.
virtual scalar timeToNextAction();
//- Return the maximum time-step for stable operation
virtual scalar maxDeltaT() const;
//- Update topology using the given map
virtual void movePoints(const polyMesh& mesh);

View File

@ -299,6 +299,19 @@ Foam::scalar Foam::functionObjectList::timeToNextAction()
}
Foam::scalar Foam::functionObjectList::maxDeltaT() const
{
scalar result = vGreat;
forAll(*this, oi)
{
result = min(result, operator[](oi).maxDeltaT());
}
return result;
}
bool Foam::functionObjectList::read()
{
bool ok = true;

View File

@ -178,6 +178,9 @@ public:
//- Return the time to the next write
scalar timeToNextAction();
//- Return the maximum time-step for stable operation
virtual scalar maxDeltaT() const;
//- Update topology using the given map
virtual void movePoints(const polyMesh& mesh);

View File

@ -208,6 +208,10 @@ public:
template<class Type>
const Type& lookupObject(const word& name) const;
//- Lookup and return the object reference of the given Type
template<class Type>
Type& lookupObjectRef(const word& name) const;
//- Is the Type in registry
// the name is derived from the type name and given group
template<class Type>
@ -218,10 +222,6 @@ public:
template<class Type>
const Type& lookupType(const word& group = word::null) const;
//- Lookup and return the object reference of the given Type
template<class Type>
Type& lookupObjectRef(const word& name) const;
//- Return new event number.
label getEvent() const;

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2023 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -216,6 +216,13 @@ const Type& Foam::objectRegistry::lookupObject(const word& name) const
}
template<class Type>
Type& Foam::objectRegistry::lookupObjectRef(const word& name) const
{
return const_cast<Type&>(lookupObject<Type>(name));
}
template<class Type>
bool Foam::objectRegistry::foundType(const word& group) const
{
@ -230,13 +237,6 @@ const Type& Foam::objectRegistry::lookupType(const word& group) const
}
template<class Type>
Type& Foam::objectRegistry::lookupObjectRef(const word& name) const
{
return const_cast<Type&>(lookupObject<Type>(name));
}
template<class Object>
bool Foam::objectRegistry::cacheTemporaryObject(Object& ob) const
{

View File

@ -126,10 +126,32 @@ bool Foam::functionObjects::adjustTimeStepToCombustion::read
bool Foam::functionObjects::adjustTimeStepToCombustion::execute()
{
return true;
}
bool Foam::functionObjects::adjustTimeStepToCombustion::write()
{
if (extrapolate_ && obr_.time().writeTime())
{
timeIOdictionary propsDict(propsDictIo(IOobject::NO_READ));
propsDict.add("combustionDeltaT", combustionDeltaT0_);
propsDict.regIOobject::write();
}
return true;
}
Foam::scalar
Foam::functionObjects::adjustTimeStepToCombustion::maxDeltaT() const
{
if (!time_.controlDict().lookupOrDefault("adjustTimeStep", false))
{
return true;
return vGreat;
}
const combustionModel& combustion =
@ -185,32 +207,7 @@ bool Foam::functionObjects::adjustTimeStepToCombustion::execute()
haveCombustionDeltaT0_ = true;
combustionDeltaT0_ = combustionDeltaT1;
// The solver has not adjusted the time-step yet. When it does, if it is
// within the physical and specified limits it will increase it by a
// fixed factor. So, we clip it here to the combustion time-step divided by
// that factor. The solver will then increase it to the combustion
// time-step if it can.
const_cast<Time&>(time_).setDeltaTNoAdjust
(
min(deltaT/solver::deltaTFactor, time_.deltaTValue())
);
return true;
}
bool Foam::functionObjects::adjustTimeStepToCombustion::write()
{
if (extrapolate_ && obr_.time().writeTime())
{
timeIOdictionary propsDict(propsDictIo(IOobject::NO_READ));
propsDict.add("combustionDeltaT", combustionDeltaT0_);
propsDict.regIOobject::write();
}
return true;
return deltaT;
}

View File

@ -25,17 +25,18 @@ Class
Foam::functionObjects::adjustTimeStepToCombustion
Description
Adjusts the time step to match bulk reaction time scales. This allows the
solver to temporally resolve chemical changes, in order to better couple
the chemistry and transport, or to improve the time-accuracy of
post-processing.
Returns the minimum bulk reaction time scale
This allows the solver to temporally resolve chemical changes, in order to
better couple the chemistry and transport, or to improve the time-accuracy
of post-processing.
Note that this function only does anything if time step adjustment is
enabled in the controlDict.
Example of function object specification:
\verbatim
adjustTimeStepToCombustion1
adjustTimeStepToCombustion
{
type adjustTimeStepToCombustion;
libs ("libcombustionModels.so");
@ -94,10 +95,10 @@ class adjustTimeStepToCombustion
bool extrapolate_;
//- Do we have the previous combustion time-step?
bool haveCombustionDeltaT0_;
mutable bool haveCombustionDeltaT0_;
//- The previous combustion time-step
scalar combustionDeltaT0_;
mutable scalar combustionDeltaT0_;
// Private Member Functions
@ -143,12 +144,15 @@ public:
return wordList::null();
}
//- Reset the timeStep from the Function1 of time
//- Do nothing
virtual bool execute();
//- Do nothing
virtual bool write();
//- Return the minimum combustion time-scale
virtual scalar maxDeltaT() const;
// Member Operators

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2013-2022 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2013-2023 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -158,7 +158,7 @@ bool Foam::functionObjects::turbulenceFields::read(const dictionary& dict)
bool Foam::functionObjects::turbulenceFields::execute()
{
if (obr_.foundObject<fluidThermophysicalTransportModel>(phaseName_))
if (obr_.foundType<fluidThermophysicalTransportModel>(phaseName_))
{
const fluidThermophysicalTransportModel& ttm =
obr_.lookupType<fluidThermophysicalTransportModel>(phaseName_);

View File

@ -83,29 +83,6 @@ bool Foam::functionObjects::adjustTimeStepToChemistry::read
bool Foam::functionObjects::adjustTimeStepToChemistry::execute()
{
if (!time_.controlDict().lookupOrDefault("adjustTimeStep", false))
{
return true;
}
const basicChemistryModel& chemistry =
obr_.lookupObject<basicChemistryModel>
(
IOobject::groupName("chemistryProperties", phaseName_)
);
const scalar deltaT = gMin(chemistry.deltaTChem());
// The solver has not adjusted the time-step yet. When it does, if it is
// within the physical and specified limits it will increase it by a
// fixed factor. So, we clip it here to the chemical time-step divided by
// that factor. The solver will then increase it to the chemical time-step
// if it can.
const_cast<Time&>(time_).setDeltaTNoAdjust
(
min(deltaT/solver::deltaTFactor, time_.deltaTValue())
);
return true;
}
@ -116,4 +93,21 @@ bool Foam::functionObjects::adjustTimeStepToChemistry::write()
}
Foam::scalar Foam::functionObjects::adjustTimeStepToChemistry::maxDeltaT() const
{
if (!time_.controlDict().lookupOrDefault("adjustTimeStep", false))
{
return vGreat;
}
const basicChemistryModel& chemistry =
obr_.lookupObject<basicChemistryModel>
(
IOobject::groupName("chemistryProperties", phaseName_)
);
return gMin(chemistry.deltaTChem());
}
// ************************************************************************* //

View File

@ -25,17 +25,18 @@ Class
Foam::functionObjects::adjustTimeStepToChemistry
Description
Adjusts the time step to match a chemistry model's stored chemical time
step. This allows the solver to temporally resolve chemical changes, in
order to better couple the chemistry and transport, or in order to
accurately post-process the chemical changes.
Returns the minimum chemistry chemical time scale
This allows the solver to temporally resolve chemical changes, in order to
better couple the chemistry and transport, or in order to accurately
post-process the chemical changes.
Note that this function only does anything if time step adjustment is
enabled in the controlDict.
Example of function object specification:
\verbatim
adjustTimeStepToChemistry1
adjustTimeStepToChemistry
{
type adjustTimeStepToChemistry;
libs ("libchemistryModel.so");
@ -114,12 +115,15 @@ public:
return wordList::null();
}
//- Reset the timeStep from the Function1 of time
//- Do nothing
virtual bool execute();
//- Do nothing
virtual bool write();
//- Return the minimum chemistry.deltaTChem()
virtual scalar maxDeltaT() const;
// Member Operators