Compare commits
4 Commits
demand-dri
...
feature-un
| Author | SHA1 | Date | |
|---|---|---|---|
| 07664c0de8 | |||
| 32c8fb57b7 | |||
| 4ee7dd50ee | |||
| 162f5f29ec |
@ -967,6 +967,34 @@ bool Foam::Time::end() const
|
||||
}
|
||||
|
||||
|
||||
bool Foam::Time::reverseRun() const
|
||||
{
|
||||
// Must not solve for the 0 time step
|
||||
bool isRunning = value() > (endTime_ + 0.5*deltaT_);
|
||||
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::Time::reverseLoop()
|
||||
{
|
||||
const bool isRunning = reverseRun();
|
||||
|
||||
if (isRunning)
|
||||
{
|
||||
operator--();
|
||||
}
|
||||
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::Time::reverseEnd() const
|
||||
{
|
||||
return value() < (endTime_ - 0.5*deltaT_);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::Time::stopAt(const stopAtControls stopCtrl) const
|
||||
{
|
||||
if (stopCtrl == stopAtControls::saUnknown)
|
||||
@ -1365,4 +1393,242 @@ Foam::Time& Foam::Time::operator++(int)
|
||||
}
|
||||
|
||||
|
||||
Foam::Time&
|
||||
Foam::Time::operator-=(const dimensionedScalar& deltaT)
|
||||
{
|
||||
return operator-=(deltaT.value());
|
||||
}
|
||||
|
||||
|
||||
Foam::Time& Foam::Time::operator-=(const scalar deltaT)
|
||||
{
|
||||
setDeltaT(deltaT);
|
||||
return operator--();
|
||||
}
|
||||
|
||||
|
||||
Foam::Time& Foam::Time::operator--()
|
||||
{
|
||||
deltaT0_ = deltaTSave_;
|
||||
deltaTSave_ = deltaT_;
|
||||
|
||||
// Save old time value and name
|
||||
const scalar oldTimeValue = timeToUserTime(value());
|
||||
const word oldTimeName = dimensionedScalar::name();
|
||||
|
||||
// Decrease time
|
||||
setTime(value() - deltaT_, timeIndex_ - 1);
|
||||
|
||||
if (!subCycling_)
|
||||
{
|
||||
// If the time is very close to zero reset to zero
|
||||
if (mag(value()) < 10*SMALL*deltaT_)
|
||||
{
|
||||
setTime(0.0, timeIndex_);
|
||||
}
|
||||
|
||||
if (sigStopAtWriteNow_.active() || sigWriteNow_.active())
|
||||
{
|
||||
// A signal might have been sent on one processor only
|
||||
// Reduce so all decide the same.
|
||||
|
||||
label flag = 0;
|
||||
if (sigStopAtWriteNow_.active() && stopAt_ == saWriteNow)
|
||||
{
|
||||
flag += 1;
|
||||
}
|
||||
if (sigWriteNow_.active() && writeOnce_)
|
||||
{
|
||||
flag += 2;
|
||||
}
|
||||
reduce(flag, maxOp<label>());
|
||||
|
||||
if (flag & 1)
|
||||
{
|
||||
stopAt_ = saWriteNow;
|
||||
}
|
||||
if (flag & 2)
|
||||
{
|
||||
writeOnce_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
writeTime_ = false;
|
||||
|
||||
switch (writeControl_)
|
||||
{
|
||||
case wcNone:
|
||||
case wcUnknown:
|
||||
break;
|
||||
|
||||
case wcTimeStep:
|
||||
// Avoid writing just because timIndex_ is zero
|
||||
writeTime_ =
|
||||
!(timeIndex_ % label(writeInterval_)) && timeIndex_;
|
||||
break;
|
||||
|
||||
case wcRunTime:
|
||||
case wcAdjustableRunTime:
|
||||
{
|
||||
const label writeIndex = label
|
||||
(
|
||||
((value() - startTime_) - 0.5*deltaT_)
|
||||
/ writeInterval_
|
||||
);
|
||||
|
||||
if (writeIndex < writeTimeIndex_)
|
||||
{
|
||||
writeTime_ = true;
|
||||
writeTimeIndex_ = writeIndex;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case wcCpuTime:
|
||||
{
|
||||
const label writeIndex = label
|
||||
(
|
||||
returnReduce(elapsedCpuTime(), maxOp<double>())
|
||||
/ writeInterval_
|
||||
);
|
||||
if (writeIndex > writeTimeIndex_)
|
||||
{
|
||||
writeTime_ = true;
|
||||
writeTimeIndex_ = writeIndex;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case wcClockTime:
|
||||
{
|
||||
const label writeIndex = label
|
||||
(
|
||||
returnReduce(elapsedClockTime(), maxOp<double>())
|
||||
/ writeInterval_
|
||||
);
|
||||
if (writeIndex > writeTimeIndex_)
|
||||
{
|
||||
writeTime_ = true;
|
||||
writeTimeIndex_ = writeIndex;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Check if endTime needs adjustment to stop at the next
|
||||
// reverseRun()/reverseEnd()
|
||||
if (!reverseEnd())
|
||||
{
|
||||
if (stopAt_ == saNoWriteNow)
|
||||
{
|
||||
endTime_ = value();
|
||||
}
|
||||
else if (stopAt_ == saWriteNow)
|
||||
{
|
||||
endTime_ = value();
|
||||
writeTime_ = true;
|
||||
}
|
||||
else if (stopAt_ == saNextWrite && writeTime_ == true)
|
||||
{
|
||||
endTime_ = value();
|
||||
}
|
||||
}
|
||||
|
||||
// Override writeTime if one-shot writing
|
||||
if (writeOnce_)
|
||||
{
|
||||
writeTime_ = true;
|
||||
writeOnce_ = false;
|
||||
}
|
||||
|
||||
// Adjust the precision of the time directory name if necessary
|
||||
if (writeTime_)
|
||||
{
|
||||
// Tolerance used when testing time equivalence
|
||||
const scalar timeTol =
|
||||
max(min(pow(10.0, -precision_), 0.1*deltaT_), SMALL);
|
||||
|
||||
// User-time equivalent of deltaT
|
||||
const scalar userDeltaT = timeToUserTime(deltaT_);
|
||||
|
||||
// Time value obtained by reading timeName
|
||||
scalar timeNameValue = -VGREAT;
|
||||
|
||||
// Check that new time representation differs from old one
|
||||
// reinterpretation of the word
|
||||
if
|
||||
(
|
||||
readScalar(dimensionedScalar::name(), timeNameValue)
|
||||
&& (mag(-timeNameValue + oldTimeValue - userDeltaT) > timeTol)
|
||||
)
|
||||
{
|
||||
int oldPrecision = precision_;
|
||||
while
|
||||
(
|
||||
precision_ < maxPrecision_
|
||||
&& readScalar(dimensionedScalar::name(), timeNameValue)
|
||||
&& (mag(-timeNameValue + oldTimeValue - userDeltaT) > timeTol)
|
||||
)
|
||||
{
|
||||
precision_++;
|
||||
setTime(value(), timeIndex());
|
||||
}
|
||||
|
||||
if (precision_ != oldPrecision)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Increased the timePrecision from " << oldPrecision
|
||||
<< " to " << precision_
|
||||
<< " to distinguish between timeNames at time "
|
||||
<< dimensionedScalar::name()
|
||||
<< endl;
|
||||
|
||||
if (precision_ == maxPrecision_)
|
||||
{
|
||||
// Reached maxPrecision limit
|
||||
WarningInFunction
|
||||
<< "Current time name " << dimensionedScalar::name()
|
||||
<< nl
|
||||
<< " The maximum time precision has been reached"
|
||||
" which might result in overwriting previous"
|
||||
" results."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Check if round-off error caused time-reversal
|
||||
scalar oldTimeNameValue = -VGREAT;
|
||||
if
|
||||
(
|
||||
readScalar(oldTimeName, oldTimeNameValue)
|
||||
&& (
|
||||
sign(timeNameValue - oldTimeNameValue)
|
||||
!= sign(deltaT_)
|
||||
)
|
||||
)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Current time name " << dimensionedScalar::name()
|
||||
<< " is set to an instance prior to the "
|
||||
"previous one "
|
||||
<< oldTimeName << nl
|
||||
<< " This might result in temporal "
|
||||
"discontinuities."
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Foam::Time& Foam::Time::operator--(int)
|
||||
{
|
||||
return operator--();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2022 PCOpt/NTUA
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -571,6 +572,43 @@ public:
|
||||
// not yield the same result
|
||||
virtual bool end() const;
|
||||
|
||||
//- Return true if run should continue.
|
||||
// Does not invoke any functionObject methods
|
||||
// \note
|
||||
// For correct behaviour, the following style of time-loop
|
||||
// is recommended:
|
||||
// \code
|
||||
// while (runTime.reverseRun())
|
||||
// {
|
||||
// --runTime;
|
||||
// solve;
|
||||
// runTime.write();
|
||||
// }
|
||||
// \endcode
|
||||
virtual bool reverseRun() const;
|
||||
|
||||
//- Return true if run should continue and if so decrease time
|
||||
// Does not invoke any functionObject methods
|
||||
// \note
|
||||
// For correct behaviour, the following style of time-loop
|
||||
// is recommended:
|
||||
// \code
|
||||
// while (runTime.reverseLoop())
|
||||
// {
|
||||
// solve;
|
||||
// runTime.write();
|
||||
// }
|
||||
// \endcode
|
||||
virtual bool reverseLoop();
|
||||
|
||||
//- Return true if end of run,
|
||||
// does not invoke any functionObject methods
|
||||
// \note
|
||||
// The rounding heuristics near endTime mean that
|
||||
// \code reverseRun() \endcode and \code !reverseEnd() \endcode
|
||||
// may not yield the same result
|
||||
virtual bool reverseEnd() const;
|
||||
|
||||
|
||||
// Edit
|
||||
|
||||
@ -653,6 +691,20 @@ public:
|
||||
|
||||
//- Postfix increment, this is identical to the prefix increment
|
||||
virtual Time& operator++(int);
|
||||
|
||||
//- Set deltaT to that specified and decrease time via operator--()
|
||||
virtual Time& operator-=(const dimensionedScalar& deltaT);
|
||||
|
||||
//- Set deltaT to that specified and decrease time via operator--()
|
||||
virtual Time& operator-=(const scalar deltaT);
|
||||
|
||||
//- prefix decrease,
|
||||
// also invokes the functionobjectlist::start() or
|
||||
// functionobjectlist::execute() method, depending on the time-index
|
||||
virtual Time& operator--();
|
||||
|
||||
//- Postfix decrease, this is identical to the decrease increment
|
||||
virtual Time& operator--(int);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -545,7 +545,8 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
||||
(
|
||||
const IOobject& io,
|
||||
const Mesh& mesh,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
const bool readOldTime
|
||||
)
|
||||
:
|
||||
Internal(io, mesh, dimless, false),
|
||||
@ -566,6 +567,11 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
if (readOldTime)
|
||||
{
|
||||
readOldTimeIfPresent();
|
||||
}
|
||||
|
||||
DebugInFunction
|
||||
<< "Finishing dictionary-construct" << nl << this->info() << endl;
|
||||
}
|
||||
@ -623,7 +629,8 @@ template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
||||
(
|
||||
const IOobject& io,
|
||||
const GeometricField<Type, PatchField, GeoMesh>& gf
|
||||
const GeometricField<Type, PatchField, GeoMesh>& gf,
|
||||
const bool readOldTime
|
||||
)
|
||||
:
|
||||
Internal(io, gf),
|
||||
@ -636,7 +643,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
||||
<< "Copy construct, resetting IO params" << nl
|
||||
<< this->info() << endl;
|
||||
|
||||
if (!readIfPresent() && gf.field0Ptr_)
|
||||
if (!readIfPresent() && gf.field0Ptr_ && readOldTime)
|
||||
{
|
||||
field0Ptr_ = new GeometricField<Type, PatchField, GeoMesh>
|
||||
(
|
||||
|
||||
@ -296,7 +296,8 @@ public:
|
||||
(
|
||||
const IOobject& io,
|
||||
const Mesh& mesh,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
const bool readOldTime = false
|
||||
);
|
||||
|
||||
//- Copy construct
|
||||
@ -315,7 +316,8 @@ public:
|
||||
GeometricField
|
||||
(
|
||||
const IOobject& io,
|
||||
const GeometricField<Type, PatchField, GeoMesh>& gf
|
||||
const GeometricField<Type, PatchField, GeoMesh>& gf,
|
||||
const bool readOldTime = true
|
||||
);
|
||||
|
||||
//- Construct from tmp\<GeometricField\> resetting IO parameters
|
||||
|
||||
@ -1,3 +1,12 @@
|
||||
/* COMPRESSION PARAMETERS */
|
||||
storage/primalStorage/storageParameters/storageParameters/storageParameters.C
|
||||
storage/primalStorage/storageParameters/shortParameters/shortParameters.C
|
||||
|
||||
/* COMPRESSED GEOMETRIC FIELD */
|
||||
compressedGeometricField = OpenFOAM/fields/compressedGeometricField
|
||||
$(compressedGeometricField)/compressedGeometricField/compressedGeometricFields.C
|
||||
$(compressedGeometricField)/shortGeometricField/shortGeometricFields.C
|
||||
|
||||
/* TURBULENCE MODEL VARIABLE REFS */
|
||||
turbulenceModels/turbulenceModelVariables/RAS/RASModelVariables/RASModelVariables.C
|
||||
turbulenceModels/turbulenceModelVariables/RAS/laminar/laminar.C
|
||||
@ -11,12 +20,29 @@ solvers/variablesSet/variablesSet/variablesSet.C
|
||||
solvers/variablesSet/incompressible/incompressibleVars.C
|
||||
solvers/variablesSet/incompressibleAdjointMeanFlow/incompressibleAdjointMeanFlowVars.C
|
||||
solvers/variablesSet/incompressibleAdjoint/incompressibleAdjointVars.C
|
||||
solvers/variablesSet/compressedIncompressible/compressedIncompressibleVars/compressedIncompressibleVars.C
|
||||
solvers/variablesSet/compressedIncompressible/shortIncompressibleVars/shortIncompressibleVars.C
|
||||
solvers/variablesSet/compressedIncompressible/fullIncompressibleVars/fullIncompressibleVars.C
|
||||
solvers/variablesSet/checkPoint/checkPoint.C
|
||||
|
||||
/* SOLVER CONTROL */
|
||||
solvers/solverControl/solverControl/solverControl.C
|
||||
solvers/solverControl/SIMPLEControl/SIMPLEControl/SIMPLEControl.C
|
||||
solvers/solverControl/SIMPLEControl/singleRun/SIMPLEControlSingleRun.C
|
||||
solvers/solverControl/SIMPLEControl/optimisation/SIMPLEControlOpt.C
|
||||
solvers/solverControl/PISOControl/PISOControl/PISOControl.C
|
||||
solvers/solverControl/PISOControl/optimisation/PISOControlOpt.C
|
||||
solvers/solverControl/PIMPLEControl/PIMPLEControl/PIMPLEControl.C
|
||||
solvers/solverControl/PIMPLEControl/optimisation/PIMPLEControlOpt.C
|
||||
|
||||
/* STORAGE MANAGMENT */
|
||||
storage/primalStorage/primalStorage/primalStorage.C
|
||||
storage/primalStorage/fullStorage/fullStorage.C
|
||||
storage/primalStorage/none/noneStorage.C
|
||||
storage/primalStorage/binomialCheckPointing/binomialCheckPointing.C
|
||||
compressedFullStorage = storage/primalStorage/compressedFullStorage
|
||||
$(compressedFullStorage)/compressedFullStorage/compressedFullStorage.C
|
||||
$(compressedFullStorage)/shortFullStorage/shortFullStorage.C
|
||||
|
||||
/* SOLVERS */
|
||||
solvers/solver/solver.C
|
||||
@ -24,9 +50,13 @@ solvers/primalSolvers/primalSolver/primalSolver.C
|
||||
solvers/primalSolvers/incompressible/incompressiblePrimalSolver/incompressiblePrimalSolver.C
|
||||
solvers/primalSolvers/incompressible/simple/simple.C
|
||||
solvers/primalSolvers/incompressible/RASTurbulenceModel/RASTurbulenceModel.C
|
||||
solvers/primalSolvers/incompressible/piso/piso.C
|
||||
solvers/primalSolvers/incompressible/pimple/pimple.C
|
||||
solvers/adjointSolvers/adjointSolver/adjointSolver.C
|
||||
solvers/adjointSolvers/incompressible/incompressibleAdjointSolver/incompressibleAdjointSolver.C
|
||||
solvers/adjointSolvers/incompressible/adjointSimple/adjointSimple.C
|
||||
solvers/adjointSolvers/incompressible/adjointPiso/adjointPiso.C
|
||||
solvers/adjointSolvers/incompressible/adjointPimple/adjointPimple.C
|
||||
|
||||
/* ADJOINT SOLVER MANAGER */
|
||||
solvers/adjointSolverManager/adjointSolverManager.C
|
||||
@ -183,5 +213,7 @@ $(incoOptType)/shapeOptimisation/shapeOptimisationIncompressible.C
|
||||
optimisation/optimisationManager/optimisationManager/optimisationManager.C
|
||||
optimisation/optimisationManager/singleRun/singleRun.C
|
||||
optimisation/optimisationManager/steadyOptimisation/steadyOptimisation.C
|
||||
optimisation/optimisationManager/unsteadyOptimisation/unsteadyTimeManipulation/unsteadyTimeManipulation.C
|
||||
optimisation/optimisationManager/unsteadyOptimisation/unsteadyOptimisation.C
|
||||
|
||||
LIB = $(FOAM_LIBBIN)/libadjointOptimisation
|
||||
|
||||
@ -0,0 +1,612 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "wallFvPatch.H"
|
||||
#include "symmetryPlaneFvPatch.H"
|
||||
#include "emptyFvsPatchField.H"
|
||||
#include "processorFvsPatchField.H"
|
||||
#include "coupledFvPatchField.H"
|
||||
#include "emptyFvPatchField.H"
|
||||
#include "zeroGradientFvPatchField.H"
|
||||
#include "inletOutletFvPatchField.H"
|
||||
#include "outletInletFvPatchField.H"
|
||||
#include "freestreamFvPatchField.H"
|
||||
#include "slipFvPatchField.H"
|
||||
#include "symmetryFvPatchField.H"
|
||||
#include "symmetryPlaneFvPatchField.H"
|
||||
#include "cyclicACMIFvPatchField.H"
|
||||
#include "bound.H"
|
||||
#include "compressedGeometricField.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
label compressedGeometricField<Type, PatchField, GeoMesh>::counter = 0;
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<>
|
||||
inline scalar&
|
||||
compressedGeometricField<scalar, fvPatchField, volMesh>::getValue
|
||||
(
|
||||
Field<scalar>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const
|
||||
{
|
||||
return field[pos];
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline scalar&
|
||||
compressedGeometricField<scalar, fvsPatchField, surfaceMesh>::getValue
|
||||
(
|
||||
Field<scalar>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const
|
||||
{
|
||||
return field[pos];
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline scalar&
|
||||
compressedGeometricField<vector, fvPatchField, volMesh>::getValue
|
||||
(
|
||||
Field<vector>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const
|
||||
{
|
||||
return field[pos][componI];
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline const scalar&
|
||||
compressedGeometricField<scalar, fvPatchField, volMesh>::getValue
|
||||
(
|
||||
const Field<scalar>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const
|
||||
{
|
||||
return field[pos];
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline const scalar&
|
||||
compressedGeometricField<scalar, fvsPatchField, surfaceMesh>::getValue
|
||||
(
|
||||
const Field<scalar>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const
|
||||
{
|
||||
return field[pos];
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline const scalar&
|
||||
compressedGeometricField<vector, fvPatchField, volMesh>::getValue
|
||||
(
|
||||
const Field<vector>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const
|
||||
{
|
||||
return field[pos][componI];
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline scalar&
|
||||
compressedGeometricField<scalar, fvPatchField, volMesh>::getValue
|
||||
(
|
||||
List<scalar>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const
|
||||
{
|
||||
return field[pos];
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline scalar&
|
||||
compressedGeometricField<scalar, fvsPatchField, surfaceMesh>::getValue
|
||||
(
|
||||
List<scalar>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const
|
||||
{
|
||||
return field[pos];
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline scalar&
|
||||
compressedGeometricField<vector, fvPatchField, volMesh>::getValue
|
||||
(
|
||||
List<vector>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const
|
||||
{
|
||||
return field[pos][componI];
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline const
|
||||
scalar& compressedGeometricField<scalar, fvPatchField, volMesh>::getValue
|
||||
(
|
||||
const List<scalar>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const
|
||||
{
|
||||
return field[pos];
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline const
|
||||
scalar& compressedGeometricField<scalar, fvsPatchField, surfaceMesh>::getValue
|
||||
(
|
||||
const List<scalar>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const
|
||||
{
|
||||
return field[pos];
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline const
|
||||
scalar& compressedGeometricField<vector, fvPatchField, volMesh>::getValue
|
||||
(
|
||||
const List<vector>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const
|
||||
{
|
||||
return field[pos][componI];
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void compressedGeometricField<Type, PatchField, GeoMesh>::toBeStored()
|
||||
{
|
||||
setValidComponent();
|
||||
toBeStored_.setSize(mesh_.boundary().size(), false);
|
||||
toBeStoredUniformOrNot_.setSize(mesh_.boundary().size(), false);
|
||||
surfacePatchesToBeZeroed_.setSize(mesh_.boundary().size(), false);
|
||||
typedef typename GeometricField<Type, PatchField, GeoMesh>::Boundary
|
||||
Boundary;
|
||||
const Boundary& boundaryField = field_.boundaryField();
|
||||
forAll(mesh_.boundary(), pI)
|
||||
{
|
||||
const PatchField<Type>& pf = boundaryField[pI];
|
||||
if (storageParams_.storeAllBoundaries())
|
||||
{
|
||||
if (pf.size() != 0)
|
||||
{
|
||||
// Warning: Possible error upon compression of boundaries
|
||||
// with very small values when single precision is used.
|
||||
// E.g. flux phi on boundaries with rotatingWallVelocity
|
||||
// for the velocity
|
||||
toBeStoredUniformOrNot_[pI] = true;
|
||||
toBeStored_[pI] = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
checkFvsPatchFieldStorage(pf, pI);
|
||||
checkFvPatchFieldStorage(pf, pI);
|
||||
}
|
||||
if (debug > 1)
|
||||
{
|
||||
Info<< "Field '" << field_.name() << "': "
|
||||
<< "Storing boundary patch " << pI
|
||||
<< " '" << mesh_.boundary()[pI].name() << "' "
|
||||
<< "of type '" << boundaryField.types()[pI] << "'? "
|
||||
<< Switch(toBeStored_[pI]);
|
||||
if (toBeStoredUniformOrNot_[pI] && !toBeStored_[pI])
|
||||
{
|
||||
Info << " --> Uniform boundary. A single value is stored.";
|
||||
}
|
||||
Info << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void
|
||||
compressedGeometricField<Type, PatchField, GeoMesh>::checkFvsPatchFieldStorage
|
||||
(
|
||||
const PatchField<Type>& patchField,
|
||||
const label pI
|
||||
)
|
||||
{
|
||||
if
|
||||
(
|
||||
isA<fvsPatchField<Type>>(patchField)
|
||||
&& !isA<emptyFvsPatchField<Type>>(patchField)
|
||||
&& patchField.size()
|
||||
)
|
||||
{
|
||||
toBeStoredUniformOrNot_[pI] = true;
|
||||
// Store processor boundaries even if they are not uniform.
|
||||
// Not sure what will happen at a latter time-step for
|
||||
// compression techniques using time-windows, such as iPGD
|
||||
// Processor check only valid for surfaceFields since volFields
|
||||
// wont enter here due to !isA<coupledFvPatch>
|
||||
if
|
||||
(
|
||||
!patchField.uniform()
|
||||
|| storageParams_.storeUniformBoundaries()
|
||||
|| isA<processorFvsPatchField<Type>>(patchField)
|
||||
)
|
||||
{
|
||||
toBeStored_[pI] = true;
|
||||
}
|
||||
// At boundaries with a near-zero value of flux, store a
|
||||
// (single) zero value for phi. This was added after ZFP
|
||||
// crashed trying to compress single-precision values of the
|
||||
// iPGD modes with magnitude below 5.e-30. That problem does
|
||||
// not arise if these values are represented in
|
||||
// double-precision. In case that the maximum flux magnitude
|
||||
// is lower than 1.e-15, it is assumed that the field should
|
||||
// be zero and the non-zero values arise due to arithmetic
|
||||
// error. This threshold has been arbitrarily chosen.
|
||||
// Target patch types (although not checked in the code):
|
||||
// wall, symmetryPlane
|
||||
|
||||
// surfacePatchesToBeZeroed becomes true only in case that phi at the
|
||||
// corresponding patch must be stored (toBeStoredUniformOrNot = true)
|
||||
// and is not uniform (patchField.uniform() = false)
|
||||
if (toBeStored_[pI])
|
||||
{
|
||||
// Do the magnitude check here, to avoid unnecessary max
|
||||
// mag calculations
|
||||
if (max(mag(patchField)) < 1.e-15)
|
||||
{
|
||||
toBeStored_[pI] = false;
|
||||
surfacePatchesToBeZeroed_[pI] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void
|
||||
compressedGeometricField<Type, PatchField, GeoMesh>::checkFvPatchFieldStorage
|
||||
(
|
||||
const PatchField<Type>& patchField,
|
||||
const label pI
|
||||
)
|
||||
{
|
||||
const fvPatch& patch = mesh_.boundary()[pI];
|
||||
if
|
||||
(
|
||||
isA<fvPatchField<Type>>(patchField)
|
||||
&& !isA<emptyFvPatchField<Type>>(patchField)
|
||||
&& !isA<coupledFvPatchField<Type>>(patchField)
|
||||
&& !isA<wallFvPatch>(patch)
|
||||
&& !isA<cyclicAMIFvPatchField<Type>>(patchField)
|
||||
&& !isA<zeroGradientFvPatchField<Type>>(patchField)
|
||||
&& !isA<inletOutletFvPatchField<Type>>(patchField)
|
||||
&& !isA<outletInletFvPatchField<Type>>(patchField)
|
||||
&& !isA<freestreamFvPatchField<Type>>(patchField)
|
||||
&& !isA<slipFvPatchField<Type>>(patchField)
|
||||
&& !isA<symmetryFvPatchField<Type>>(patchField)
|
||||
&& !isA<symmetryPlaneFvPatchField<Type>>(patchField)
|
||||
&& patchField.size()
|
||||
)
|
||||
{
|
||||
toBeStoredUniformOrNot_[pI] = true;
|
||||
if (!patchField.uniform() || storageParams_.storeUniformBoundaries())
|
||||
{
|
||||
toBeStored_[pI] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void compressedGeometricField<Type, PatchField, GeoMesh>::setValidComponent()
|
||||
{
|
||||
validCompon_ = 0;
|
||||
if (!solDirs_[0])
|
||||
{
|
||||
validCompon_ = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void compressedGeometricField<Type, PatchField, GeoMesh>::computeSize()
|
||||
{
|
||||
initialSize_ = Zero;
|
||||
uncompressedRoughSize_ = Zero;
|
||||
totalSize_ = Zero;
|
||||
const Field<Type>& internalField = field_.primitiveField();
|
||||
for (label cmptI = 0; cmptI < pTraits<Type>::nComponents; ++cmptI)
|
||||
{
|
||||
initialSize_ += internalField.size()*sizeof(scalar);
|
||||
if (solDirs_[cmptI])
|
||||
{
|
||||
uncompressedRoughSize_ += internalField.size()*sizeof(scalar);
|
||||
totalSize_ += internalField.size();
|
||||
}
|
||||
forAll(mesh_.boundary(), pI)
|
||||
{
|
||||
const Field<Type>& boundaryField = field_.boundaryField()[pI];
|
||||
initialSize_ += boundaryField.size()*sizeof(scalar);
|
||||
if (toBeStored_[pI] && solDirs_[cmptI])
|
||||
{
|
||||
uncompressedRoughSize_ += boundaryField.size()*sizeof(scalar);
|
||||
totalSize_ += boundaryField.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void compressedGeometricField<Type, PatchField, GeoMesh>::gatherStorageMetrics()
|
||||
{
|
||||
if (!timing_)
|
||||
{
|
||||
for (scalar& sm : storageMetrics_)
|
||||
{
|
||||
reduce(sm, sumOp<scalar>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline void
|
||||
compressedGeometricField<scalar, fvPatchField, volMesh>::handleParticularities
|
||||
(
|
||||
volScalarField& field
|
||||
)
|
||||
{
|
||||
// Due to compression error, turbulence variables might take on
|
||||
// negative values. Correct here
|
||||
// TODO: A little dangerous way to identify turbuelence fields
|
||||
if (iPtr_ == 3 || iPtr_ == 4)
|
||||
{
|
||||
bound(field, dimensionedScalar(field.dimensions(), Zero));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline void
|
||||
compressedGeometricField<vector, fvPatchField, volMesh>::handleParticularities
|
||||
(
|
||||
volVectorField& field
|
||||
)
|
||||
{
|
||||
vectorField& internalField = field_.primitiveFieldRef();
|
||||
const labelList& cellIDs = storageParams_.wallList();
|
||||
label cellCounter(0);
|
||||
forAll(cellIDs, i)
|
||||
{
|
||||
vector& vec = internalField[cellIDs[i]];
|
||||
if (mag(vec) < SMALL)
|
||||
{
|
||||
cellCounter++;
|
||||
forAll(vec, j)
|
||||
{
|
||||
if (solDirs_[j])
|
||||
{
|
||||
vec[j] = SMALL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DebugInfo
|
||||
<< "Modified " << field.name() << " in " << cellCounter
|
||||
<< " cell(s) next to wall boundaries" << endl;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline void
|
||||
compressedGeometricField<scalar, fvsPatchField, surfaceMesh>::handleParticularities
|
||||
(
|
||||
surfaceScalarField& field
|
||||
)
|
||||
{
|
||||
// Does nothing
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline void compressedGeometricField<scalar, fvPatchField, volMesh>::correctBCs
|
||||
(
|
||||
volScalarField& field
|
||||
)
|
||||
{
|
||||
handleParticularities(field);
|
||||
if (!storageParams_.storeAllBoundaries())
|
||||
{
|
||||
field.correctBoundaryConditions();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline void compressedGeometricField<vector, fvPatchField, volMesh>::correctBCs
|
||||
(
|
||||
volVectorField& field
|
||||
)
|
||||
{
|
||||
handleParticularities(field);
|
||||
if (!storageParams_.storeAllBoundaries())
|
||||
{
|
||||
field.correctBoundaryConditions();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline void
|
||||
compressedGeometricField<scalar, fvsPatchField, surfaceMesh>::correctBCs
|
||||
(
|
||||
surfaceScalarField& field
|
||||
)
|
||||
{
|
||||
// Does nothing
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
compressedGeometricField<Type, PatchField, GeoMesh>::compressedGeometricField
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
storageParameters& storageParams,
|
||||
const label iPtr,
|
||||
const label& k
|
||||
):
|
||||
field_(field),
|
||||
iPtr_(iPtr),
|
||||
|
||||
dict_(storageParams.dict()),
|
||||
mesh_(field.mesh()),
|
||||
validCompon_(0),
|
||||
k_(k),
|
||||
|
||||
storageParams_(storageParams),
|
||||
timing_(storageParams.timing()),
|
||||
solDirs_(storageParams.solDirs()),
|
||||
eps_(1.e-12),
|
||||
|
||||
storageMetrics_(4, Zero),
|
||||
initialSize_(storageMetrics_[0]),
|
||||
uncompressedRoughSize_(storageMetrics_[1]),
|
||||
uncompressedSize_(storageMetrics_[2]),
|
||||
compressedSize_(storageMetrics_[3]),
|
||||
totalSize_(Zero)
|
||||
{
|
||||
if (Pstream::master()) counter++;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
autoPtr<compressedGeometricField<Type, PatchField, GeoMesh>>
|
||||
compressedGeometricField<Type, PatchField, GeoMesh>::New
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
storageParameters& storageParams,
|
||||
const label iPtr,
|
||||
const label& k
|
||||
)
|
||||
{
|
||||
const word& type = storageParams.compressionMethod()[iPtr];
|
||||
auto cstrIter = dictionaryConstructorTablePtr_->cfind(type);
|
||||
|
||||
if (!cstrIter.found())
|
||||
{
|
||||
FatalIOErrorInFunction(storageParams.dict())
|
||||
<< "Unknown compressedGeometricField type " << type << nl << nl
|
||||
<< "Valid compressedGeometricField types are :" << nl
|
||||
<< dictionaryConstructorTablePtr_->sortedToc()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
return autoPtr<compressedGeometricField<Type, PatchField, GeoMesh>>
|
||||
(cstrIter()( field, storageParams, iPtr, k ));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void compressedGeometricField<Type, PatchField, GeoMesh>::compress()
|
||||
{
|
||||
NotImplemented
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void compressedGeometricField<Type, PatchField, GeoMesh>::decompress
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
)
|
||||
{
|
||||
NotImplemented
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void compressedGeometricField<Type, PatchField, GeoMesh>::decompress()
|
||||
{
|
||||
this->decompress(field_);
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
const word& compressedGeometricField<Type, PatchField, GeoMesh>::name() const
|
||||
{
|
||||
return field_.name();
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
const scalarList&
|
||||
compressedGeometricField<Type, PatchField, GeoMesh>::storageMetrics() const
|
||||
{
|
||||
return storageMetrics_;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,354 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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
|
||||
compressedGeometricField
|
||||
|
||||
Description
|
||||
Base class for compression and decompression of the primal fields
|
||||
|
||||
SourceFiles
|
||||
compressedGeometricField.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef compressedGeometricField_H
|
||||
#define compressedGeometricField_H
|
||||
|
||||
#include "GeometricField.H"
|
||||
#include "fieldTypes.H"
|
||||
#include "storageParameters.H"
|
||||
#include "typeInfo.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class compressedGeometricField Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
class compressedGeometricField
|
||||
{
|
||||
static label counter;
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- No copy construct
|
||||
compressedGeometricField(const compressedGeometricField&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const compressedGeometricField&) = delete;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Reference to the field to be compressed,
|
||||
//- i.e. the field used from primalSolver
|
||||
GeometricField<Type, PatchField, GeoMesh>& field_;
|
||||
|
||||
//- Name of the field to be compressed
|
||||
const label iPtr_;
|
||||
|
||||
const dictionary dict_;
|
||||
const fvMesh& mesh_;
|
||||
|
||||
//- Is the first non-empty direction
|
||||
label validCompon_;
|
||||
|
||||
//- Current S/N of the time-step that is compressed in the present
|
||||
//- object
|
||||
const label& k_;
|
||||
|
||||
//- Reference to the compression parameters
|
||||
storageParameters& storageParams_;
|
||||
|
||||
//- Are all unnecessary actions are avoided to benchmark the code?
|
||||
const bool timing_;
|
||||
|
||||
//- The vector of solved-for directions in mesh.
|
||||
// 1 indicates valid direction and -1 an invalid direction.
|
||||
const Vector<label>& solDirs_;
|
||||
|
||||
//- Per patch, whether to store/compress fields using the
|
||||
//- appropriate algorithm.
|
||||
// Patches with uniform BCs, if a single value is chosen to be
|
||||
// stored for them, have a false value
|
||||
boolList toBeStored_;
|
||||
|
||||
//- Per patch of a surfaceScalarField, whether they must be zeroed
|
||||
//- upon retrieval.
|
||||
// To do so a zero value is stored for each of them.
|
||||
boolList surfacePatchesToBeZeroed_;
|
||||
|
||||
//- Per patch, whether to store/compress fields using the
|
||||
//- appropriate algorithm, irrespective of storing a uniform or
|
||||
//- non-uniform value
|
||||
boolList toBeStoredUniformOrNot_;
|
||||
|
||||
//- Threshold to avoid division with Zero
|
||||
scalar eps_;
|
||||
|
||||
//- List holding all of the storageMetrics information
|
||||
scalarList storageMetrics_;
|
||||
|
||||
//- Initial memory size of the field
|
||||
scalar& initialSize_;
|
||||
|
||||
//- Initial memory size of the part of the field, which will be stored
|
||||
// (e.g. excluding the coupled patches)
|
||||
scalar& uncompressedRoughSize_;
|
||||
|
||||
//- Initial memory size of the part of the field that is sent to Zfp
|
||||
//- compressor.
|
||||
// It may be larger than uncompressedRoughSize_, if
|
||||
// rearrangementType=2 and meshMode_=1. Needed to compute the pure
|
||||
// compression ratio of zfp.
|
||||
scalar& uncompressedSize_;
|
||||
|
||||
//- Compressed memory size of the field
|
||||
scalar& compressedSize_;
|
||||
|
||||
//- Total size of elements at all lists to be compressed
|
||||
label totalSize_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Fill in uniformBoundaryValuePtr_ with the uniform boundary field
|
||||
//- values
|
||||
virtual void storeUniformBoundaryValues() = 0;
|
||||
|
||||
//- Restore the uniform boundary field values based on what is stored
|
||||
//- in uniformBoundaryValuePtr_
|
||||
virtual void restoreUniformBoundaryValues
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
) = 0;
|
||||
|
||||
//- Const and non-const function to return a reference to
|
||||
//- field[pos][componI] for a vectorField and to field[pos] for a
|
||||
//- scalarField
|
||||
inline scalar& getValue
|
||||
(
|
||||
Field<Type>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const;
|
||||
|
||||
inline const scalar& getValue
|
||||
(
|
||||
const Field<Type>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const;
|
||||
|
||||
//- Const and non-const function to return a reference to
|
||||
//- field[pos][componI] for a List<vector> and to field[pos] for a
|
||||
//- List<scalar>
|
||||
inline scalar& getValue
|
||||
(
|
||||
List<Type>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const;
|
||||
|
||||
inline const scalar& getValue
|
||||
(
|
||||
const List<Type>& field,
|
||||
const label& pos,
|
||||
const label& componI
|
||||
) const;
|
||||
|
||||
//- Fill in toBeSorted_ which defines if the scalarField component of
|
||||
//- a boundary condition must be stored or not, per patch
|
||||
// (empty, coupled and zero sized patches do not get stored)
|
||||
virtual void toBeStored();
|
||||
|
||||
//- Since partial template specialization is not allowed,
|
||||
//- define two different functions with the same arguments
|
||||
//- and specialize checks there
|
||||
void checkFvsPatchFieldStorage
|
||||
(
|
||||
const PatchField<Type>& patchField,
|
||||
const label pI
|
||||
);
|
||||
|
||||
void checkFvPatchFieldStorage
|
||||
(
|
||||
const PatchField<Type>& patchField,
|
||||
const label patchI
|
||||
);
|
||||
|
||||
//- Compute initial size of the field to be compressed
|
||||
void computeSize();
|
||||
|
||||
//- Construct a list containing all of the compression metrics
|
||||
void gatherStorageMetrics();
|
||||
|
||||
//- Set a valid solution direction
|
||||
void setValidComponent();
|
||||
|
||||
//- Called before correcting the BCs
|
||||
// The function is specialized for the different geometric fields.
|
||||
inline void handleParticularities
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
);
|
||||
|
||||
//- Correct boundary conditions of coupled patches.
|
||||
// The function is specialized for the different geometric fields.
|
||||
inline void correctBCs
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("compressedGeometricField");
|
||||
|
||||
// Declare run-time constructor selection tables
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
compressedGeometricField,
|
||||
dictionary,
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
storageParameters& storageParams,
|
||||
const label iPtr,
|
||||
const label& k
|
||||
),
|
||||
(field, storageParams, iPtr, k)
|
||||
);
|
||||
|
||||
|
||||
// Constructors
|
||||
compressedGeometricField
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
storageParameters& storageParams,
|
||||
const label iPtr,
|
||||
const label& k
|
||||
);
|
||||
|
||||
|
||||
// Destructors
|
||||
virtual ~compressedGeometricField() = default;
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Return a pointer to a new compressedGeometricField
|
||||
static autoPtr<compressedGeometricField<Type, PatchField, GeoMesh>> New
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
storageParameters& storageParams,
|
||||
const label iPtr,
|
||||
const label& k
|
||||
);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Compress the field
|
||||
virtual void compress();
|
||||
|
||||
//- Decompress the field
|
||||
virtual void decompress
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
);
|
||||
|
||||
void decompress();
|
||||
|
||||
const word& name() const;
|
||||
|
||||
//- Get a const reference to the compression metrics
|
||||
virtual const scalarList& storageMetrics() const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "compressedGeometricField.C"
|
||||
#endif
|
||||
|
||||
|
||||
// Add the patch constructor functions to the hash tables
|
||||
|
||||
#define makeCompressedGeometricTypeField(SS, Type, PatchField, GeoMesh) \
|
||||
typedef SS<Type, PatchField, GeoMesh> \
|
||||
SS##Type##PatchField##GeoMesh##_; \
|
||||
\
|
||||
defineNamedTemplateTypeNameAndDebug \
|
||||
(SS##Type##PatchField##GeoMesh##_, 0); \
|
||||
\
|
||||
compressedGeometricField<Type, PatchField, GeoMesh> \
|
||||
::adddictionaryConstructorToTable<SS<Type, PatchField, GeoMesh>> \
|
||||
add##SS##Type##PatchField##GeoMesh##dictionaryConstructorToTable_; \
|
||||
|
||||
#define makeCompressedGeometricTypeFieldNoAdd(SS, Type, PatchField, GeoMesh) \
|
||||
typedef SS<Type, PatchField, GeoMesh> \
|
||||
SS##Type##PatchField##GeoMesh##_; \
|
||||
\
|
||||
defineNamedTemplateTypeNameAndDebug \
|
||||
(SS##Type##PatchField##GeoMesh##_, 0);
|
||||
|
||||
#define makeCompressedGeometricField(SS) \
|
||||
\
|
||||
makeCompressedGeometricTypeField(SS, scalar, fvPatchField, volMesh) \
|
||||
makeCompressedGeometricTypeField(SS, scalar, fvsPatchField, surfaceMesh) \
|
||||
makeCompressedGeometricTypeField(SS, vector, fvPatchField, volMesh)
|
||||
|
||||
#define makeCompressedGeometricFieldNoAdd(SS) \
|
||||
\
|
||||
makeCompressedGeometricTypeFieldNoAdd(SS, scalar, fvPatchField, volMesh) \
|
||||
makeCompressedGeometricTypeFieldNoAdd(SS, scalar, fvsPatchField, surfaceMesh) \
|
||||
makeCompressedGeometricTypeFieldNoAdd(SS, vector, fvPatchField, volMesh)
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,51 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Released 2004-2011 OpenCFD Ltd.
|
||||
Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
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 "compressedGeometricFields.H"
|
||||
#include "HashTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
// Define the constructor function hash tables
|
||||
|
||||
defineNamedTemplateTypeNameAndDebug(compressedVolScalarField, 0);
|
||||
defineTemplateRunTimeSelectionTable(compressedVolScalarField, dictionary);
|
||||
|
||||
defineNamedTemplateTypeNameAndDebug(compressedSurfaceScalarField, 0);
|
||||
defineTemplateRunTimeSelectionTable(compressedSurfaceScalarField, dictionary);
|
||||
|
||||
defineNamedTemplateTypeNameAndDebug(compressedVolVectorField, 0);
|
||||
defineTemplateRunTimeSelectionTable(compressedVolVectorField, dictionary);
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Released 2004-2011 OpenCFD Ltd.
|
||||
Copyright (C) 2011 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef compressedGeometricFields_H
|
||||
#define compressedGeometricFields_H
|
||||
|
||||
#include "compressedGeometricField.H"
|
||||
#include "compressedGeometricFieldsFwd.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,61 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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
|
||||
compressedGeometricField
|
||||
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef compressedGeometricFieldsFwd_H
|
||||
#define compressedGeometricFieldsFwd_H
|
||||
|
||||
#include "fieldTypes.H"
|
||||
#include "fvPatchField.H"
|
||||
#include "wordList.H"
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
class compressedGeometricField;
|
||||
|
||||
typedef compressedGeometricField<scalar, fvPatchField, volMesh> compressedVolScalarField;
|
||||
typedef compressedGeometricField<scalar, fvsPatchField, surfaceMesh> compressedSurfaceScalarField;
|
||||
typedef compressedGeometricField<vector, fvPatchField, volMesh> compressedVolVectorField;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,254 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "shortGeometricField.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void
|
||||
shortGeometricField<Type, PatchField, GeoMesh>::storeUniformBoundaryValues()
|
||||
{
|
||||
forAll(uniformBoundaryValuePtr_, pI)
|
||||
{
|
||||
const Field<Type>& boundaryField = this->field_.boundaryField()[pI];
|
||||
if (this->toBeStoredUniformOrNot_[pI] && !this->toBeStored_[pI])
|
||||
{
|
||||
if
|
||||
(
|
||||
std::is_same<PatchField<Type>, fvsPatchField<Type>>::value
|
||||
&& this->surfacePatchesToBeZeroed_[pI]
|
||||
)
|
||||
{
|
||||
// At this point, the maximum magnitude of the boundaryField is
|
||||
// for sure below the prescribed threshold
|
||||
uniformBoundaryValuePtr_.set(pI, new Type(Zero));
|
||||
}
|
||||
else
|
||||
{
|
||||
uniformBoundaryValuePtr_.set
|
||||
(
|
||||
pI, new Type(boundaryField.first())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void
|
||||
shortGeometricField<Type, PatchField, GeoMesh>::restoreUniformBoundaryValues
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
)
|
||||
{
|
||||
forAll(uniformBoundaryValuePtr_, pI)
|
||||
{
|
||||
Field<Type>& boundaryField = field.boundaryFieldRef()[pI];
|
||||
if (uniformBoundaryValuePtr_(pI))
|
||||
{
|
||||
boundaryField = uniformBoundaryValuePtr_[pI];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void shortGeometricField<Type, PatchField, GeoMesh>::initialize()
|
||||
{
|
||||
this->toBeStored();
|
||||
this->computeSize();
|
||||
this->uncompressedSize_ = this->uncompressedRoughSize_;
|
||||
this->compressedSize_ = this->uncompressedRoughSize_;
|
||||
setBuffers();
|
||||
storeUniformBoundaryValues();
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void shortGeometricField<Type, PatchField, GeoMesh>::setBuffers()
|
||||
{
|
||||
const Field<Type>& internalField = this->field_.primitiveField();
|
||||
forAll(internalBufferPtr_, cmptI)
|
||||
{
|
||||
if (this->solDirs_[cmptI])
|
||||
{
|
||||
internalBufferPtr_[cmptI].setSize(internalField.size());
|
||||
}
|
||||
}
|
||||
forAll (boundaryBufferPtr_, pI)
|
||||
{
|
||||
if (this->toBeStored_[pI])
|
||||
{
|
||||
boundaryBufferPtr_[pI].setSize(pTraits<Type>::nComponents);
|
||||
const Field<Type>& boundaryField = this->field_.boundaryField()[pI];
|
||||
forAll(boundaryBufferPtr_[pI], cmptI)
|
||||
{
|
||||
if (this->solDirs_[cmptI])
|
||||
{
|
||||
boundaryBufferPtr_[pI][cmptI].setSize(boundaryField.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
shortGeometricField<Type, PatchField, GeoMesh>::shortGeometricField
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
storageParameters& storageParams,
|
||||
const label iPtr,
|
||||
const label& k
|
||||
):
|
||||
compressedGeometricField<Type, PatchField, GeoMesh>
|
||||
(
|
||||
field,
|
||||
storageParams,
|
||||
iPtr,
|
||||
k
|
||||
),
|
||||
internalBufferPtr_(pTraits<Type>::nComponents),
|
||||
boundaryBufferPtr_(field.mesh().boundary().size()),
|
||||
uniformBoundaryValuePtr_(field.mesh().boundary().size())
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void shortGeometricField<Type, PatchField, GeoMesh>::compress()
|
||||
{
|
||||
const Field<Type>& internalField = this->field_.primitiveField();
|
||||
forAll(internalBufferPtr_, cmptI)
|
||||
{
|
||||
if (this->solDirs_[cmptI])
|
||||
{
|
||||
forAll(internalBufferPtr_[cmptI], iPtr)
|
||||
{
|
||||
internalBufferPtr_[cmptI][iPtr] =
|
||||
this->getValue(internalField, iPtr, cmptI);
|
||||
}
|
||||
}
|
||||
}
|
||||
forAll(boundaryBufferPtr_, pI)
|
||||
{
|
||||
if (this->toBeStored_[pI])
|
||||
{
|
||||
const Field<Type>& boundaryField = this->field_.boundaryField()[pI];
|
||||
for (label cmptI = 0; cmptI < pTraits<Type>::nComponents; ++cmptI)
|
||||
{
|
||||
if (this->solDirs_[cmptI])
|
||||
{
|
||||
forAll(boundaryBufferPtr_[pI][cmptI], iPtr)
|
||||
{
|
||||
boundaryBufferPtr_[pI][cmptI][iPtr] =
|
||||
this->getValue(boundaryField, iPtr, cmptI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this->gatherStorageMetrics();
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void shortGeometricField<Type, PatchField, GeoMesh>::decompress
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
)
|
||||
{
|
||||
Field<Type>& internalField = field.primitiveFieldRef();
|
||||
forAll(internalBufferPtr_, cmptI)
|
||||
{
|
||||
if (this->solDirs_[cmptI])
|
||||
{
|
||||
forAll(internalBufferPtr_[cmptI], iPtr)
|
||||
{
|
||||
scalar& val = this->getValue(internalField, iPtr, cmptI);
|
||||
val = internalBufferPtr_[cmptI][iPtr];
|
||||
}
|
||||
}
|
||||
/*else
|
||||
{
|
||||
forAll(internalBufferPtr_[cmptI], iPtr)
|
||||
{
|
||||
scalar& val = this->getValue(internalField, iPtr, cmptI);
|
||||
val = 0;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
forAll(boundaryBufferPtr_, pI)
|
||||
{
|
||||
if (this->toBeStored_[pI])
|
||||
{
|
||||
Field<Type>& boundaryField = field.boundaryFieldRef()[pI];
|
||||
for (label cmptI = 0; cmptI < pTraits<Type>::nComponents; ++cmptI)
|
||||
{
|
||||
if (this->solDirs_[cmptI])
|
||||
{
|
||||
forAll(boundaryBufferPtr_[pI][cmptI], iPtr)
|
||||
{
|
||||
scalar& val =
|
||||
this->getValue(boundaryField, iPtr, cmptI);
|
||||
val = boundaryBufferPtr_[pI][cmptI][iPtr];
|
||||
}
|
||||
}
|
||||
/*else
|
||||
{
|
||||
forAll (boundaryBufferPtr_[pI], iPtr)
|
||||
{
|
||||
scalar& val = this->getValue(boundaryField, iPtr, cmptI);
|
||||
val = 0;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
this->restoreUniformBoundaryValues(field);
|
||||
this->correctBCs(field);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,142 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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
|
||||
shortGeometricField
|
||||
|
||||
Description
|
||||
Stores only the current state of a GeometricField (i.e. not oldTimes).
|
||||
Additionally, avoids storing patchFields that can be retrieved through
|
||||
correctBoundaryConditions (e.g. uniform fields, coupled, symmetry, etc)
|
||||
|
||||
SourceFiles
|
||||
shortGeometricField.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef shortGeometricField_H
|
||||
#define shortGeometricField_H
|
||||
|
||||
#include "compressedGeometricField.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class shortGeometricField Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
class shortGeometricField
|
||||
:
|
||||
public compressedGeometricField<Type, PatchField, GeoMesh>
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Storage of the internalField deceomposed into multiple
|
||||
//- scalarFields
|
||||
List<scalarField> internalBufferPtr_;
|
||||
|
||||
//- Storage of the boundaryField deceomposed into multiple
|
||||
//- scalarFields per patch
|
||||
List<List<scalarField>> boundaryBufferPtr_;
|
||||
|
||||
//- Holds the uniform value for patches with such boundary conditions.
|
||||
// Allocated only on these patches
|
||||
PtrList<Type> uniformBoundaryValuePtr_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Fill in uniformBoundaryValuePtr_ with the uniform boundary field
|
||||
//- values
|
||||
void storeUniformBoundaryValues() override;
|
||||
|
||||
//- Restore the uniform boundary field values based on what is stored
|
||||
//- in uniformBoundaryValuePtr_
|
||||
void restoreUniformBoundaryValues
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
) override;
|
||||
|
||||
//- Initialize necessary parameters
|
||||
void initialize();
|
||||
|
||||
//- Set sizes for internalBufferPtr_ and boundaryBufferPtr_
|
||||
void setBuffers();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("shortGeometricField");
|
||||
|
||||
|
||||
// Constructors
|
||||
shortGeometricField
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
storageParameters& storageParams,
|
||||
const label iPtr,
|
||||
const label& k
|
||||
);
|
||||
|
||||
|
||||
// Destructors
|
||||
virtual ~shortGeometricField() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Store field
|
||||
void compress() override;
|
||||
|
||||
//- Retrieve field
|
||||
void decompress
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
) override;
|
||||
};
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "shortGeometricField.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,45 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "shortGeometricField.H"
|
||||
#include "HashTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
makeCompressedGeometricField(shortGeometricField)
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
||||
Copyright (C) 2013-2021 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019-2021 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -67,7 +67,8 @@ objectiveManager::objectiveManager
|
||||
adjointSolverName_(adjointSolverName),
|
||||
primalSolverName_(primalSolverName),
|
||||
objectives_(0),
|
||||
weigthedObjectiveFile_(nullptr)
|
||||
weigthedObjectiveFile_(nullptr),
|
||||
hasIntegrationTimes_(true)
|
||||
{
|
||||
// Construct objectives
|
||||
//~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -182,6 +183,12 @@ bool objectiveManager::readDict(const dictionary& dict)
|
||||
}
|
||||
|
||||
|
||||
bool objectiveManager::hasIntegrationTimes() const
|
||||
{
|
||||
return hasIntegrationTimes_;
|
||||
}
|
||||
|
||||
|
||||
void objectiveManager::updateNormalizationFactor()
|
||||
{
|
||||
// Update normalization factors for all objectives
|
||||
@ -252,6 +259,24 @@ scalar objectiveManager::print()
|
||||
}
|
||||
|
||||
|
||||
void objectiveManager::setWrite(const bool shouldWrite)
|
||||
{
|
||||
for (objective& obj : objectives_)
|
||||
{
|
||||
obj.setWrite(shouldWrite);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void objectiveManager::setWriteOption(IOobject::writeOption w)
|
||||
{
|
||||
for (objective& obj : objectives_)
|
||||
{
|
||||
obj.setWriteOption(w);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool objectiveManager::writeObjectives
|
||||
(
|
||||
const scalar weightedObjective,
|
||||
@ -261,8 +286,8 @@ bool objectiveManager::writeObjectives
|
||||
for (const objective& obj : objectives_)
|
||||
{
|
||||
// Write objective function to file
|
||||
obj.write();
|
||||
obj.writeMeanValue();
|
||||
obj.write();
|
||||
obj.writeMeanValue();
|
||||
}
|
||||
|
||||
if (weigthedObjectiveFile_.valid())
|
||||
@ -317,16 +342,13 @@ const word& objectiveManager::primalSolverName() const
|
||||
}
|
||||
|
||||
|
||||
void objectiveManager::checkIntegrationTimes() const
|
||||
void objectiveManager::checkIntegrationTimes()
|
||||
{
|
||||
for (const objective& obj : objectives_)
|
||||
{
|
||||
if (!obj.hasIntegrationStartTime() || !obj.hasIntegrationEndTime())
|
||||
{
|
||||
FatalErrorInFunction()
|
||||
<< "Objective function " << obj.objectiveName()
|
||||
<< " does not have a defined integration start or end time "
|
||||
<< exit(FatalError);
|
||||
hasIntegrationTimes_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
||||
Copyright (C) 2013-2021 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -66,6 +66,7 @@ protected:
|
||||
const word primalSolverName_;
|
||||
PtrList<objective> objectives_;
|
||||
autoPtr<OFstream> weigthedObjectiveFile_;
|
||||
bool hasIntegrationTimes_;
|
||||
|
||||
|
||||
private:
|
||||
@ -130,6 +131,12 @@ public:
|
||||
|
||||
virtual bool readDict(const dictionary& dict);
|
||||
|
||||
//- Boolean defining if all objectives have defined their integration
|
||||
// window.
|
||||
// false if at least one of the objectives has an undefined
|
||||
// integration window
|
||||
bool hasIntegrationTimes() const;
|
||||
|
||||
//- Update objective function related values
|
||||
void updateNormalizationFactor();
|
||||
|
||||
@ -145,6 +152,12 @@ public:
|
||||
//- Print to screen
|
||||
scalar print();
|
||||
|
||||
//- Set write option for objectives (files in the optimisation folder)
|
||||
void setWrite(const bool shouldWrite);
|
||||
|
||||
//- Set write option for the localIOdictionary base of the objectives
|
||||
void setWriteOption(IOobject::writeOption w);
|
||||
|
||||
//- Write objective function history
|
||||
virtual bool writeObjectives
|
||||
(
|
||||
@ -172,7 +185,7 @@ public:
|
||||
const word& primalSolverName() const;
|
||||
|
||||
//- Check integration times for unsteady runs
|
||||
void checkIntegrationTimes() const;
|
||||
void checkIntegrationTimes();
|
||||
|
||||
//- Add contribution to adjoint momentum PDEs
|
||||
virtual void addUaEqnSource(fvVectorMatrix& UaEqn) = 0;
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
||||
Copyright (C) 2013-2020 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019-2021 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -131,6 +131,7 @@ objective::objective
|
||||
computeMeanFields_(false), // is reset in derived classes
|
||||
nullified_(false),
|
||||
normalize_(dict.getOrDefault<bool>("normalize", false)),
|
||||
shouldWrite_(true),
|
||||
|
||||
J_(Zero),
|
||||
JMean_(this->getOrDefault<scalar>("JMean", Zero)),
|
||||
@ -172,14 +173,22 @@ objective::objective
|
||||
{
|
||||
integrationStartTimePtr_.reset
|
||||
(
|
||||
new scalar(dict.get<scalar>("integrationStartTime"))
|
||||
new scalar
|
||||
(
|
||||
dict.get<scalar>("integrationStartTime") +
|
||||
mesh_.time().value()
|
||||
)
|
||||
);
|
||||
}
|
||||
if (dict.found("integrationEndTime"))
|
||||
{
|
||||
integrationEndTimePtr_.reset
|
||||
(
|
||||
new scalar(dict.get<scalar>("integrationEndTime"))
|
||||
new scalar
|
||||
(
|
||||
dict.get<scalar>("integrationEndTime") +
|
||||
mesh_.time().value()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -299,17 +308,22 @@ void objective::accumulateJMean(solverControl& solverControl)
|
||||
}
|
||||
|
||||
|
||||
void objective::resetJMean()
|
||||
{
|
||||
JMean_ = 0;
|
||||
}
|
||||
|
||||
|
||||
void objective::accumulateJMean()
|
||||
{
|
||||
if (hasIntegrationStartTime() && hasIntegrationEndTime())
|
||||
{
|
||||
const scalar time = mesh_.time().value();
|
||||
if (isWithinIntegrationTime())
|
||||
{
|
||||
const scalar dt = mesh_.time().deltaT().value();
|
||||
const scalar elapsedTime = time - integrationStartTimePtr_();
|
||||
const scalar denom = elapsedTime + dt;
|
||||
JMean_ = (JMean_*elapsedTime + J_*dt)/denom;
|
||||
const scalar dt = mesh_.time().deltaTValue();
|
||||
const scalar elapsedTime
|
||||
= mesh_.time().value() - integrationStartTimePtr_();
|
||||
JMean_ = (JMean_*elapsedTime + J_*dt)/(elapsedTime + dt);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -384,10 +398,11 @@ bool objective::isWithinIntegrationTime() const
|
||||
if (hasIntegrationStartTime() && hasIntegrationEndTime())
|
||||
{
|
||||
const scalar time = mesh_.time().value();
|
||||
const scalar dt = mesh_.time().deltaTValue();
|
||||
return
|
||||
(
|
||||
time >= integrationStartTimePtr_()
|
||||
&& time <= integrationEndTimePtr_()
|
||||
time >= (integrationStartTimePtr_() - 0.1*dt)
|
||||
&& time <= (integrationEndTimePtr_() + 1.1*dt)
|
||||
);
|
||||
}
|
||||
else
|
||||
@ -413,6 +428,8 @@ void objective::incrementIntegrationTimes(const scalar timeSpan)
|
||||
<< "Unallocated integration start or end time"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
// Set nullified_ to false for the next optimization cycle
|
||||
nullified_ = false;
|
||||
}
|
||||
|
||||
|
||||
@ -659,7 +676,7 @@ void objective::nullify()
|
||||
|
||||
bool objective::write(const bool valid) const
|
||||
{
|
||||
if (Pstream::master())
|
||||
if (Pstream::master() && shouldWrite_)
|
||||
{
|
||||
// File is opened only upon invocation of the write function
|
||||
// in order to avoid various instantiations of the same objective
|
||||
@ -732,7 +749,7 @@ void objective::writeInstantaneousSeparator() const
|
||||
|
||||
void objective::writeMeanValue() const
|
||||
{
|
||||
if (Pstream::master())
|
||||
if (Pstream::master() && shouldWrite_)
|
||||
{
|
||||
// Write mean value if necessary
|
||||
// Covers both steady and unsteady runs
|
||||
@ -742,8 +759,8 @@ void objective::writeMeanValue() const
|
||||
|| (hasIntegrationStartTime() && hasIntegrationEndTime())
|
||||
)
|
||||
{
|
||||
// File is opened only upon invocation of the write function
|
||||
// in order to avoid various instantiations of the same objective
|
||||
// File is opened only upon invocation of the write function in
|
||||
// order to avoid various instantiations of the same objective
|
||||
// opening the same file
|
||||
if (!meanValueFilePtr_)
|
||||
{
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
||||
Copyright (C) 2013-2020 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -73,6 +73,7 @@ protected:
|
||||
bool computeMeanFields_;
|
||||
bool nullified_;
|
||||
bool normalize_;
|
||||
bool shouldWrite_;
|
||||
|
||||
//- Objective function value and weight
|
||||
scalar J_;
|
||||
@ -253,6 +254,9 @@ public:
|
||||
// For unsteady runs
|
||||
void accumulateJMean();
|
||||
|
||||
//- Nullify JMean. To be used in unsteady optimization.
|
||||
void resetJMean();
|
||||
|
||||
//- Return the objective function weight
|
||||
scalar weight() const;
|
||||
|
||||
@ -392,6 +396,15 @@ public:
|
||||
//- Return the objective name
|
||||
inline const word& objectiveName() const;
|
||||
|
||||
//- Should the objective be written to file upon calling write()?
|
||||
inline bool shouldWrite() const;
|
||||
|
||||
//- Set the shouldWrite_ flag (files in the optimisation folder)
|
||||
inline void setWrite(const bool shouldWrite);
|
||||
|
||||
//- Set the write option of the base localIOdictionary
|
||||
inline void setWriteOption(IOobject::writeOption w);
|
||||
|
||||
// Inline functions for checking whether pointers are set or not
|
||||
inline bool hasdJdb() const;
|
||||
inline bool hasBoundarydJdb() const;
|
||||
|
||||
@ -36,6 +36,24 @@ inline const Foam::word& Foam::objective::objectiveName() const
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::objective::shouldWrite() const
|
||||
{
|
||||
return shouldWrite_;
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::objective::setWrite(const bool shouldWrite)
|
||||
{
|
||||
shouldWrite_ = shouldWrite;
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::objective::setWriteOption(IOobject::writeOption w)
|
||||
{
|
||||
IOobject::writeOpt() = w;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::objective::hasdJdb() const
|
||||
{
|
||||
return bool(dJdbPtr_);
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
||||
Copyright (C) 2013-2019 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019-2021 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -38,28 +38,137 @@ namespace Foam
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::optimisationManager::optimisationManager(fvMesh& mesh)
|
||||
:
|
||||
IOdictionary
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"optimisationDict",
|
||||
mesh.time().system(),
|
||||
mesh,
|
||||
IOobject::MUST_READ_IF_MODIFIED,
|
||||
IOobject::NO_WRITE,
|
||||
true
|
||||
)
|
||||
),
|
||||
mesh_(mesh),
|
||||
time_(const_cast<Time&>(mesh.time())),
|
||||
primalSolvers_(),
|
||||
adjointSolverManagers_(),
|
||||
managerType_(get<word>("optimisationManager")),
|
||||
optType_(nullptr)
|
||||
void Foam::optimisationManager::resetTime()
|
||||
{
|
||||
// Does nothing in base
|
||||
}
|
||||
|
||||
|
||||
void Foam::optimisationManager::lineSearchUpdate()
|
||||
{
|
||||
// Compute direction of update
|
||||
tmp<scalarField> tdirection = optType_->computeDirection();
|
||||
scalarField& direction = tdirection.ref();
|
||||
|
||||
// Grab reference to line search
|
||||
autoPtr<lineSearch>& lineSrch = optType_->getLineSearch();
|
||||
|
||||
// Store starting point
|
||||
optType_->storeDesignVariables();
|
||||
|
||||
// Compute merit function before update
|
||||
scalar meritFunction = optType_->computeMeritFunction();
|
||||
lineSrch->setOldMeritValue(meritFunction);
|
||||
|
||||
// Get merit function derivative
|
||||
const scalar dirDerivative =
|
||||
optType_->meritFunctionDirectionalDerivative();
|
||||
lineSrch->setDeriv(dirDerivative);
|
||||
lineSrch->setDirection(direction);
|
||||
|
||||
// Reset initial step.
|
||||
// Might be interpolated from previous optimisation cycles
|
||||
lineSrch->reset();
|
||||
|
||||
// Perform line search
|
||||
for (label iter = 0; iter < lineSrch->maxIters(); ++iter)
|
||||
{
|
||||
Info<< "\n- - - - - - - - - - - - - - -" << endl;
|
||||
Info<< "Line search iteration " << iter << endl;
|
||||
Info<< "- - - - - - - - - - - - - - -\n" << endl;
|
||||
|
||||
// Update design variables. Multiplication with line search step
|
||||
// happens inside the update(direction) function
|
||||
moveDesignVariables(direction);
|
||||
|
||||
// Solve all primal equations
|
||||
solvePrimalEquations();
|
||||
|
||||
// Compute and set new merit function
|
||||
meritFunction = optType_->computeMeritFunction();
|
||||
lineSrch->setNewMeritValue(meritFunction);
|
||||
|
||||
if (lineSrch->converged())
|
||||
{
|
||||
// If line search criteria have been met, proceed
|
||||
Info<< "Line search converged in " << iter + 1
|
||||
<< " iterations." << endl;
|
||||
scalarField scaledCorrection(lineSrch->step()*direction);
|
||||
optType_->updateOldCorrection(scaledCorrection);
|
||||
optType_->write();
|
||||
lineSrch()++;
|
||||
postUpdate();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If maximum number of iteration has been reached, continue
|
||||
if (iter == lineSrch->maxIters() - 1)
|
||||
{
|
||||
Info<< "Line search reached max. number of iterations.\n"
|
||||
<< "Proceeding to the next optimisation cycle" << endl;
|
||||
scalarField scaledCorrection(lineSrch->step()*direction);
|
||||
optType_->updateOldCorrection(scaledCorrection);
|
||||
optType_->write();
|
||||
lineSrch()++;
|
||||
postUpdate();
|
||||
}
|
||||
// Reset to initial design variables and update step
|
||||
else
|
||||
{
|
||||
resetTime();
|
||||
optType_->resetDesignVariables();
|
||||
lineSrch->updateStep();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::optimisationManager::fixedStepUpdate()
|
||||
{
|
||||
moveDesignVariables();
|
||||
|
||||
// Solve primal equations
|
||||
solvePrimalEquations();
|
||||
postUpdate();
|
||||
}
|
||||
|
||||
|
||||
void Foam::optimisationManager::postUpdate()
|
||||
{
|
||||
for (primalSolver& solver : primalSolvers_)
|
||||
{
|
||||
solver.postLineSearch();
|
||||
}
|
||||
|
||||
for (adjointSolverManager& manager : adjointSolverManagers_)
|
||||
{
|
||||
manager.postLineSearch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::optimisationManager::moveDesignVariables()
|
||||
{
|
||||
// Update design variables
|
||||
optType_->update();
|
||||
}
|
||||
|
||||
|
||||
void Foam::optimisationManager::moveDesignVariables
|
||||
(
|
||||
scalarField& direction
|
||||
)
|
||||
{
|
||||
// Update design variables
|
||||
optType_->update(direction);
|
||||
}
|
||||
|
||||
|
||||
void Foam::optimisationManager::initialize()
|
||||
{
|
||||
dictionary& primalSolversDict = subDict("primalSolvers");
|
||||
const wordList& primalSolverNames = primalSolversDict.toc();
|
||||
@ -79,7 +188,7 @@ Foam::optimisationManager::optimisationManager(fvMesh& mesh)
|
||||
solveri,
|
||||
primalSolver::New
|
||||
(
|
||||
mesh,
|
||||
mesh_,
|
||||
managerType_,
|
||||
solverDict
|
||||
)
|
||||
@ -100,7 +209,7 @@ Foam::optimisationManager::optimisationManager(fvMesh& mesh)
|
||||
manageri,
|
||||
new adjointSolverManager
|
||||
(
|
||||
mesh,
|
||||
mesh_,
|
||||
managerType_,
|
||||
adjointManagersDict.subDict(adjointManagerNames[manageri]),
|
||||
overrideUseSolverName
|
||||
@ -148,6 +257,33 @@ Foam::optimisationManager::optimisationManager(fvMesh& mesh)
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::optimisationManager::optimisationManager(fvMesh& mesh)
|
||||
:
|
||||
IOdictionary
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"optimisationDict",
|
||||
mesh.time().system(),
|
||||
mesh,
|
||||
IOobject::MUST_READ_IF_MODIFIED,
|
||||
IOobject::NO_WRITE,
|
||||
true
|
||||
)
|
||||
),
|
||||
mesh_(mesh),
|
||||
time_(const_cast<Time&>(mesh.time())),
|
||||
primalSolvers_(),
|
||||
adjointSolverManagers_(),
|
||||
managerType_(get<word>("optimisationManager")),
|
||||
optType_(nullptr),
|
||||
shouldUpdateDesignVariables_(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::optimisationManager> Foam::optimisationManager::New
|
||||
@ -215,6 +351,24 @@ bool Foam::optimisationManager::read()
|
||||
}
|
||||
|
||||
|
||||
void Foam::optimisationManager::updateDesignVariables()
|
||||
{
|
||||
// Update design variables using either a line-search scheme or
|
||||
// a fixed-step update
|
||||
if (optType_->getLineSearch())
|
||||
{
|
||||
lineSearchUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
fixedStepUpdate();
|
||||
}
|
||||
|
||||
// Reset adjoint sensitivities in all adjoint solver managers
|
||||
clearSensitivities();
|
||||
}
|
||||
|
||||
|
||||
Foam::PtrList<Foam::primalSolver>& Foam::optimisationManager::primalSolvers()
|
||||
{
|
||||
return primalSolvers_;
|
||||
@ -230,10 +384,9 @@ Foam::optimisationManager::adjointSolverManagers()
|
||||
|
||||
void Foam::optimisationManager::solvePrimalEquations()
|
||||
{
|
||||
// Solve all primal equations
|
||||
forAll(primalSolvers_, psI)
|
||||
for (primalSolver& solver : primalSolvers_)
|
||||
{
|
||||
primalSolvers_[psI].solve();
|
||||
solver.solve();
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,9 +394,9 @@ void Foam::optimisationManager::solvePrimalEquations()
|
||||
void Foam::optimisationManager::solveAdjointEquations()
|
||||
{
|
||||
// Solve all adjoint solver equations
|
||||
forAll(adjointSolverManagers_, amI)
|
||||
for (adjointSolverManager& manager : adjointSolverManagers_)
|
||||
{
|
||||
adjointSolverManagers_[amI].solveAdjointEquations();
|
||||
manager.solveAdjointEquations();
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,6 +411,15 @@ void Foam::optimisationManager::computeSensitivities()
|
||||
}
|
||||
|
||||
|
||||
void Foam::optimisationManager::clearSensitivities()
|
||||
{
|
||||
for (adjointSolverManager& adjSolvManager : adjointSolverManagers_)
|
||||
{
|
||||
adjSolvManager.clearSensitivities();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::optimisationManager::updatePrimalBasedQuantities()
|
||||
{
|
||||
forAll(adjointSolverManagers_, amI)
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
||||
Copyright (C) 2013-2019 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2e22 FOSS GP
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -68,8 +68,37 @@ protected:
|
||||
PtrList<primalSolver> primalSolvers_;
|
||||
PtrList<adjointSolverManager> adjointSolverManagers_;
|
||||
const word managerType_;
|
||||
|
||||
autoPtr<incompressible::optimisationType> optType_;
|
||||
|
||||
Switch shouldUpdateDesignVariables_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
virtual void resetTime();
|
||||
|
||||
//- Update design variables
|
||||
virtual void moveDesignVariables();
|
||||
|
||||
//- Update design variables. Multiplication with line search step
|
||||
//- happens inside the update(direction) function
|
||||
virtual void moveDesignVariables
|
||||
(
|
||||
scalarField& direction
|
||||
);
|
||||
|
||||
//- Update design variables using a line-search
|
||||
void lineSearchUpdate();
|
||||
|
||||
//- Update design variables using a fixed step
|
||||
void fixedStepUpdate();
|
||||
|
||||
//- Actions performed after lineSearch has converged
|
||||
void postUpdate();
|
||||
|
||||
//- Initialization. Construct primal and adjoint solvers
|
||||
virtual void initialize();
|
||||
|
||||
private:
|
||||
|
||||
@ -145,7 +174,7 @@ public:
|
||||
//- Update design variables.
|
||||
// Might employ a line search to find a correction satisfying the step
|
||||
// convergence criteria
|
||||
virtual void updateDesignVariables() = 0;
|
||||
virtual void updateDesignVariables();
|
||||
|
||||
//- Solve all primal equations
|
||||
virtual void solvePrimalEquations();
|
||||
@ -156,6 +185,9 @@ public:
|
||||
//- Compute all adjoint sensitivities
|
||||
virtual void computeSensitivities();
|
||||
|
||||
//- Clear all adjoint sensitivities
|
||||
virtual void clearSensitivities();
|
||||
|
||||
//- Solve all primal equations
|
||||
virtual void updatePrimalBasedQuantities();
|
||||
};
|
||||
|
||||
@ -45,7 +45,9 @@ Foam::singleRun::singleRun(fvMesh& mesh)
|
||||
:
|
||||
optimisationManager(mesh),
|
||||
cycles_(Zero)
|
||||
{}
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
@ -66,102 +66,13 @@ void Foam::steadyOptimisation::updateOptTypeSource()
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::steadyOptimisation::lineSearchUpdate()
|
||||
{
|
||||
// Compute direction of update
|
||||
tmp<scalarField> tdirection = optType_->computeDirection();
|
||||
scalarField& direction = tdirection.ref();
|
||||
|
||||
// Grab reference to line search
|
||||
autoPtr<lineSearch>& lineSrch = optType_->getLineSearch();
|
||||
|
||||
// Store starting point
|
||||
optType_->storeDesignVariables();
|
||||
|
||||
// Compute merit function before update
|
||||
scalar meritFunction = optType_->computeMeritFunction();
|
||||
lineSrch->setOldMeritValue(meritFunction);
|
||||
|
||||
// Get merit function derivative
|
||||
const scalar dirDerivative =
|
||||
optType_->meritFunctionDirectionalDerivative();
|
||||
lineSrch->setDeriv(dirDerivative);
|
||||
lineSrch->setDirection(direction);
|
||||
|
||||
// Reset initial step.
|
||||
// Might be interpolated from previous optimisation cycles
|
||||
lineSrch->reset();
|
||||
|
||||
// Perform line search
|
||||
for (label iter = 0; iter < lineSrch->maxIters(); ++iter)
|
||||
{
|
||||
Info<< "\n- - - - - - - - - - - - - - -" << endl;
|
||||
Info<< "Line search iteration " << iter << endl;
|
||||
Info<< "- - - - - - - - - - - - - - -\n" << endl;
|
||||
|
||||
// Update design variables. Multiplication with line search step
|
||||
// happens inside the update(direction) function
|
||||
optType_->update(direction);
|
||||
|
||||
// Solve all primal equations
|
||||
solvePrimalEquations();
|
||||
|
||||
// Compute and set new merit function
|
||||
meritFunction = optType_->computeMeritFunction();
|
||||
lineSrch->setNewMeritValue(meritFunction);
|
||||
|
||||
if (lineSrch->converged())
|
||||
{
|
||||
// If line search criteria have been met, proceed
|
||||
Info<< "Line search converged in " << iter + 1
|
||||
<< " iterations." << endl;
|
||||
scalarField scaledCorrection(lineSrch->step()*direction);
|
||||
optType_->updateOldCorrection(scaledCorrection);
|
||||
optType_->write();
|
||||
lineSrch()++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If maximum number of iteration has been reached, continue
|
||||
if (iter == lineSrch->maxIters() - 1)
|
||||
{
|
||||
Info<< "Line search reached max. number of iterations.\n"
|
||||
<< "Proceeding to the next optimisation cycle" << endl;
|
||||
scalarField scaledCorrection(lineSrch->step()*direction);
|
||||
optType_->updateOldCorrection(scaledCorrection);
|
||||
optType_->write();
|
||||
lineSrch()++;
|
||||
}
|
||||
// Reset to initial design variables and update step
|
||||
else
|
||||
{
|
||||
optType_->resetDesignVariables();
|
||||
lineSrch->updateStep();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::steadyOptimisation::fixedStepUpdate()
|
||||
{
|
||||
// Update design variables
|
||||
optType_->update();
|
||||
|
||||
// Solve primal equations
|
||||
solvePrimalEquations();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::steadyOptimisation::steadyOptimisation(fvMesh& mesh)
|
||||
:
|
||||
optimisationManager(mesh)
|
||||
{
|
||||
initialize();
|
||||
optType_.reset
|
||||
(
|
||||
incompressible::optimisationType::New
|
||||
@ -221,25 +132,4 @@ bool Foam::steadyOptimisation::update()
|
||||
}
|
||||
|
||||
|
||||
void Foam::steadyOptimisation::updateDesignVariables()
|
||||
{
|
||||
// Update design variables using either a line-search scheme or
|
||||
// a fixed-step update
|
||||
if (optType_->getLineSearch())
|
||||
{
|
||||
lineSearchUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
fixedStepUpdate();
|
||||
}
|
||||
|
||||
// Reset adjoint sensitivities in all adjoint solver managers
|
||||
for (adjointSolverManager& adjSolverManager : adjointSolverManagers_)
|
||||
{
|
||||
adjSolverManager.clearSensitivities();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -114,10 +114,6 @@ public:
|
||||
|
||||
//- Whether to update the design variables
|
||||
virtual bool update();
|
||||
|
||||
//- Do a line search to find a correction satisfying the step
|
||||
//- convergence criteria
|
||||
virtual void updateDesignVariables();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,525 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "unsteadyOptimisation.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(unsteadyOptimisation, 0);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
optimisationManager,
|
||||
unsteadyOptimisation,
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::unsteadyOptimisation::updateOptTypeSource()
|
||||
{
|
||||
forAll(primalSolvers_, pI)
|
||||
{
|
||||
primalSolvers_[pI].updateOptTypeSource(optType_->sourcePtr());
|
||||
}
|
||||
|
||||
forAll(adjointSolverManagers_, asmI)
|
||||
{
|
||||
PtrList<adjointSolver>& adjointSolvers =
|
||||
adjointSolverManagers_[asmI].adjointSolvers();
|
||||
|
||||
forAll(adjointSolvers, aI)
|
||||
{
|
||||
adjointSolvers[aI].updateOptTypeSource(optType_->sourcePtr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
|
||||
void Foam::unsteadyOptimisation::resetTime()
|
||||
{
|
||||
timeManip_.moveToPrimalStartTime();
|
||||
}
|
||||
|
||||
|
||||
void Foam::unsteadyOptimisation::moveDesignVariables()
|
||||
{
|
||||
if (shouldUpdateDesignVariables_)
|
||||
{
|
||||
// Updated grid should be written at the primal end time, to coinside
|
||||
// with the primal and adjoint solutions to be stored then. The
|
||||
// (unknown) time index is not important at this point, so it remains
|
||||
// unchanged.
|
||||
timeManip_.storeTime();
|
||||
timeManip_.moveToAdjointStartTime(false, false);
|
||||
|
||||
// Update design variables
|
||||
optType_->update();
|
||||
|
||||
// Restore time
|
||||
timeManip_.restoreTime();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::unsteadyOptimisation::moveDesignVariables
|
||||
(
|
||||
scalarField& direction
|
||||
)
|
||||
{
|
||||
if (shouldUpdateDesignVariables_)
|
||||
{
|
||||
// Updated grid should be written at the primal end time, to coinside
|
||||
// with the primal and adjoint solutions to be stored then. The
|
||||
// (unknown) time index is not important at this point, so it remains
|
||||
// unchanged.
|
||||
timeManip_.storeTime();
|
||||
timeManip_.moveToAdjointStartTime(false, false);
|
||||
|
||||
// Update design variables
|
||||
optType_->update(direction);
|
||||
|
||||
// Restore time
|
||||
timeManip_.restoreTime();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::unsteadyOptimisation::nActivePrimalSolvers()
|
||||
{
|
||||
const dictionary& primalSolversDict =
|
||||
IOdictionary::subDict("primalSolvers");
|
||||
const wordList& primalSolverNames = primalSolversDict.toc();
|
||||
label n(0);
|
||||
for (const word& name : primalSolverNames)
|
||||
{
|
||||
if (primalSolversDict.subDict(name).getOrDefault<bool>("active", true))
|
||||
{
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::unsteadyOptimisation::nActiveAdjointSolvers()
|
||||
{
|
||||
const dictionary& adjointManagersDict =
|
||||
IOdictionary::subDict("adjointManagers");
|
||||
const wordList& adjointManagerNames = adjointManagersDict.toc();
|
||||
label n(0);
|
||||
for (const word& name : adjointManagerNames)
|
||||
{
|
||||
const dictionary& dict = adjointManagersDict.subDict(name);
|
||||
n += adjointSolverManager::nActiveAdjointSolvers(dict);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
void Foam::unsteadyOptimisation::initialize()
|
||||
{
|
||||
mesh_.moving(false); // Note: not sure if needed
|
||||
// Boolean defining if primal fields will be read from a custom time
|
||||
// provided by the user.
|
||||
Switch useCustomReadTime(true);
|
||||
Switch shouldWriteObjective(true);
|
||||
if (!localIOdictionary::empty())
|
||||
{
|
||||
// Possible scenarios for the solution of the primal/adjoint equations:
|
||||
// (a) one wishes to continue with the next optimization cycle, or
|
||||
// (b) has run the primal solver, has stored the flow fields
|
||||
// time-series and now wants to run adjoint,
|
||||
// (c) has already solved the adjoint equations and wants to integrate
|
||||
// them again based on the same primal fields and without proceeding to
|
||||
// the next optimization cycle, or
|
||||
// (d) wants to continue with the primal solver only.
|
||||
// For (a), nothing needs to be done here.
|
||||
// For (b), in the previous execution of the code only the flow
|
||||
// equations were integrated and, now, the adjoint equations are
|
||||
// about to be solved. Hence, isAdjointActive under uniform is false
|
||||
// and nActiveAdjointSolvers() > 0 and nActivePrimalSolvers() >= 0.
|
||||
// nActivePrimalSolvers() is allowed to take positive values since the
|
||||
// user may have stored the primal problem and now wants to run adjoint
|
||||
// only (nActivePrimalSolvers() = 0) or wants to run adjoint and, then,
|
||||
// continue with the optimization (nActivePrimalSolvers() > 0)
|
||||
// For (c), isAdjointActive under uniform is true,
|
||||
// nActiveAdjointSolvers() > 0 and nActivePrimalSolvers() = 0.
|
||||
// For (d), isAdjointActive under uniform is false,
|
||||
// nActiveAdjointSolvers() = 0 and nActivePrimalSolvers() > 0.
|
||||
// iOptCycles_ does not need to be checked for the following reason.
|
||||
// Even if iOptCycles_ > 0 and the user wants to run the primal solver
|
||||
// only, then if
|
||||
// (i) the previous optimization cycle has just been completed case4 is
|
||||
// not activated and the manager proceeds as if a new optimization
|
||||
// cycle begins (a), whereas if
|
||||
// (ii) the primal solver has already been used, primal fields must be
|
||||
// initialized using the last available time-step
|
||||
|
||||
label nPrimalSolvers = nActivePrimalSolvers();
|
||||
label nAdjointSolvers = nActiveAdjointSolvers();
|
||||
// Check if adjoint solvers were active in the previous execution
|
||||
Switch isAdjointActive =
|
||||
localIOdictionary::get<Switch>("isAdjointActive");
|
||||
|
||||
Switch case2(!isAdjointActive && nAdjointSolvers > 0);
|
||||
Switch case3
|
||||
(
|
||||
isAdjointActive && nAdjointSolvers > 0 && nPrimalSolvers == 0
|
||||
);
|
||||
Switch case4
|
||||
(
|
||||
!isAdjointActive && nAdjointSolvers == 0 && nPrimalSolvers > 0
|
||||
);
|
||||
DebugInfo
|
||||
<< "case2 " << case2 << nl
|
||||
<< "case3 " << case3 << nl
|
||||
<< "case4 " << case4 << endl;
|
||||
if (case2 || case3)
|
||||
{
|
||||
// Start time of the primal is this time - the old span
|
||||
timeManip_.setStartTime
|
||||
(
|
||||
mesh_.time().value() - localIOdictionary::get<scalar>("span")
|
||||
);
|
||||
// Read startTimeIndex from dict
|
||||
timeManip_.setStartTimeIndex
|
||||
(localIOdictionary::get<label>("primalStartTimeIndex"));
|
||||
// Don't update design variables and avoid writing objectives
|
||||
// since we are running adjoint only
|
||||
shouldUpdateDesignVariables_ = false;
|
||||
shouldWriteObjective = false;
|
||||
// Don't solve the primal equations in the first go, even if they
|
||||
// are enabled
|
||||
solveFirstPrimalEqns_ = false;
|
||||
}
|
||||
else if (case4)
|
||||
{
|
||||
// Don't update design variables since we are running primal only
|
||||
shouldUpdateDesignVariables_ = false;
|
||||
// Disable editing readTime of the primal fields
|
||||
useCustomReadTime = false;
|
||||
}
|
||||
if (case3)
|
||||
{
|
||||
if (--iOptCycle_ < 0)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "iOptCycle = " << iOptCycle_ << ". Code should enter "
|
||||
<< "here only if both the primal and adjoint" << nl
|
||||
<< "equations have already been integrated for the" << nl
|
||||
<< "current optimization cycle and the user wants to" << nl
|
||||
<< "run the adjoint solver again" << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
setSolvers(useCustomReadTime);
|
||||
// Deactivate writting objective functions in case that the primal
|
||||
// solution of the current optimization cycle has been stored and
|
||||
// the adjoint problem is about to be solved
|
||||
if (!shouldWriteObjective)
|
||||
{
|
||||
forAll(adjointSolverManagers_, amI)
|
||||
{
|
||||
adjointSolverManagers_[amI].setWrite(false);
|
||||
adjointSolverManagers_[amI].setWriteOption(IOobject::NO_WRITE);
|
||||
}
|
||||
}
|
||||
// Set averaging start time (if activated)
|
||||
forAll(primalSolvers_, psI)
|
||||
{
|
||||
primalSolvers_[psI].getVariablesSet().
|
||||
adjustAverageStartTime(timeManip_.startTime().value());
|
||||
}
|
||||
|
||||
// if (debug)
|
||||
// {
|
||||
Info<< "startTime " << timeManip_.startTime() << nl
|
||||
<< "startTimeIndex " << timeManip_.startTimeIndex() << nl
|
||||
<< "primalEndTime " << timeManip_.primalEndTime() << nl
|
||||
<< "span " << timeManip_.span() << endl;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
void Foam::unsteadyOptimisation::setSolvers(Switch useCustomReadTime)
|
||||
{
|
||||
// Read primal fields from the time prescribed in the optimisationDict,
|
||||
// Time index is not updated, but this should not be a problem
|
||||
dictionary& primalSolversDict =
|
||||
IOdictionary::subDict("primalSolvers");
|
||||
const wordList& primalSolverNames = primalSolversDict.toc();
|
||||
|
||||
// Construct primal solvers
|
||||
primalSolvers_.setSize(primalSolverNames.size());
|
||||
forAll(primalSolvers_, solveri)
|
||||
{
|
||||
dictionary& solverDict =
|
||||
primalSolversDict.subDict(primalSolverNames[solveri]);
|
||||
if (primalSolvers_.size() > 1)
|
||||
{
|
||||
solverDict.add<bool>("useSolverNameForFields", true);
|
||||
}
|
||||
primalSolvers_.set
|
||||
(
|
||||
solveri,
|
||||
primalSolver::New
|
||||
(
|
||||
mesh_,
|
||||
managerType_,
|
||||
solverDict,
|
||||
useCustomReadTime
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Construct adjointSolverManagers
|
||||
const dictionary& adjointManagersDict =
|
||||
IOdictionary::subDict("adjointManagers");
|
||||
const wordList& adjointManagerNames = adjointManagersDict.toc();
|
||||
adjointSolverManagers_.setSize(adjointManagerNames.size());
|
||||
|
||||
label nAdjointSolvers(0);
|
||||
label nActiveAdjointSolvers(0);
|
||||
bool overrideUseSolverName(adjointSolverManagers_.size() > 1);
|
||||
forAll(adjointSolverManagers_, manageri)
|
||||
{
|
||||
adjointSolverManagers_.set
|
||||
(
|
||||
manageri,
|
||||
new adjointSolverManager
|
||||
(
|
||||
mesh_,
|
||||
managerType_,
|
||||
adjointManagersDict.subDict(adjointManagerNames[manageri]),
|
||||
overrideUseSolverName
|
||||
)
|
||||
);
|
||||
nAdjointSolvers +=
|
||||
adjointSolverManagers_[manageri].nAdjointSolvers();
|
||||
nActiveAdjointSolvers +=
|
||||
adjointSolverManagers_[manageri].nActiveAdjointSolvers();
|
||||
}
|
||||
isAdjointActive_ = (nActiveAdjointSolvers > 0);
|
||||
|
||||
// Sanity checks on the naming convention
|
||||
if (primalSolvers_.size() > 1)
|
||||
{
|
||||
for (const primalSolver& solveri : primalSolvers_)
|
||||
{
|
||||
if (!solveri.useSolverNameForFields())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Multiple primal solvers are present but "
|
||||
<< "useSolverNameForFields is set to false in "
|
||||
<< "primal solver " << solveri.solverName() << nl
|
||||
<< "This is considered fatal."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nAdjointSolvers > 1)
|
||||
{
|
||||
for (const adjointSolverManager& amI : adjointSolverManagers_)
|
||||
{
|
||||
const PtrList<adjointSolver>& adjointSolvers = amI.adjointSolvers();
|
||||
for (const adjointSolver& asI : adjointSolvers)
|
||||
{
|
||||
if (!asI.useSolverNameForFields())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Multiple adjoint solvers are present but "
|
||||
<< "useSolverNameForFields is set to false in "
|
||||
<< "adjoint solver " << asI.solverName() << nl
|
||||
<< "This is considered fatal."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::unsteadyOptimisation::unsteadyOptimisation(fvMesh& mesh)
|
||||
:
|
||||
optimisationManager(mesh),
|
||||
localIOdictionary
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"optimisation",
|
||||
mesh_.time().timeName(),
|
||||
"uniform",
|
||||
mesh_,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
word::null
|
||||
),
|
||||
iOptCycle_(localIOdictionary::getOrDefault<label>("optimisationCycle", 0)),
|
||||
nOptCycles_(mesh_.time().controlDict().get<label>("nOptimisationCycles")),
|
||||
isAdjointActive_(true),
|
||||
timeManip_
|
||||
(
|
||||
const_cast<unsteadyTimeManipulation&>
|
||||
(
|
||||
unsteadyTimeManipulation::New(mesh)
|
||||
)
|
||||
),
|
||||
solveFirstPrimalEqns_(true)
|
||||
{
|
||||
// Set primal and adjoint solvers
|
||||
initialize();
|
||||
optType_.reset
|
||||
(
|
||||
incompressible::optimisationType::New
|
||||
(
|
||||
mesh,
|
||||
IOdictionary::subDict("optimisation"),
|
||||
adjointSolverManagers_
|
||||
)
|
||||
);
|
||||
// Update source ptrs in all solvers to look at the source held in optType
|
||||
// Possible problem if mesh is adapted
|
||||
updateOptTypeSource();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::optimisationManager& Foam::unsteadyOptimisation::operator++()
|
||||
{
|
||||
iOptCycle_++;
|
||||
|
||||
if (!end())
|
||||
{
|
||||
Info<< "\n* * * * * * * * * * * * * * * * *" << endl;
|
||||
Info<< "Optimisation cycle " << iOptCycle_ << endl;
|
||||
Info<< "Time span ["
|
||||
<< time_.value() << ","
|
||||
<< time_.value() + timeManip_.span()
|
||||
<< "]" << endl;
|
||||
Info<< "* * * * * * * * * * * * * * * * *\n" << endl;
|
||||
}
|
||||
timeManip_.newOptimisationCycle();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Foam::optimisationManager& Foam::unsteadyOptimisation::operator++(int)
|
||||
{
|
||||
return operator++();
|
||||
}
|
||||
|
||||
|
||||
bool Foam::unsteadyOptimisation::checkEndOfLoopAndUpdate()
|
||||
{
|
||||
if (update())
|
||||
{
|
||||
optType_->update();
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
|
||||
bool Foam::unsteadyOptimisation::end()
|
||||
{
|
||||
return iOptCycle_ > nOptCycles_;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::unsteadyOptimisation::update()
|
||||
{
|
||||
return (iOptCycle_ != 1 && !end());
|
||||
}
|
||||
|
||||
|
||||
void Foam::unsteadyOptimisation::solvePrimalEquations()
|
||||
{
|
||||
// Solve all primal equations
|
||||
if (solveFirstPrimalEqns_)
|
||||
{
|
||||
optimisationManager::solvePrimalEquations();
|
||||
}
|
||||
solveFirstPrimalEqns_ = true;
|
||||
}
|
||||
|
||||
|
||||
void Foam::unsteadyOptimisation::solveAdjointEquations()
|
||||
{
|
||||
optimisationManager::solveAdjointEquations();
|
||||
// Re-activate Switch to update the design variables at the
|
||||
// beggining of the next optimization cycle, if it has been
|
||||
// deactivated
|
||||
shouldUpdateDesignVariables_ = true;
|
||||
// Allow writing objectives at the next optimization cycle,
|
||||
// if deactivated
|
||||
forAll(adjointSolverManagers_, amI)
|
||||
{
|
||||
adjointSolverManagers_[amI].setWrite(true);
|
||||
adjointSolverManagers_[amI].setWriteOption(IOobject::AUTO_WRITE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::unsteadyOptimisation::writeData(Ostream& os) const
|
||||
{
|
||||
DebugInfo
|
||||
<< "Calling unsteadyOptimisation::writeData" << endl;
|
||||
|
||||
// If adjoint hasn't been solved, don't treat this cycle as complete
|
||||
label cycle(isAdjointActive_ ? iOptCycle_ : iOptCycle_ - 1);
|
||||
|
||||
const label startTimeIndex = timeManip_.startTimeIndex();
|
||||
os.writeEntry("optimisationCycle", cycle);
|
||||
os.writeEntry("isAdjointActive", isAdjointActive_);
|
||||
os.writeEntry("primalStartTimeIndex", startTimeIndex);
|
||||
|
||||
DebugInfo
|
||||
<< "Writing data to localIOdictionary for continuation" << nl
|
||||
<< tab << "optimisationCycle " << cycle << nl
|
||||
<< tab << "isAdjointActive " << isAdjointActive_ << nl
|
||||
<< tab << "primalStartTimeIndex " << startTimeIndex << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,180 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::unsteadyOptimisation
|
||||
|
||||
Description
|
||||
Iterate the optimisation cycles. For steady state opt, this coinsides
|
||||
with evolving Time
|
||||
|
||||
SourceFiles
|
||||
unsteadyOptimisation.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef unsteadyOptimisation_H
|
||||
#define unsteadyOptimisation_H
|
||||
|
||||
#include "optimisationManager.H"
|
||||
#include "localIOdictionary.H"
|
||||
#include "unsteadyTimeManipulation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class unsteadyOptimisation Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class unsteadyOptimisation
|
||||
:
|
||||
public optimisationManager,
|
||||
public localIOdictionary
|
||||
{
|
||||
private:
|
||||
|
||||
// Private Member Data
|
||||
|
||||
//- Current optimisation cycle
|
||||
label iOptCycle_;
|
||||
|
||||
//- Number of optimisation cycles
|
||||
label nOptCycles_;
|
||||
|
||||
//- Switch defining if at least one adjoint solver is active
|
||||
Switch isAdjointActive_;
|
||||
|
||||
//- Time manipulation, common for all primal and adjoint solvers
|
||||
unsteadyTimeManipulation& timeManip_;
|
||||
|
||||
//- Boolean to treat a special case
|
||||
// If adjoint was not solved in the previous code execution, but it is
|
||||
// solved now, together with the primal equations, avoid solving the
|
||||
// primal equations the first time
|
||||
bool solveFirstPrimalEqns_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Update optimisationType source for all primal and adjoint solvers
|
||||
void updateOptTypeSource();
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
unsteadyOptimisation(const unsteadyOptimisation&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const unsteadyOptimisation&) = delete;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Reset time to primal time after a failed line search
|
||||
virtual void resetTime() override;
|
||||
|
||||
virtual void moveDesignVariables() override;
|
||||
|
||||
virtual void moveDesignVariables
|
||||
(
|
||||
scalarField& direction
|
||||
) override;
|
||||
|
||||
//- Return number of active primal and adjoint solvers without
|
||||
//- constructing any of the solvers.
|
||||
// It is calculated through reading dictionary entries. Warning: It is
|
||||
// designed to be used by initialize() function only. In this case no
|
||||
// mismatch can occur if the optimisationDict is changed during
|
||||
// runTime, since the primal or adjoint solvers are built directly
|
||||
// after calling this function. If the number of active adjoint
|
||||
// solvers is required elsewhere, use the nActiveAdjointSolvers()
|
||||
// function of each adjointSolverManager.
|
||||
label nActivePrimalSolvers();
|
||||
|
||||
label nActiveAdjointSolvers();
|
||||
|
||||
virtual void initialize() override;
|
||||
|
||||
void setSolvers(Switch editPrimalReadTime);
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("unsteadyOptimisation");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
unsteadyOptimisation(fvMesh& mesh);
|
||||
|
||||
|
||||
// Destructor
|
||||
virtual ~unsteadyOptimisation() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Prefix increment
|
||||
virtual optimisationManager& operator++();
|
||||
|
||||
//- Postfix increment, this is identical to the prefix increment
|
||||
virtual optimisationManager& operator++(int);
|
||||
|
||||
//- Return true if end of optimisation run
|
||||
// Also, updates the design variables if needed
|
||||
virtual bool checkEndOfLoopAndUpdate();
|
||||
|
||||
//- Return true if end of optimisation run
|
||||
virtual bool end();
|
||||
|
||||
//- Whether to update the design variables
|
||||
virtual bool update();
|
||||
|
||||
//- Solve all primal equations
|
||||
virtual void solvePrimalEquations() override;
|
||||
|
||||
//- Solve all adjoint equations
|
||||
virtual void solveAdjointEquations() override;
|
||||
|
||||
//- write necessary data for continuation
|
||||
virtual bool writeData(Ostream&) const override;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,202 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "error.H"
|
||||
#include "unsteadyTimeManipulation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(unsteadyTimeManipulation, 0);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::unsteadyTimeManipulation::printOut(const char* functionName)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "After call to " << functionName << endl;
|
||||
OSstream& os = Info.stream();
|
||||
os.beginBlock();
|
||||
os<< *this;
|
||||
os.endBlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::unsteadyTimeManipulation::unsteadyTimeManipulation
|
||||
(
|
||||
const fvMesh& mesh
|
||||
)
|
||||
:
|
||||
MeshObject<fvMesh, UpdateableMeshObject, unsteadyTimeManipulation>(mesh),
|
||||
time_(const_cast<Time&>(mesh.time())),
|
||||
startTime_(time_.startTime()),
|
||||
startTimeIndex_(time_.startTimeIndex()),
|
||||
endTimeIndex_(-1),
|
||||
span_(time_.endTime().value() - time_.startTime().value()),
|
||||
storedTime_(nullptr),
|
||||
storedTimeIndex_(nullptr),
|
||||
storedEndTime_(nullptr)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::unsteadyTimeManipulation::moveToPrimalStartTime(bool setEndTime)
|
||||
{
|
||||
time_.setTime(startTime_, startTimeIndex_);
|
||||
if (setEndTime)
|
||||
{
|
||||
time_.setEndTime(startTime_.value() + span_);
|
||||
}
|
||||
printOut(FUNCTION_NAME);
|
||||
}
|
||||
|
||||
|
||||
void Foam::unsteadyTimeManipulation::moveToAdjointStartTime
|
||||
(
|
||||
bool setEndTime,
|
||||
bool setTimeIndex
|
||||
)
|
||||
{
|
||||
label index(setTimeIndex ? endTimeIndex_ : time_.timeIndex());
|
||||
time_.setTime(startTime_.value() + span_, index);
|
||||
if (setEndTime)
|
||||
{
|
||||
// Set endTime of the adjoint solver as the start of the primal one,
|
||||
// plus a deltaT
|
||||
time_.setEndTime(startTime_.value() + time_.deltaT().value());
|
||||
}
|
||||
printOut(FUNCTION_NAME);
|
||||
}
|
||||
|
||||
|
||||
void Foam::unsteadyTimeManipulation::newOptimisationCycle()
|
||||
{
|
||||
// Increment endTime by a time span
|
||||
time_.setEndTime(time_.value() + span_);
|
||||
|
||||
// Adjust startTime of each optimisation loop
|
||||
startTime_ = time_;
|
||||
startTimeIndex_ = time_.timeIndex();
|
||||
printOut(FUNCTION_NAME);
|
||||
}
|
||||
|
||||
|
||||
void Foam::unsteadyTimeManipulation::storeTime()
|
||||
{
|
||||
storedTime_.reset(new dimensionedScalar(time_));
|
||||
storedTimeIndex_.reset(new label(time_.timeIndex()));
|
||||
storedEndTime_.reset(new dimensionedScalar(time_.endTime()));
|
||||
}
|
||||
|
||||
|
||||
void Foam::unsteadyTimeManipulation::restoreTime()
|
||||
{
|
||||
if (storedTime_ && storedTimeIndex_)
|
||||
{
|
||||
time_.setTime(storedTime_(), storedTimeIndex_());
|
||||
storedTime_.clear();
|
||||
storedTimeIndex_.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted to restore unset stored time and timeIndex"
|
||||
<< exit(FatalError)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
if (storedEndTime_)
|
||||
{
|
||||
time_.setEndTime(storedEndTime_());
|
||||
storedEndTime_.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted to restore unset stored endTime"
|
||||
<< exit(FatalError)
|
||||
<< endl;
|
||||
}
|
||||
printOut(FUNCTION_NAME);
|
||||
}
|
||||
|
||||
|
||||
void Foam::unsteadyTimeManipulation::writeEntries(Ostream& os) const
|
||||
{
|
||||
os.beginBlock("localEntries");
|
||||
os.writeEntry("startTime", startTime());
|
||||
os.writeEntry("startTimeIndex", startTimeIndex());
|
||||
os.writeEntry("primalEndTime", primalEndTime());
|
||||
os.writeEntry("endTimeIndex", endTimeIndex());
|
||||
os.writeEntry("span", span_);
|
||||
os.endBlock();
|
||||
|
||||
os.beginBlock("TimeEntries");
|
||||
os.writeEntry("time", time_.value());
|
||||
os.writeEntry("timeIndex", time_.timeIndex());
|
||||
os.writeEntry("deltaT", time_.deltaT());
|
||||
os.writeEntry("endTime", time_.endTime());
|
||||
os.endBlock();
|
||||
}
|
||||
|
||||
|
||||
bool Foam::unsteadyTimeManipulation::movePoints()
|
||||
{
|
||||
// Does nothing
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Foam::unsteadyTimeManipulation::updateMesh(const mapPolyMesh&)
|
||||
{
|
||||
// Does nothing
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
||||
|
||||
Foam::Ostream& Foam::operator<<
|
||||
(
|
||||
Ostream& os,
|
||||
const unsteadyTimeManipulation& timeManip
|
||||
)
|
||||
{
|
||||
timeManip.writeEntries(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,247 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::unsteadyTimeManipulation
|
||||
|
||||
Description
|
||||
Class with helper functions to manipulate time during unsteady optimisation
|
||||
|
||||
|
||||
|
||||
SourceFiles
|
||||
unsteadyTimeManipulation.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef unsteadyTimeManipulation_H
|
||||
#define unsteadyTimeManipulation_H
|
||||
|
||||
#include "MeshObject.H"
|
||||
#include "fvMesh.H"
|
||||
#include "OFstream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class unsteadyTimeManipulation;
|
||||
Ostream& operator<< (Ostream&, const unsteadyTimeManipulation&);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class unsteadyTimeManipulation Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class unsteadyTimeManipulation
|
||||
:
|
||||
public MeshObject<fvMesh, UpdateableMeshObject, unsteadyTimeManipulation>
|
||||
{
|
||||
protected:
|
||||
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Not constant reference to Time
|
||||
Time& time_;
|
||||
|
||||
//- Start time of the optimisation loop
|
||||
// Will be updated at the beginning of each new loop
|
||||
dimensionedScalar startTime_;
|
||||
|
||||
//- Start time index of the optimisation loop
|
||||
label startTimeIndex_;
|
||||
|
||||
//- Start time index of the optimisation loop
|
||||
label endTimeIndex_;
|
||||
|
||||
//- Span of the optimisation loop
|
||||
scalar span_;
|
||||
|
||||
|
||||
// Temporarily stored time features
|
||||
|
||||
autoPtr<dimensionedScalar> storedTime_;
|
||||
autoPtr<label> storedTimeIndex_;
|
||||
autoPtr<dimensionedScalar> storedEndTime_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Print entries for debugging
|
||||
void printOut(const char* functionName);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- No copy construct
|
||||
unsteadyTimeManipulation(const unsteadyTimeManipulation&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const unsteadyTimeManipulation&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("unsteadyTimeManipulation");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
unsteadyTimeManipulation(const fvMesh& mesh);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~unsteadyTimeManipulation() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Return start time of the optimisation loop
|
||||
inline const dimensionedScalar& startTime() const
|
||||
{
|
||||
return startTime_;
|
||||
}
|
||||
|
||||
//- Return start time of the optimisation loop
|
||||
inline label startTimeIndex() const
|
||||
{
|
||||
return startTimeIndex_;
|
||||
}
|
||||
|
||||
//- Return span of the optimisation loop
|
||||
inline label endTimeIndex() const
|
||||
{
|
||||
return endTimeIndex_;
|
||||
}
|
||||
|
||||
//- Return span of the optimisation loop
|
||||
inline scalar span() const
|
||||
{
|
||||
return span_;
|
||||
}
|
||||
|
||||
//- Return end time of primal
|
||||
inline scalar primalEndTime() const
|
||||
{
|
||||
return startTime_.value() + span_;
|
||||
}
|
||||
|
||||
|
||||
// Edit
|
||||
|
||||
//- Set startTime
|
||||
inline void setStartTime(const scalar startTime)
|
||||
{
|
||||
startTime_.value() = startTime;
|
||||
}
|
||||
|
||||
//- Set startTimeIndex
|
||||
inline void setStartTimeIndex(const label startTimeIndex)
|
||||
{
|
||||
startTimeIndex_ = startTimeIndex;
|
||||
}
|
||||
|
||||
//- Set span
|
||||
inline void setSpan(const scalar span)
|
||||
{
|
||||
span_ = span;
|
||||
}
|
||||
|
||||
//- Set endTimeIndex
|
||||
inline void setEndTimeIndex(const label endTimeIndex)
|
||||
{
|
||||
endTimeIndex_ = endTimeIndex;
|
||||
}
|
||||
|
||||
|
||||
//- Store current endTimeIndex to local copy
|
||||
inline void storeEndTimeIndex()
|
||||
{
|
||||
endTimeIndex_ = time_.timeIndex();
|
||||
}
|
||||
|
||||
//- Move time to the beginning of the primal
|
||||
// Optionally sets endTime equal to startTime + span
|
||||
void moveToPrimalStartTime(bool setEndTime = true);
|
||||
|
||||
//- Move time to the end of the primal
|
||||
// Optionally sets endTime equal to startTime
|
||||
void moveToAdjointStartTime
|
||||
(
|
||||
bool setEndTime = true,
|
||||
bool setTimeIndex = true
|
||||
);
|
||||
|
||||
//- Increment time features at the beginning of each optimisation
|
||||
//- cycle
|
||||
void newOptimisationCycle();
|
||||
|
||||
|
||||
//- Store current time features
|
||||
void storeTime();
|
||||
|
||||
//- Retrieve last stored time features
|
||||
void restoreTime();
|
||||
|
||||
//- Write local entries and time entries to stream
|
||||
void writeEntries(Ostream& os) const;
|
||||
|
||||
//- Dummy function required by MeshObject.
|
||||
virtual bool movePoints();
|
||||
|
||||
//- Dummy function required by MeshObject.
|
||||
virtual void updateMesh(const mapPolyMesh&);
|
||||
|
||||
|
||||
// Ostream operators
|
||||
|
||||
friend Ostream& operator<<
|
||||
(
|
||||
Ostream&,
|
||||
const unsteadyTimeManipulation&
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
||||
Copyright (C) 2013-2019 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -27,6 +27,7 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "Ostream.H"
|
||||
#include "adjointSolverManager.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
@ -36,6 +37,27 @@ namespace Foam
|
||||
defineTypeNameAndDebug(adjointSolverManager, 0);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::adjointSolverManager::checkIntegrationTimes() const
|
||||
{
|
||||
forAll(adjointSolvers_, i)
|
||||
{
|
||||
const objectiveManager& objManager =
|
||||
adjointSolvers_[i].getObjectiveManager();
|
||||
if (!objManager.hasIntegrationTimes())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "The integration window of at least one of the objectives "
|
||||
<< "of adjointSolver '"<< adjointSolvers_[i].solverName()
|
||||
<< "' is undefined." << endl
|
||||
// << "Either define the integration window "
|
||||
// << "for all objectives or use FFT to one of them."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
@ -62,6 +84,7 @@ Foam::adjointSolverManager::adjointSolverManager
|
||||
mesh_(mesh),
|
||||
dict_(dict),
|
||||
managerName_(dict.dictName()),
|
||||
managerType_(managerType),
|
||||
primalSolverName_(dict.get<word>("primalSolver")),
|
||||
adjointSolvers_(0),
|
||||
objectiveSolverIDs_(0),
|
||||
@ -69,7 +92,8 @@ Foam::adjointSolverManager::adjointSolverManager
|
||||
operatingPointWeight_
|
||||
(
|
||||
dict.getOrDefault<scalar>("operatingPointWeight", 1)
|
||||
)
|
||||
),
|
||||
nActiveAdjointSolvers_(0)
|
||||
{
|
||||
dictionary& adjointSolversDict =
|
||||
const_cast<dictionary&>(dict.subDict("adjointSolvers"));
|
||||
@ -99,7 +123,10 @@ Foam::adjointSolverManager::adjointSolverManager
|
||||
primalSolverName_
|
||||
)
|
||||
);
|
||||
|
||||
if (adjointSolvers_[namei].active())
|
||||
{
|
||||
nActiveAdjointSolvers_++;
|
||||
}
|
||||
if (adjointSolvers_[namei].isConstraint())
|
||||
{
|
||||
constraintSolverIDs_[nConstraints++] = namei;
|
||||
@ -115,6 +142,9 @@ Foam::adjointSolverManager::adjointSolverManager
|
||||
Info<< "Found " << nConstraints
|
||||
<< " adjoint solvers acting as constraints" << endl;
|
||||
|
||||
Info<< "Found " << nActiveAdjointSolvers_
|
||||
<< " active adjoint solvers" << endl;
|
||||
|
||||
// Having more than one non-aggregated objectives per operating point
|
||||
// is needlessly expensive. Issue a warning
|
||||
if (objectiveSolverIDs_.size() > 1)
|
||||
@ -122,8 +152,9 @@ Foam::adjointSolverManager::adjointSolverManager
|
||||
WarningInFunction
|
||||
<< "Number of adjoint solvers corresponding to objectives "
|
||||
<< "is greater than 1 (" << objectiveSolverIDs_.size() << ")" << nl
|
||||
<< "Consider aggregating your objectives to one" << endl;
|
||||
<< "Consider aggregating your objectives to one" << nl << endl;
|
||||
}
|
||||
checkIntegrationTimes();
|
||||
}
|
||||
|
||||
|
||||
@ -163,6 +194,24 @@ const Foam::dictionary& Foam::adjointSolverManager::dict() const
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointSolverManager::setWrite(const bool shouldWrite)
|
||||
{
|
||||
forAll(adjointSolvers_, i)
|
||||
{
|
||||
adjointSolvers_[i].getObjectiveManager().setWrite(shouldWrite);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointSolverManager::setWriteOption(IOobject::writeOption w)
|
||||
{
|
||||
forAll(adjointSolvers_, i)
|
||||
{
|
||||
adjointSolvers_[i].getObjectiveManager().setWriteOption(w);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const Foam::PtrList<Foam::adjointSolver>&
|
||||
Foam::adjointSolverManager::adjointSolvers() const
|
||||
{
|
||||
@ -177,12 +226,51 @@ Foam::adjointSolverManager::adjointSolvers()
|
||||
}
|
||||
|
||||
|
||||
Foam::wordList Foam::adjointSolverManager::adjointSolversNames() const
|
||||
{
|
||||
wordList names(adjointSolvers_.size());
|
||||
forAll(adjointSolvers_, sI)
|
||||
{
|
||||
names[sI] = adjointSolvers_[sI].name();
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
Foam::scalar Foam::adjointSolverManager::operatingPointWeight() const
|
||||
{
|
||||
return operatingPointWeight_;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::adjointSolverManager::nActiveAdjointSolvers() const
|
||||
{
|
||||
return nActiveAdjointSolvers_;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::adjointSolverManager::nActiveAdjointSolvers
|
||||
(
|
||||
const dictionary& dict
|
||||
)
|
||||
{
|
||||
const dictionary& adjointSolversDict = dict.subDict("adjointSolvers");
|
||||
const wordList adjSolverNames = adjointSolversDict.toc();
|
||||
label n(0);
|
||||
Switch active(true);
|
||||
forAll(adjSolverNames, namei)
|
||||
{
|
||||
active = adjointSolversDict.subDict(adjSolverNames[namei]).
|
||||
getOrDefault<bool>("active", true);
|
||||
if (active)
|
||||
{
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::adjointSolverManager::nConstraints() const
|
||||
{
|
||||
return constraintSolverIDs_.size();
|
||||
@ -316,4 +404,13 @@ void Foam::adjointSolverManager::updatePrimalBasedQuantities(const word& name)
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointSolverManager::postLineSearch()
|
||||
{
|
||||
for (adjointSolver& solver : adjointSolvers_)
|
||||
{
|
||||
solver.postLineSearch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
||||
Copyright (C) 2013-2019 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -77,6 +77,8 @@ protected:
|
||||
|
||||
const word managerName_;
|
||||
|
||||
const word managerType_;
|
||||
|
||||
const word primalSolverName_;
|
||||
|
||||
PtrList<adjointSolver> adjointSolvers_;
|
||||
@ -87,6 +89,13 @@ protected:
|
||||
|
||||
scalar operatingPointWeight_;
|
||||
|
||||
label nActiveAdjointSolvers_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Check integration times for unsteady runs
|
||||
void checkIntegrationTimes() const;
|
||||
|
||||
public:
|
||||
|
||||
@ -125,15 +134,33 @@ public:
|
||||
//- Const access to the construction dictionary
|
||||
const dictionary& dict() const;
|
||||
|
||||
//- Should the objectives be written to file upon calling the
|
||||
// corresponding write() function?
|
||||
void setWrite(const bool shouldWrite);
|
||||
|
||||
//- Should the localIOdictionary be written?
|
||||
void setWriteOption(IOobject::writeOption w);
|
||||
|
||||
//- Const access to adjoint solvers
|
||||
const PtrList<adjointSolver>& adjointSolvers() const;
|
||||
|
||||
//- Non-const access to adjoint solvers
|
||||
PtrList<adjointSolver>& adjointSolvers();
|
||||
|
||||
//- Return the names of all adjointSolvers
|
||||
wordList adjointSolversNames() const;
|
||||
|
||||
//- Const access to adjoint solvers
|
||||
scalar operatingPointWeight() const;
|
||||
|
||||
//- Return number of active adjoint solvers, either corresponding
|
||||
// to objectives or constraints
|
||||
label nActiveAdjointSolvers() const;
|
||||
|
||||
//- Static function returning the number of active adjoint
|
||||
// solvers reading dict
|
||||
static label nActiveAdjointSolvers(const dictionary& dict);
|
||||
|
||||
//- Number of adjoint solvers corresponding to constraints
|
||||
label nConstraints() const;
|
||||
|
||||
@ -173,6 +200,9 @@ public:
|
||||
// For instance, primal fields of adjoint turbulence models
|
||||
void updatePrimalBasedQuantities(const word& name);
|
||||
|
||||
//- Actions to be executed after the convergence of lineSearch
|
||||
void postLineSearch();
|
||||
|
||||
|
||||
// IO
|
||||
|
||||
|
||||
@ -0,0 +1,588 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "pimple.H"
|
||||
#include "adjointPimple.H"
|
||||
#include "findRefCell.H"
|
||||
#include "constrainHbyA.H"
|
||||
#include "constrainPressure.H"
|
||||
#include "adjustPhi.H"
|
||||
#include "fvOptions.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(adjointPimple, 0);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
incompressibleAdjointSolver,
|
||||
adjointPimple,
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::incompressibleAdjointVars& Foam::adjointPimple::allocateVars()
|
||||
{
|
||||
vars_.reset
|
||||
(
|
||||
new incompressibleAdjointVars
|
||||
(
|
||||
mesh_,
|
||||
solverControl_(),
|
||||
objectiveManagerPtr_(),
|
||||
primalVars_
|
||||
)
|
||||
);
|
||||
return getAdjointVars();
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPimple::setDeltaT()
|
||||
{
|
||||
// Original function at
|
||||
// src/finiteVolume/cfdTools/general/include/setDeltaT.H
|
||||
if (!deltaTList_.empty())
|
||||
{
|
||||
Time& runTime = const_cast<Time&>(mesh_.time());
|
||||
DebugInfo
|
||||
<< "runTime.timeIndex(), primalStartTimeIndex = "
|
||||
<< runTime.timeIndex() << " " << timeManip_.startTimeIndex()
|
||||
<< endl;
|
||||
runTime.setDeltaT
|
||||
(
|
||||
deltaTList_[runTime.timeIndex() - timeManip_.startTimeIndex() -1]
|
||||
);
|
||||
|
||||
Info<< "deltaT = " << runTime.deltaTValue() << endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPimple::setTime()
|
||||
{
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
--time;
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPimple::CourantNo() const
|
||||
{
|
||||
const surfaceScalarField& phi = primalVars_.phiInst();
|
||||
const Time& runTime = mesh_.time();
|
||||
const fvMesh& mesh = mesh_;
|
||||
#include "CourantNo.H"
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPimple::continuityErrors()
|
||||
{
|
||||
// Original function at
|
||||
// src/finiteVolume/cfdTools/incompressible/continuityErrs.H
|
||||
const Time& runTime = mesh_.time();
|
||||
const fvMesh& mesh = mesh_;
|
||||
const surfaceScalarField& phi = adjointVars_.phiaInst();
|
||||
scalar& cumulativeContErr = cumulativeContErr_;
|
||||
#include "continuityErrs.H"
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPimple::accumulateSensitivities()
|
||||
{
|
||||
if (computeSensitivities_)
|
||||
{
|
||||
adjointSensitivity_->accumulateIntegrand(mesh_.time().deltaTValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::adjointPimple::adjointPimple
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict,
|
||||
const word& primalSolverName
|
||||
)
|
||||
:
|
||||
incompressibleAdjointSolver
|
||||
(
|
||||
mesh,
|
||||
managerType,
|
||||
dict,
|
||||
primalSolverName
|
||||
),
|
||||
solverControl_(PIMPLEControl::New(mesh, managerType, *this)),
|
||||
adjointVars_(allocateVars()),
|
||||
cumulativeContErr_(Zero),
|
||||
adjointSensitivity_(nullptr),
|
||||
primalStorage_(getPrimalSolver().getPrimalStorage()),
|
||||
deltaTList_(refCast<pimple>(getPrimalSolver()).getDeltaTList()),
|
||||
timeManip_
|
||||
(
|
||||
const_cast<unsteadyTimeManipulation&>
|
||||
(
|
||||
unsteadyTimeManipulation::New(mesh)
|
||||
)
|
||||
)
|
||||
{
|
||||
ATCModel_.reset
|
||||
(
|
||||
ATCModel::New
|
||||
(
|
||||
mesh,
|
||||
primalVars_,
|
||||
adjointVars_,
|
||||
dict.subDict("ATCModel")
|
||||
).ptr()
|
||||
);
|
||||
|
||||
addExtraSchemes();
|
||||
setRefCell
|
||||
(
|
||||
adjointVars_.paInst(),
|
||||
solverControl_().dict(),
|
||||
solverControl_().pRefCell(),
|
||||
solverControl_().pRefValue()
|
||||
);
|
||||
|
||||
if (computeSensitivities_)
|
||||
{
|
||||
const IOdictionary& optDict =
|
||||
mesh.lookupObject<IOdictionary>("optimisationDict");
|
||||
|
||||
adjointSensitivity_.reset
|
||||
(
|
||||
incompressible::adjointSensitivity::New
|
||||
(
|
||||
mesh,
|
||||
optDict.subDict("optimisation").subDict("sensitivities"),
|
||||
*this
|
||||
).ptr()
|
||||
);
|
||||
}
|
||||
|
||||
// Check integration times of the objectives
|
||||
objectiveManagerPtr_().checkIntegrationTimes();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::adjointPimple::readDict(const dictionary& dict)
|
||||
{
|
||||
if (incompressibleAdjointSolver::readDict(dict))
|
||||
{
|
||||
if (adjointSensitivity_.valid())
|
||||
{
|
||||
const IOdictionary& optDict =
|
||||
mesh_.lookupObject<IOdictionary>("optimisationDict");
|
||||
|
||||
adjointSensitivity_().readDict
|
||||
(
|
||||
optDict.subDict("optimisation").subDict("sensitivities")
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPimple::solveIter()
|
||||
{
|
||||
CourantNo();
|
||||
setDeltaT();
|
||||
setTime();
|
||||
|
||||
// Retrieve primal fields of the time step. Retrieving of the first
|
||||
// time-step of the adjoint loop is also necessary if more than one adjoint
|
||||
// solvers are used. Includes potential recomputation of the primal fields,
|
||||
// depending on the primal storage strategy
|
||||
primalStorage_->retrieveVariables();
|
||||
const Time& time = mesh_.time();
|
||||
Info<< "Time = " << time.timeName() << "\n" << endl;
|
||||
|
||||
// Update objective related fields
|
||||
objectiveManagerPtr_->updateOrNullify();
|
||||
|
||||
// Update turbulence model and ATC related terms
|
||||
incompressibleAdjointSolver::updatePrimalBasedQuantities();
|
||||
|
||||
// Grab primal references
|
||||
const surfaceScalarField& phi = primalVars_.phi();
|
||||
// Grab adjoint references
|
||||
volScalarField& pa = adjointVars_.paInst();
|
||||
volVectorField& Ua = adjointVars_.UaInst();
|
||||
surfaceScalarField& phia = adjointVars_.phiaInst();
|
||||
autoPtr<incompressibleAdjoint::adjointRASModel>& adjointTurbulence =
|
||||
adjointVars_.adjointTurbulence();
|
||||
const label& paRefCell = solverControl_().pRefCell();
|
||||
const scalar& paRefValue = solverControl_().pRefValue();
|
||||
fv::options& fvOptions(fv::options::New(this->mesh_));
|
||||
|
||||
while (solverControl_().loop())
|
||||
{
|
||||
// Momentum predictor
|
||||
//~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
tmp<fvVectorMatrix> tUaEqn
|
||||
(
|
||||
fvm::ddt(Ua) + fvm::div(-phi, Ua)
|
||||
+ adjointTurbulence->divDevReff(Ua)
|
||||
+ adjointTurbulence->adjointMeanFlowSource()
|
||||
==
|
||||
fvOptions(Ua)
|
||||
);
|
||||
fvVectorMatrix& UaEqn = tUaEqn.ref();
|
||||
|
||||
// Add sources from boundary conditions
|
||||
UaEqn.boundaryManipulate(Ua.boundaryFieldRef());
|
||||
|
||||
// Add sources from volume-based objectives
|
||||
objectiveManagerPtr_().addUaEqnSource(UaEqn);
|
||||
|
||||
// Add ATC term
|
||||
ATCModel_->addATC(UaEqn);
|
||||
|
||||
UaEqn.relax();
|
||||
|
||||
fvOptions.constrain(UaEqn);
|
||||
|
||||
if (solverControl_().momentumPredictor())
|
||||
{
|
||||
Foam::solve(UaEqn == -fvc::grad(pa));
|
||||
|
||||
fvOptions.correct(Ua);
|
||||
}
|
||||
|
||||
// Pressure Eq
|
||||
//~~~~~~~~~~~~
|
||||
while (solverControl_().correct())
|
||||
{
|
||||
volScalarField rAUa(1.0/UaEqn.A());
|
||||
volVectorField HabyA(constrainHbyA(rAUa*UaEqn.H(), Ua, pa));
|
||||
surfaceScalarField phiaHbyA
|
||||
(
|
||||
"phiaHbyA",
|
||||
fvc::flux(HabyA)
|
||||
//+ MRF_.zeroFilter(fvc::interpolate(rAU)*fvc::ddtCorr(U, phi))
|
||||
);
|
||||
|
||||
if (pa.needReference())
|
||||
{
|
||||
fvc::makeRelative(phiaHbyA, Ua);
|
||||
adjustPhi(phiaHbyA, Ua, pa);
|
||||
fvc::makeAbsolute(phiaHbyA, Ua);
|
||||
}
|
||||
|
||||
tmp<volScalarField> rAtUa(rAUa);
|
||||
|
||||
if (solverControl_().consistent())
|
||||
{
|
||||
rAtUa = 1.0/max(1.0/rAUa - UaEqn.H1(), 0.1/rAUa);
|
||||
phiaHbyA +=
|
||||
fvc::interpolate(rAtUa() - rAUa)*fvc::snGrad(pa)*mesh_.magSf();
|
||||
HabyA -= (rAUa - rAtUa())*fvc::grad(pa);
|
||||
}
|
||||
|
||||
if (solverControl_().nCorrPISO() <= 1)
|
||||
{
|
||||
tUaEqn.clear();
|
||||
}
|
||||
|
||||
// Non-orthogonal pressure corrector loop
|
||||
while (solverControl_().correctNonOrthogonal())
|
||||
{
|
||||
fvScalarMatrix paEqn
|
||||
(
|
||||
fvm::laplacian(rAtUa(), pa) == fvc::div(phiaHbyA)
|
||||
);
|
||||
|
||||
paEqn.boundaryManipulate(pa.boundaryFieldRef());
|
||||
|
||||
fvOptions.constrain(paEqn);
|
||||
paEqn.setReference(paRefCell, paRefValue);
|
||||
|
||||
paEqn.solve
|
||||
(
|
||||
mesh_.solver(pa.select(solverControl_().finalInnerIter()))
|
||||
);
|
||||
|
||||
if (solverControl_().finalNonOrthogonalIter())
|
||||
{
|
||||
phia = phiaHbyA - paEqn.flux();
|
||||
}
|
||||
}
|
||||
|
||||
continuityErrors();
|
||||
|
||||
// Explicitly relax pressure for momentum corrector
|
||||
pa.relax();
|
||||
|
||||
Ua = HabyA - rAtUa()*fvc::grad(pa);
|
||||
Ua.correctBoundaryConditions();
|
||||
fvOptions.correct(Ua);
|
||||
pa.correctBoundaryConditions();
|
||||
}
|
||||
|
||||
if (solverControl_().turbCorr())
|
||||
{
|
||||
adjointTurbulence->correct();
|
||||
}
|
||||
|
||||
if (solverControl_().printMaxMags())
|
||||
{
|
||||
dimensionedScalar maxUa = max(mag(Ua)());
|
||||
dimensionedScalar maxpa = max(mag(pa)());
|
||||
Info<< "Max mag of adjoint velocity = " << maxUa.value() << endl;
|
||||
Info<< "Max mag of adjoint pressure = " << maxpa.value() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Average fields if necessary
|
||||
adjointVars_.computeMeanUnsteadyFields(timeManip_.primalEndTime());
|
||||
|
||||
// Calls time.write()
|
||||
solverControl_().writeFields();
|
||||
|
||||
// Print execution time
|
||||
time.printExecutionTime(Info);
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPimple::solve()
|
||||
{
|
||||
// Iterate
|
||||
if (active_)
|
||||
{
|
||||
preLoop();
|
||||
while (loop())
|
||||
{
|
||||
solveIter();
|
||||
accumulateSensitivities();
|
||||
}
|
||||
postLoop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::adjointPimple::run()
|
||||
{
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
return time.reverseRun();
|
||||
}
|
||||
|
||||
|
||||
bool Foam::adjointPimple::loop()
|
||||
{
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
// mesh_.time().reverseRun() is actually needed here. Not a mistake.
|
||||
// Chosen for compatibility reasons with the piso algorithm
|
||||
// and the 'solveWithArgs' function at solverTemplates.C
|
||||
return time.reverseRun();
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPimple::preLoop()
|
||||
{
|
||||
// Disable re-writting of primal fields
|
||||
primalVars_.setWriteOption(IOobject::NO_WRITE);
|
||||
|
||||
// Reset time to the beginning of the adjoint loop.
|
||||
// Resets endTime too
|
||||
timeManip_.moveToAdjointStartTime();
|
||||
|
||||
// TODO: To be able to stop the adjoint solution midway and continue
|
||||
// thereafter, the oldTimes of the adjoint fields are required to be
|
||||
// correctly read. Make sure that these are not reset due to change in
|
||||
// time, upon calling oldTime() function.
|
||||
|
||||
// Reset all adjoint fields to zero
|
||||
adjointVars_.nullify();
|
||||
adjointVars_.resetMeanFields();
|
||||
|
||||
// Copy pointers to storage instances and possibly read compressed fields
|
||||
// in cases of restarted runs
|
||||
primalStorage_->preAdjointLoop();
|
||||
|
||||
// The adjoint equations should be also solved at the last primal time-step.
|
||||
// Advance time once more to get to the correct time during the solution
|
||||
// of the first adjoint time-setp
|
||||
const_cast<Time&>(mesh_.time())++;
|
||||
|
||||
// Print out
|
||||
Info<< nl << "- - - - - - - - - - - - - - - - - - - - -" << endl;
|
||||
Info<< "Solving adjoint equations for solver " << solverName() << endl;
|
||||
Info<< "- - - - - - - - - - - - - - - - - - - - -" << nl << endl;
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPimple::postLoop()
|
||||
{
|
||||
// rite adjoint fields at primalEndTime. Although the adjoint equations
|
||||
// are integrated backwards in time starting from primalEndTime and ending
|
||||
// at primalStartTime, the appropriate time to write the adjoint fields is
|
||||
// the primalEndTime. This is not only to have both the primal and adjoint
|
||||
// fields of each optimization cycle written at the same time, but more
|
||||
// importantly to have consistency between the written grid and the adjoint
|
||||
// fields. To do so, reset only the time value to that corresponding to the
|
||||
// end of the primal. Keep the timeIndex unchanged, so that
|
||||
// GeometricField::storeOldTime() function is not called by the time
|
||||
// GeometricField::oldTime() is called from the
|
||||
// incompressibleAdjointVars::write() function. This way, the adjoint
|
||||
// fields will be written correctly in disk without oldTimes to been
|
||||
// shifted
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
timeManip_.moveToAdjointStartTime(false, false);
|
||||
if (!time.writeTime())
|
||||
{
|
||||
adjointVars_.write();
|
||||
}
|
||||
// Completely reset time to that corresponding to the end of the primal
|
||||
// problem.
|
||||
timeManip_.moveToAdjointStartTime();
|
||||
// Write data except for the adjoint fields that have already been written
|
||||
if (!time.writeTime())
|
||||
{
|
||||
adjointVars_.setWriteOption(IOobject::NO_WRITE);
|
||||
time.writeNow();
|
||||
this->writeNow();
|
||||
adjointVars_.setWriteOption(IOobject::AUTO_WRITE);
|
||||
}
|
||||
|
||||
// Print useful info and rewind storage pointers
|
||||
primalStorage_->postAdjointLoop();
|
||||
|
||||
// Compute sensitivities
|
||||
adjointSolver::postLoop();
|
||||
|
||||
//- Re-enable writting of primal fields
|
||||
primalVars_.setWriteOption(IOobject::AUTO_WRITE);
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPimple::postLineSearch()
|
||||
{
|
||||
// Set integration times for the next optimisation cycle
|
||||
objectiveManagerPtr_().incrementIntegrationTimes(timeManip_.span());
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPimple::computeObjectiveSensitivities()
|
||||
{
|
||||
if (computeSensitivities_)
|
||||
{
|
||||
const scalarField& sens = adjointSensitivity_->calculateSensitivities();
|
||||
if (!sensitivities_)
|
||||
{
|
||||
sensitivities_.reset(new scalarField(sens.size(), scalar(0)));
|
||||
}
|
||||
sensitivities_.ref() = sens;
|
||||
}
|
||||
else
|
||||
{
|
||||
sensitivities_.reset(new scalarField(0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const Foam::scalarField& Foam::adjointPimple::getObjectiveSensitivities()
|
||||
{
|
||||
if (!sensitivities_.valid())
|
||||
{
|
||||
computeObjectiveSensitivities();
|
||||
}
|
||||
|
||||
return sensitivities_();
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPimple::clearSensitivities()
|
||||
{
|
||||
if (computeSensitivities_)
|
||||
{
|
||||
adjointSensitivity_->clearSensitivities();
|
||||
adjointSolver::clearSensitivities();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::sensitivity& Foam::adjointPimple::getSensitivityBase()
|
||||
{
|
||||
if (adjointSensitivity_.valid())
|
||||
{
|
||||
return adjointSensitivity_();
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Sensitivity object not allocated \n"
|
||||
<< "Turn computeSensitivities on in "
|
||||
<< solverName_
|
||||
<< nl << nl
|
||||
<< exit(FatalError);
|
||||
|
||||
return adjointSensitivity_();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPimple::updatePrimalBasedQuantities()
|
||||
{
|
||||
// Update turbulence model and ATC related terms
|
||||
incompressibleAdjointSolver::updatePrimalBasedQuantities();
|
||||
|
||||
// Write mean values for all objectives
|
||||
PtrList<objective>& objectives
|
||||
= objectiveManagerPtr_->getObjectiveFunctions();
|
||||
for (objective& obj : objectives)
|
||||
{
|
||||
if (obj.shouldWrite())
|
||||
{
|
||||
obj.writeMeanValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::adjointPimple::writeData(Ostream& os) const
|
||||
{
|
||||
os.writeEntry("averageIter", solverControl_().averageIter());
|
||||
return adjointSolver::writeData(os);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,218 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::adjointPimple
|
||||
|
||||
Description
|
||||
Solution of the incompressible, unsteady adjoint equations using the PIMPLE
|
||||
algorithm
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef adjointPimple_H
|
||||
#define adjointPimple_H
|
||||
|
||||
#include "incompressibleAdjointSolver.H"
|
||||
#include "PIMPLEControl.H"
|
||||
#include "incompressibleVars.H"
|
||||
#include "incompressibleAdjointVars.H"
|
||||
#include "adjointSensitivityIncompressible.H"
|
||||
#include "primalStorage.H"
|
||||
#include "unsteadyTimeManipulation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class adjointPimple Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class adjointPimple
|
||||
:
|
||||
public incompressibleAdjointSolver
|
||||
{
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
adjointPimple(const adjointPimple&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const adjointPimple&) = delete;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Solver control
|
||||
autoPtr<PIMPLEControl> solverControl_;
|
||||
|
||||
//- Reference to incompressibleAdjointVars
|
||||
// Used for convenience and to avoid repetitive dynamic_casts
|
||||
// Same as getAdjointVars()
|
||||
incompressibleAdjointVars& adjointVars_;
|
||||
|
||||
//- Cumulative continuity error
|
||||
scalar cumulativeContErr_;
|
||||
|
||||
//- Sensitivity Derivatives engine
|
||||
autoPtr<incompressible::adjointSensitivity> adjointSensitivity_;
|
||||
|
||||
//- Reference to primal storage mechanism
|
||||
autoPtr<primalStorage>& primalStorage_;
|
||||
|
||||
//- labelList containing all the time-step dependent pointers necessary
|
||||
// for the sucessfull retrieving of the variableSet
|
||||
labelList storagePtrs_;
|
||||
|
||||
//- Time instances and indices at the beginning and end of each
|
||||
//- optimisation loop
|
||||
dimensionedScalar primalEndTime_;
|
||||
|
||||
//- Reference to the deltaTList of the primal solver
|
||||
const DynamicList<scalar>& deltaTList_;
|
||||
|
||||
//- Time manipulation, common for all primal and adjoint solvers
|
||||
unsteadyTimeManipulation& timeManip_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Allocate incompressibleAdjointVars and return reference to be used
|
||||
//- for convenience in the rest of the class.
|
||||
incompressibleAdjointVars& allocateVars();
|
||||
|
||||
//- Reset time-step to maintain a constant maximum courant Number.
|
||||
// Reduction of time-step is immediate, but increase is damped to
|
||||
// avoid unstable oscillations.
|
||||
void setDeltaT();
|
||||
|
||||
//- Decrease time
|
||||
void setTime();
|
||||
|
||||
//- Compute Courant No
|
||||
void CourantNo() const;
|
||||
|
||||
//- Compute continuity errors
|
||||
void continuityErrors();
|
||||
|
||||
//- Accumulate sensitivities from the various time instances
|
||||
void accumulateSensitivities();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("adjointPimple");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from mesh and dictionary
|
||||
adjointPimple
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict,
|
||||
const word& primalSolverName
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~adjointPimple() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual bool readDict(const dictionary& dict);
|
||||
|
||||
// Evolution
|
||||
|
||||
//- Execute one iteration of the solution algorithm
|
||||
virtual void solveIter();
|
||||
|
||||
//- Main control loop
|
||||
virtual void solve();
|
||||
|
||||
//- Looper (advances iters, time step)
|
||||
virtual bool run();
|
||||
|
||||
//- Looper (advances iters, time step)
|
||||
virtual bool loop();
|
||||
|
||||
//- Functions to be called before loop
|
||||
virtual void preLoop();
|
||||
|
||||
//- Functions to be called after loop
|
||||
virtual void postLoop();
|
||||
|
||||
//- Functions to be called after the convergence of linearSearch
|
||||
virtual void postLineSearch();
|
||||
|
||||
//- Compute sensitivities of the underlaying objectives
|
||||
virtual void computeObjectiveSensitivities();
|
||||
|
||||
//- Grab a reference to the computed sensitivities
|
||||
virtual const scalarField& getObjectiveSensitivities();
|
||||
|
||||
//- Clears the sensitivity field known by the adjoint solver
|
||||
//- and zeros sensitivities constituents
|
||||
virtual void clearSensitivities();
|
||||
|
||||
//- Return the base sensitivity object
|
||||
virtual sensitivity& getSensitivityBase();
|
||||
|
||||
//- Update primal based quantities
|
||||
//- related to the objective functions.
|
||||
// Also writes the objective function values to files.
|
||||
// Written here and not in the postLoop function of the primal
|
||||
// to make sure we don't pollute the objective files with
|
||||
// objectives of non-converged linearSearch iterations
|
||||
virtual void updatePrimalBasedQuantities();
|
||||
|
||||
//- Write average iteration
|
||||
virtual bool writeData(Ostream& os) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,576 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "adjointPiso.H"
|
||||
#include "findRefCell.H"
|
||||
#include "constrainHbyA.H"
|
||||
#include "constrainPressure.H"
|
||||
#include "adjustPhi.H"
|
||||
#include "fvOptions.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(adjointPiso, 0);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
incompressibleAdjointSolver,
|
||||
adjointPiso,
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::adjointPiso::printFields()
|
||||
{
|
||||
if (debug > 1)
|
||||
{
|
||||
const word timeName = mesh_.time().timeName();
|
||||
const word prefix = "after solving for t = " + timeName + " ";
|
||||
volScalarField& pa = adjointVars_.paInst();
|
||||
volVectorField& Ua = adjointVars_.UaInst();
|
||||
surfaceScalarField& phia = adjointVars_.phiaInst();
|
||||
Info<< "Debug: Ua.nOldTimes() = " << Ua.nOldTimes() << endl;
|
||||
Info<< "Debug: phia.nOldTimes() = " << phia.nOldTimes() << endl;
|
||||
Info<< prefix << "pa:\n" << pa << endl;
|
||||
Info<< prefix << "Ua:\n" << Ua << endl;
|
||||
Info<< prefix << "Ua.oldTime():\n" << Ua.oldTime() << endl;
|
||||
Info<< prefix << "phia:\n" << phia << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPiso::printPrimalFields()
|
||||
{
|
||||
if (debug > 2)
|
||||
{
|
||||
const word timeName = mesh_.time().timeName();
|
||||
const word prefix = "primal fields for t = " + timeName + " ";
|
||||
volScalarField& p = primalVars_.pInst();
|
||||
volVectorField& U = primalVars_.UInst();
|
||||
surfaceScalarField& phi = primalVars_.phiInst();
|
||||
Info<< prefix << "p:\n" << p << endl;
|
||||
Info<< prefix << "U:\n" << U << endl;
|
||||
Info<< prefix << "phi:\n" << phi << endl;
|
||||
incompressible::RASModelVariables& rasVars =
|
||||
primalVars_.RASModelVariables()();
|
||||
if (rasVars.hasTMVar1())
|
||||
{
|
||||
Info << prefix << " TMVar1:\n" << rasVars.TMVar1Inst() << endl;
|
||||
}
|
||||
if (rasVars.hasTMVar2())
|
||||
{
|
||||
Info << prefix << " TMVar2:\n" << rasVars.TMVar2Inst() << endl;
|
||||
}
|
||||
if (rasVars.hasNut())
|
||||
{
|
||||
Info << prefix << " nut:\n" << rasVars.nutRefInst() << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::incompressibleAdjointVars& Foam::adjointPiso::allocateVars()
|
||||
{
|
||||
vars_.reset
|
||||
(
|
||||
new incompressibleAdjointVars
|
||||
(
|
||||
mesh_,
|
||||
solverControl_(),
|
||||
objectiveManagerPtr_(),
|
||||
primalVars_
|
||||
)
|
||||
);
|
||||
return getAdjointVars();
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPiso::CourantNo() const
|
||||
{
|
||||
const surfaceScalarField& phi = primalVars_.phiInst();
|
||||
const Time& runTime = mesh_.time();
|
||||
const fvMesh& mesh = mesh_;
|
||||
#include "CourantNo.H"
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPiso::continuityErrors()
|
||||
{
|
||||
const surfaceScalarField& phia = adjointVars_.phiaInst();
|
||||
volScalarField contErr(fvc::div(phia));
|
||||
|
||||
scalar sumLocalContErr = mesh_.time().deltaTValue()*
|
||||
mag(contErr)().weightedAverage(mesh_.V()).value();
|
||||
|
||||
scalar globalContErr = mesh_.time().deltaTValue()*
|
||||
contErr.weightedAverage(mesh_.V()).value();
|
||||
cumulativeContErr_ += globalContErr;
|
||||
|
||||
Info<< "time step continuity errors : sum local = " << sumLocalContErr
|
||||
<< ", global = " << globalContErr
|
||||
<< ", cumulative = " << cumulativeContErr_
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPiso::accumulateSensitivities()
|
||||
{
|
||||
if (computeSensitivities_)
|
||||
{
|
||||
adjointSensitivity_->accumulateIntegrand(mesh_.time().deltaTValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::adjointPiso::adjointPiso
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict,
|
||||
const word& primalSolverName
|
||||
)
|
||||
:
|
||||
incompressibleAdjointSolver
|
||||
(
|
||||
mesh,
|
||||
managerType,
|
||||
dict,
|
||||
primalSolverName
|
||||
),
|
||||
solverControl_(PISOControl::New(mesh, managerType, *this)),
|
||||
adjointVars_(allocateVars()),
|
||||
cumulativeContErr_(Zero),
|
||||
adjointSensitivity_(nullptr),
|
||||
primalStorage_(getPrimalSolver().getPrimalStorage()),
|
||||
timeManip_
|
||||
(
|
||||
const_cast<unsteadyTimeManipulation&>
|
||||
(
|
||||
unsteadyTimeManipulation::New(mesh)
|
||||
)
|
||||
)
|
||||
{
|
||||
ATCModel_.reset
|
||||
(
|
||||
ATCModel::New
|
||||
(
|
||||
mesh,
|
||||
primalVars_,
|
||||
adjointVars_,
|
||||
dict.subDict("ATCModel")
|
||||
).ptr()
|
||||
);
|
||||
|
||||
addExtraSchemes();
|
||||
setRefCell
|
||||
(
|
||||
adjointVars_.paInst(),
|
||||
solverControl_().dict(),
|
||||
solverControl_().pRefCell(),
|
||||
solverControl_().pRefValue()
|
||||
);
|
||||
|
||||
if (computeSensitivities_)
|
||||
{
|
||||
const IOdictionary& optDict =
|
||||
mesh.lookupObject<IOdictionary>("optimisationDict");
|
||||
|
||||
adjointSensitivity_.reset
|
||||
(
|
||||
incompressible::adjointSensitivity::New
|
||||
(
|
||||
mesh,
|
||||
optDict.subDict("optimisation").subDict("sensitivities"),
|
||||
*this
|
||||
).ptr()
|
||||
);
|
||||
}
|
||||
|
||||
// Check integration times of the objectives
|
||||
objectiveManagerPtr_().checkIntegrationTimes();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::adjointPiso::readDict(const dictionary& dict)
|
||||
{
|
||||
if (incompressibleAdjointSolver::readDict(dict))
|
||||
{
|
||||
if (adjointSensitivity_.valid())
|
||||
{
|
||||
const IOdictionary& optDict =
|
||||
mesh_.lookupObject<IOdictionary>("optimisationDict");
|
||||
|
||||
adjointSensitivity_().readDict
|
||||
(
|
||||
optDict.subDict("optimisation").subDict("sensitivities")
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPiso::solveIter()
|
||||
{
|
||||
// Retrieve primal fields of the time step. Retrieving of the first
|
||||
// time-step of the adjoint loop is also necessary if more than one adjoint
|
||||
// solvers are used. Includes potential recomputation of the primal fields,
|
||||
// depending on the primal storage strategy
|
||||
primalStorage_->retrieveVariables();
|
||||
const Time& time = mesh_.time();
|
||||
Info << "Time = " << time.timeName() << "\n" << endl;
|
||||
printPrimalFields();
|
||||
|
||||
// Update objective related fields
|
||||
objectiveManagerPtr_->updateOrNullify();
|
||||
|
||||
// Update turbulence model and ATC related terms
|
||||
incompressibleAdjointSolver::updatePrimalBasedQuantities();
|
||||
|
||||
// Grab primal references
|
||||
const surfaceScalarField& phi = primalVars_.phi();
|
||||
// Grab adjoint references
|
||||
volScalarField& pa = adjointVars_.paInst();
|
||||
volVectorField& Ua = adjointVars_.UaInst();
|
||||
surfaceScalarField& phia = adjointVars_.phiaInst();
|
||||
autoPtr<incompressibleAdjoint::adjointRASModel>& adjointTurbulence =
|
||||
adjointVars_.adjointTurbulence();
|
||||
const label& paRefCell = solverControl_().pRefCell();
|
||||
const scalar& paRefValue = solverControl_().pRefValue();
|
||||
fv::options& fvOptions(fv::options::New(this->mesh_));
|
||||
|
||||
CourantNo();
|
||||
|
||||
// Momentum predictor
|
||||
//~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
tmp<fvVectorMatrix> tUaEqn
|
||||
(
|
||||
fvm::ddt(Ua) + fvm::div(-phi, Ua)
|
||||
+ adjointTurbulence->divDevReff(Ua)
|
||||
+ adjointTurbulence->adjointMeanFlowSource()
|
||||
==
|
||||
fvOptions(Ua)
|
||||
);
|
||||
fvVectorMatrix& UaEqn = tUaEqn.ref();
|
||||
|
||||
// Add sources from boundary conditions
|
||||
UaEqn.boundaryManipulate(Ua.boundaryFieldRef());
|
||||
|
||||
// Add sources from volume-based objectives
|
||||
objectiveManagerPtr_().addUaEqnSource(UaEqn);
|
||||
|
||||
// Add ATC term
|
||||
ATCModel_->addATC(UaEqn);
|
||||
|
||||
UaEqn.relax();
|
||||
|
||||
fvOptions.constrain(UaEqn);
|
||||
|
||||
if (solverControl_().momentumPredictor())
|
||||
{
|
||||
Foam::solve(UaEqn == -fvc::grad(pa));
|
||||
|
||||
fvOptions.correct(Ua);
|
||||
}
|
||||
|
||||
// Pressure Eq
|
||||
//~~~~~~~~~~~~
|
||||
while (solverControl_().correct())
|
||||
{
|
||||
volScalarField rAUa(1.0/UaEqn.A());
|
||||
volVectorField HabyA(constrainHbyA(rAUa*UaEqn.H(), Ua, pa));
|
||||
surfaceScalarField phiaHbyA
|
||||
(
|
||||
"phiaHbyA",
|
||||
fvc::flux(HabyA)
|
||||
//+ MRF_.zeroFilter(fvc::interpolate(rAU)*fvc::ddtCorr(U, phi))
|
||||
);
|
||||
adjustPhi(phiaHbyA, Ua, pa);
|
||||
|
||||
// Non-orthogonal pressure corrector loop
|
||||
while (solverControl_().correctNonOrthogonal())
|
||||
{
|
||||
fvScalarMatrix paEqn
|
||||
(
|
||||
fvm::laplacian(rAUa, pa) == fvc::div(phiaHbyA)
|
||||
);
|
||||
|
||||
paEqn.boundaryManipulate(pa.boundaryFieldRef());
|
||||
|
||||
fvOptions.constrain(paEqn);
|
||||
paEqn.setReference(paRefCell, paRefValue);
|
||||
|
||||
paEqn.solve
|
||||
(
|
||||
mesh_.solver(pa.select(solverControl_().finalInnerIter()))
|
||||
);
|
||||
|
||||
if (solverControl_().finalNonOrthogonalIter())
|
||||
{
|
||||
phia = phiaHbyA - paEqn.flux();
|
||||
}
|
||||
}
|
||||
|
||||
continuityErrors();
|
||||
|
||||
Ua = HabyA - rAUa*fvc::grad(pa);
|
||||
Ua.correctBoundaryConditions();
|
||||
fvOptions.correct(Ua);
|
||||
pa.correctBoundaryConditions();
|
||||
}
|
||||
|
||||
adjointTurbulence->correct();
|
||||
|
||||
if (solverControl_().printMaxMags())
|
||||
{
|
||||
dimensionedScalar maxUa = max(mag(Ua)());
|
||||
dimensionedScalar maxpa = max(mag(pa)());
|
||||
Info<< "Max mag of adjoint velocity = " << maxUa.value() << endl;
|
||||
Info<< "Max mag of adjoint pressure = " << maxpa.value() << endl;
|
||||
}
|
||||
|
||||
// Average fields if necessary
|
||||
adjointVars_.computeMeanUnsteadyFields(timeManip_.primalEndTime());
|
||||
|
||||
// Calls time.write()
|
||||
solverControl_().writeFields();
|
||||
|
||||
// Print execution time
|
||||
time.printExecutionTime(Info);
|
||||
|
||||
printFields();
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPiso::solve()
|
||||
{
|
||||
// Iterate
|
||||
if (active_)
|
||||
{
|
||||
preLoop();
|
||||
while (loop())
|
||||
{
|
||||
this->solveIter();
|
||||
accumulateSensitivities();
|
||||
}
|
||||
postLoop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::adjointPiso::loop()
|
||||
{
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
return time.reverseLoop();
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPiso::preLoop()
|
||||
{
|
||||
// Disable re-writting of primal fields
|
||||
primalVars_.setWriteOption(IOobject::NO_WRITE);
|
||||
|
||||
// Reset time to the beginning of the adjoint loop.
|
||||
// Resets endTime too
|
||||
timeManip_.moveToAdjointStartTime();
|
||||
|
||||
// TODO: To be able to stop the adjoint solution midway and continue
|
||||
// thereafter, the oldTimes of the adjoint fields are required to be
|
||||
// correctly read. Make sure that these are not reset due to change in
|
||||
// time, upon calling oldTime() function.
|
||||
|
||||
// Reset all adjoint fields to zero
|
||||
adjointVars_.nullify();
|
||||
adjointVars_.resetMeanFields();
|
||||
|
||||
// Copy pointers to storage instances and possibly read compressed fields
|
||||
// in cases of restarted runs
|
||||
primalStorage_->preAdjointLoop();
|
||||
|
||||
// The adjoint equations should be also solved at the last primal time-step.
|
||||
// Advance time once more to get to the correct time during the solution
|
||||
// of the first adjoint time-setp
|
||||
const_cast<Time&>(mesh_.time())++;
|
||||
|
||||
// Print out
|
||||
Info<< nl << "- - - - - - - - - - - - - - - - - - - - -" << endl;
|
||||
Info<< "Solving adjoint equations for solver " << solverName() << endl;
|
||||
Info<< "- - - - - - - - - - - - - - - - - - - - -" << nl << endl;
|
||||
|
||||
printFields();
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPiso::postLoop()
|
||||
{
|
||||
// Write adjoint fields at primalEndTime. Although the adjoint equations
|
||||
// are integrated backwards in time starting from primalEndTime and ending
|
||||
// at primalStartTime, the appropriate time to write the adjoint fields is
|
||||
// the primalEndTime. This is not only to have both the primal and adjoint
|
||||
// fields of each optimization cycle written at the same time, but more
|
||||
// importantly to have consistency between the written grid and the adjoint
|
||||
// fields. To do so, reset only the time value to that corresponding to the
|
||||
// end of the primal. Keep the timeIndex unchanged, so that
|
||||
// GeometricField::storeOldTime() is not called by the time
|
||||
// GeometricField::oldTime() is called from
|
||||
// incompressibleAdjointVars::write(). This way, the adjoint
|
||||
// fields will be written correctly in disk without oldTimes been
|
||||
// shifted
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
timeManip_.moveToAdjointStartTime(false, false);
|
||||
if (!time.writeTime())
|
||||
{
|
||||
adjointVars_.write();
|
||||
}
|
||||
// Completely reset time to that corresponding to the end of the primal
|
||||
// problem.
|
||||
timeManip_.moveToAdjointStartTime();
|
||||
// Write data except for the adjoint fields that have already been written
|
||||
if (!time.writeTime())
|
||||
{
|
||||
adjointVars_.setWriteOption(IOobject::NO_WRITE);
|
||||
time.writeNow();
|
||||
this->writeNow();
|
||||
adjointVars_.setWriteOption(IOobject::AUTO_WRITE);
|
||||
}
|
||||
|
||||
// Print useful info and rewind storage pointers
|
||||
primalStorage_->postAdjointLoop();
|
||||
|
||||
// Compute sensitivities
|
||||
adjointSolver::postLoop();
|
||||
|
||||
// Re-enable writting of primal fields
|
||||
primalVars_.setWriteOption(IOobject::AUTO_WRITE);
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPiso::postLineSearch()
|
||||
{
|
||||
// Set integration times for the next optimisation cycle
|
||||
objectiveManagerPtr_().incrementIntegrationTimes(timeManip_.span());
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPiso::computeObjectiveSensitivities()
|
||||
{
|
||||
if (computeSensitivities_)
|
||||
{
|
||||
const scalarField& sens = adjointSensitivity_->calculateSensitivities();
|
||||
if (!sensitivities_)
|
||||
{
|
||||
sensitivities_.reset(new scalarField(sens.size(), scalar(0)));
|
||||
}
|
||||
sensitivities_.ref() = sens;
|
||||
}
|
||||
else
|
||||
{
|
||||
sensitivities_.reset(new scalarField(0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const Foam::scalarField& Foam::adjointPiso::getObjectiveSensitivities()
|
||||
{
|
||||
if (!sensitivities_.valid())
|
||||
{
|
||||
computeObjectiveSensitivities();
|
||||
}
|
||||
|
||||
return sensitivities_();
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPiso::clearSensitivities()
|
||||
{
|
||||
if (computeSensitivities_)
|
||||
{
|
||||
adjointSensitivity_->clearSensitivities();
|
||||
adjointSolver::clearSensitivities();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::sensitivity& Foam::adjointPiso::getSensitivityBase()
|
||||
{
|
||||
if (adjointSensitivity_.valid())
|
||||
{
|
||||
return adjointSensitivity_();
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Sensitivity object not allocated \n"
|
||||
<< "Turn computeSensitivities on in "
|
||||
<< solverName_
|
||||
<< nl << nl
|
||||
<< exit(FatalError);
|
||||
|
||||
return adjointSensitivity_();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointPiso::updatePrimalBasedQuantities()
|
||||
{
|
||||
// Update turbulence model and ATC related terms
|
||||
incompressibleAdjointSolver::updatePrimalBasedQuantities();
|
||||
|
||||
// Write mean values for all objectives
|
||||
PtrList<objective>& objectives
|
||||
= objectiveManagerPtr_->getObjectiveFunctions();
|
||||
for (objective& obj : objectives)
|
||||
{
|
||||
if (obj.shouldWrite())
|
||||
{
|
||||
obj.writeMeanValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::adjointPiso::writeData(Ostream& os) const
|
||||
{
|
||||
os.writeEntry("averageIter", solverControl_().averageIter());
|
||||
return adjointSolver::writeData(os);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,202 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::adjointPiso
|
||||
|
||||
Description
|
||||
Solution of the incompressible, unsteady adjoint equations using the PISO
|
||||
algorithm
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef adjointPiso_H
|
||||
#define adjointPiso_H
|
||||
|
||||
#include "incompressibleAdjointSolver.H"
|
||||
#include "PISOControl.H"
|
||||
#include "incompressibleVars.H"
|
||||
#include "incompressibleAdjointVars.H"
|
||||
#include "adjointSensitivityIncompressible.H"
|
||||
#include "primalStorage.H"
|
||||
#include "unsteadyTimeManipulation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class adjointPiso Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class adjointPiso
|
||||
:
|
||||
public incompressibleAdjointSolver
|
||||
{
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
adjointPiso(const adjointPiso&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const adjointPiso&) = delete;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Solver control
|
||||
autoPtr<PISOControl> solverControl_;
|
||||
|
||||
//- Reference to incompressibleAdjointVars
|
||||
// Used for convenience and to avoid repetitive dynamic_casts
|
||||
// Same as getAdjointVars()
|
||||
incompressibleAdjointVars& adjointVars_;
|
||||
|
||||
//- Cumulative continuity error
|
||||
scalar cumulativeContErr_;
|
||||
|
||||
//- Sensitivity Derivatives engine
|
||||
autoPtr<incompressible::adjointSensitivity> adjointSensitivity_;
|
||||
|
||||
//- Reference to primal storage mechanism
|
||||
autoPtr<primalStorage>& primalStorage_;
|
||||
|
||||
//- Time manipulation, common for all primal and adjoint solvers
|
||||
unsteadyTimeManipulation& timeManip_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Print adjoint fields if in debug mode
|
||||
void printFields();
|
||||
|
||||
//- Print primal fields if in debug mode
|
||||
void printPrimalFields();
|
||||
|
||||
//- Allocate incompressibleAdjointVars and return reference to be used
|
||||
//- for convenience in the rest of the class.
|
||||
incompressibleAdjointVars& allocateVars();
|
||||
|
||||
//- Compute Courant No
|
||||
void CourantNo() const;
|
||||
|
||||
//- Compute continuity errors
|
||||
void continuityErrors();
|
||||
|
||||
//- Accumulate sensitivities from the various time instances
|
||||
void accumulateSensitivities();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("adjointPiso");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from mesh and dictionary
|
||||
adjointPiso
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict,
|
||||
const word& primalSolverName
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~adjointPiso() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual bool readDict(const dictionary& dict);
|
||||
|
||||
// Evolution
|
||||
|
||||
//- Execute one iteration of the solution algorithm
|
||||
virtual void solveIter();
|
||||
|
||||
//- Main control loop
|
||||
virtual void solve();
|
||||
|
||||
//- Looper (advances iters, time step)
|
||||
virtual bool loop();
|
||||
|
||||
//- Functions to be called before loop
|
||||
virtual void preLoop();
|
||||
|
||||
//- Functions to be called after loop
|
||||
virtual void postLoop();
|
||||
|
||||
//- Functions to be called after the convergence of linearSearch
|
||||
virtual void postLineSearch();
|
||||
|
||||
//- Compute sensitivities of the underlaying objectives
|
||||
virtual void computeObjectiveSensitivities();
|
||||
|
||||
//- Grab a reference to the computed sensitivities
|
||||
virtual const scalarField& getObjectiveSensitivities();
|
||||
|
||||
//- Clears the sensitivity field known by the adjoint solver
|
||||
//- and zeros sensitivities constituents
|
||||
virtual void clearSensitivities();
|
||||
|
||||
//- Return the base sensitivity object
|
||||
virtual sensitivity& getSensitivityBase();
|
||||
|
||||
//- Update primal based quantities
|
||||
//- related to the objective functions.
|
||||
// Also writes the objective function values to files.
|
||||
// Written here and not in the postLoop function of the primal
|
||||
// to make sure we don't pollute the objective files with
|
||||
// objectives of non-converged linearSearch iterations
|
||||
virtual void updatePrimalBasedQuantities();
|
||||
|
||||
//- Write average iteration
|
||||
virtual bool writeData(Ostream& os) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -66,20 +66,6 @@ Foam::incompressibleAdjointVars& Foam::adjointSimple::allocateVars()
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointSimple::addExtraSchemes()
|
||||
{
|
||||
if (adjointVars_.useSolverNameForFields())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "useSolverNameForFields is set to true for adjointSolver "
|
||||
<< solverName() << nl << tab
|
||||
<< "Appending variable names with the solver name" << nl << tab
|
||||
<< "Please adjust the necessary entries in fvSchemes and fvSolution"
|
||||
<< nl << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::adjointSimple::continuityErrors()
|
||||
{
|
||||
const surfaceScalarField& phia = adjointVars_.phiaInst();
|
||||
|
||||
@ -103,13 +103,6 @@ protected:
|
||||
//- for convenience in the rest of the class.
|
||||
incompressibleAdjointVars& allocateVars();
|
||||
|
||||
//- In case variable names are different than the base ones,
|
||||
//- add extra schemes and relaxation factors to the appropriate dicts
|
||||
// Note: 160813: Changes in the baseline solution and fvSchemes classes
|
||||
// have to be made in order to add schemes in the dict at run time.
|
||||
// Not supported for now
|
||||
void addExtraSchemes();
|
||||
|
||||
//- Compute continuity errors
|
||||
void continuityErrors();
|
||||
|
||||
|
||||
@ -47,6 +47,22 @@ namespace Foam
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::incompressibleAdjointSolver::addExtraSchemes()
|
||||
{
|
||||
if (vars_().useSolverNameForFields())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "useSolverNameForFields is set to true for adjointSolver "
|
||||
<< solverName() << nl << tab
|
||||
<< "Appending variable names with the solver name" << nl << tab
|
||||
<< "Please adjust the necessary entries in fvSchemes and fvSolution"
|
||||
<< nl << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::incompressibleAdjointSolver::incompressibleAdjointSolver
|
||||
|
||||
@ -80,6 +80,15 @@ protected:
|
||||
autoPtr<ATCModel> ATCModel_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- In case variable names are different than the base ones,
|
||||
//- add extra schemes and relaxation factors to the appropriate dicts
|
||||
// Note: 160813: Changes in the baseline solution and fvSchemes classes
|
||||
// have to be made in order to add schemes in the dict at run time.
|
||||
// Not supported for now
|
||||
void addExtraSchemes();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
|
||||
@ -61,10 +61,11 @@ Foam::RASTurbulenceModel::RASTurbulenceModel
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime
|
||||
)
|
||||
:
|
||||
incompressiblePrimalSolver(mesh, managerType, dict),
|
||||
incompressiblePrimalSolver(mesh, managerType, dict, useCustomReadTime),
|
||||
solverControl_(SIMPLEControl::New(mesh, managerType, *this)),
|
||||
incoVars_(allocateVars())
|
||||
{
|
||||
|
||||
@ -98,7 +98,8 @@ public:
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime = false
|
||||
);
|
||||
|
||||
|
||||
|
||||
@ -48,6 +48,21 @@ namespace Foam
|
||||
);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::incompressiblePrimalSolver::addExtraSchemes()
|
||||
{
|
||||
if (vars_().useSolverNameForFields())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "useSolverNameForFields is set to true for primalSolver "
|
||||
<< solverName() << nl << tab
|
||||
<< "Appending variable names with the solver name" << nl << tab
|
||||
<< "Please adjust the necessary entries in fvSchemes and fvSolution"
|
||||
<< nl << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
@ -55,10 +70,11 @@ Foam::incompressiblePrimalSolver::incompressiblePrimalSolver
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime
|
||||
)
|
||||
:
|
||||
primalSolver(mesh, managerType, dict),
|
||||
primalSolver(mesh, managerType, dict, useCustomReadTime),
|
||||
phiReconstructionTol_
|
||||
(
|
||||
dict.subOrEmptyDict("fieldReconstruction").
|
||||
@ -79,7 +95,8 @@ Foam::incompressiblePrimalSolver::New
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime
|
||||
)
|
||||
{
|
||||
const word solverType(dict.get<word>("solver"));
|
||||
@ -99,7 +116,7 @@ Foam::incompressiblePrimalSolver::New
|
||||
return
|
||||
autoPtr<incompressiblePrimalSolver>
|
||||
(
|
||||
ctorPtr(mesh, managerType, dict)
|
||||
ctorPtr(mesh, managerType, dict, useCustomReadTime)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -77,6 +77,14 @@ protected:
|
||||
label phiReconstructionIters_;
|
||||
|
||||
|
||||
//- Protected Member Functions
|
||||
|
||||
//- In case variable names are different than the base ones,
|
||||
//- add extra schemes and relaxation factors to the appropriate dicts
|
||||
// Note: Not supported for now
|
||||
void addExtraSchemes();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@ -96,9 +104,10 @@ public:
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime
|
||||
),
|
||||
(mesh, managerType, dict)
|
||||
(mesh, managerType, dict, useCustomReadTime)
|
||||
);
|
||||
|
||||
|
||||
@ -109,7 +118,8 @@ public:
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime = false
|
||||
);
|
||||
|
||||
|
||||
@ -120,7 +130,8 @@ public:
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime = false
|
||||
);
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,686 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "pimple.H"
|
||||
#include "findRefCell.H"
|
||||
#include "constrainHbyA.H"
|
||||
#include "constrainPressure.H"
|
||||
#include "adjustPhi.H"
|
||||
#include "CorrectPhi.H"
|
||||
#include "Time.H"
|
||||
#include "fvOptions.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(pimple, 0);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
incompressiblePrimalSolver,
|
||||
pimple,
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::incompressibleVars& Foam::pimple::allocateVars(scalar readTime)
|
||||
{
|
||||
vars_.reset(new incompressibleVars(mesh_, solverControl_(), readTime));
|
||||
return getIncoVars();
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::readTimeControls()
|
||||
{
|
||||
// Original function at
|
||||
// src/finiteVolume/cfdTools/general/include/readTimeControls.H
|
||||
const Time& runTime = mesh_.time();
|
||||
bool& adjustTimeStep = adjustTimeStep_;
|
||||
scalar& maxCo = maxCo_;
|
||||
scalar& maxDeltaT = maxDeltaT_;
|
||||
#include "readTimeControls.H"
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::CourantNo()
|
||||
{
|
||||
// Original function at
|
||||
// src/finiteVolume/cfdTools/incompressible/CourantNo.H
|
||||
const surfaceScalarField& phi = incoVars_.phiInst();
|
||||
const Time& runTime = mesh_.time();
|
||||
const fvMesh& mesh = mesh_;
|
||||
#include "CourantNo.H"
|
||||
CoNum_ = CoNum;
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::continuityErrors()
|
||||
{
|
||||
// Original function at
|
||||
// src/finiteVolume/cfdTools/incompressible/continuityErrs.H
|
||||
const Time& runTime = mesh_.time();
|
||||
const fvMesh& mesh = mesh_;
|
||||
const surfaceScalarField& phi = incoVars_.phiInst();
|
||||
scalar& cumulativeContErr = cumulativeContErr_;
|
||||
#include "continuityErrs.H"
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::setDeltaT()
|
||||
{
|
||||
// Original function at
|
||||
// src/finiteVolume/cfdTools/general/include/setDeltaT.H
|
||||
Time& runTime = const_cast<Time&>(mesh_.time());
|
||||
bool& adjustTimeStep = adjustTimeStep_;
|
||||
scalar& maxCo = maxCo_;
|
||||
scalar& maxDeltaT = maxDeltaT_;
|
||||
scalar& CoNum = CoNum_;
|
||||
#include "setDeltaT.H"
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::setInitialDeltaT()
|
||||
{
|
||||
// Original function at
|
||||
// src/finiteVolume/cfdTools/general/include/setInitialDeltaT.H
|
||||
Time& runTime = const_cast<Time&>(mesh_.time());
|
||||
const bool& adjustTimeStep = adjustTimeStep_;
|
||||
const scalar& CoNum = CoNum_;
|
||||
const scalar& maxCo = maxCo_;
|
||||
const scalar& maxDeltaT = maxDeltaT_;
|
||||
#include "setInitialDeltaT.H"
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::setTime()
|
||||
{
|
||||
Time& runTime = const_cast<Time&>(mesh_.time());
|
||||
++runTime;
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::storeDeltaT()
|
||||
{
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
if (adjustTimeStep_)
|
||||
{
|
||||
DebugInfo
|
||||
<< "time.timeIndex() - primalStartTimeIndex = "
|
||||
<< time.timeIndex() - timeManip_.startTimeIndex() << nl
|
||||
<< "time.timeIndex(), primalStartTimeIndex = "
|
||||
<< time.timeIndex() << " " << timeManip_.startTimeIndex()
|
||||
<< endl;
|
||||
if
|
||||
(
|
||||
deltaTList_.empty()
|
||||
&& (time.timeIndex() > timeManip_.startTimeIndex())
|
||||
)
|
||||
{
|
||||
deltaTList_.
|
||||
setSize
|
||||
(
|
||||
time.timeIndex() - timeManip_.startTimeIndex(),
|
||||
deltaT0_
|
||||
);
|
||||
}
|
||||
deltaTList_.append(time.deltaTValue());
|
||||
}
|
||||
DebugInfo
|
||||
<< "deltaTList.size() = " << deltaTList_.size() << endl;
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::scratchDeltaTHistory()
|
||||
{
|
||||
const Time& time = mesh_.time();
|
||||
deltaT0_ = time.deltaTValue();
|
||||
primalStartTimeIndex_ = time.timeIndex();
|
||||
deltaTList_.clear();
|
||||
}
|
||||
|
||||
|
||||
const Foam::DynamicList<Foam::scalar>& Foam::pimple::getDeltaTList() const
|
||||
{
|
||||
return deltaTList_;
|
||||
}
|
||||
|
||||
|
||||
/*void Foam::pimple::readDyMControls()
|
||||
{
|
||||
// Original function at src/dynamicFvMesh/include/readDyMControls.H
|
||||
// Original function at
|
||||
// src/finiteVolume/cfdTools/general/include/readTimeControls.H
|
||||
const Time& runTime = mesh_.time();
|
||||
const PIMPLEControl& pimple = solverControl_();
|
||||
bool& moveMeshOuterCorrectors = moveMeshOuterCorrectors_;
|
||||
bool& checkMeshCourantNo = checkMeshCourantNo_;
|
||||
bool& correctPhi = correctPhi_;
|
||||
bool& adjustTimeStep = adjustTimeStep_;
|
||||
scalar& maxCo = maxCo_;
|
||||
scalar& maxDeltaT = maxDeltaT_;
|
||||
#include "readDyMControls.H"
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::meshCourantNo()
|
||||
{
|
||||
// Original function at src/dynamicFvMesh/include/meshCourantNo.H
|
||||
const Time& runTime = mesh_.time();
|
||||
const fvMesh& mesh = mesh_;
|
||||
#include "meshCourantNo.H"
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::correctPhi()
|
||||
{
|
||||
// Original function at the location of the solver
|
||||
// CorrectPhi at src/finiteVolume/cfdTools/general/CorrectPhi/CorrectPhi.H
|
||||
volScalarField& p = incoVars_.pInst();
|
||||
volVectorField& U = incoVars_.UInst();
|
||||
surfaceScalarField& phi = incoVars_.phiInst();
|
||||
CorrectPhi
|
||||
(
|
||||
U,
|
||||
phi,
|
||||
p,
|
||||
dimensionedScalar("rAUf", dimTime, 1),
|
||||
geometricZeroField(),
|
||||
solverControl_()
|
||||
);
|
||||
continuityErrors();
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::createUfIfPresent()
|
||||
{
|
||||
// Original function at
|
||||
// src/finiteVolume/cfdTools/incompressible/createUfIfPresent.H
|
||||
if (mesh_.dynamic())
|
||||
{
|
||||
volVectorField& U = incoVars_.UInst();
|
||||
|
||||
Info<< "Constructing face velocity Uf\n" << endl;
|
||||
|
||||
Uf_.reset
|
||||
(
|
||||
new surfaceVectorField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"Uf",
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
fvc::interpolate(U)
|
||||
)
|
||||
);
|
||||
}
|
||||
}*/
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pimple::pimple
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime
|
||||
)
|
||||
:
|
||||
incompressiblePrimalSolver
|
||||
(
|
||||
mesh,
|
||||
managerType,
|
||||
dict,
|
||||
useCustomReadTime
|
||||
),
|
||||
solverControl_(PIMPLEControl::New(mesh, managerType, *this)),
|
||||
shouldResetMeanFields_(useCustomReadTime),
|
||||
incoVars_
|
||||
(
|
||||
allocateVars
|
||||
(
|
||||
useCustomReadTime ? dict.getOrDefault<scalar>("readTime", 0) : -1
|
||||
)
|
||||
),
|
||||
MRF_(mesh, word(useSolverNameForFields() ? solverName() : word::null)),
|
||||
cumulativeContErr_(Zero),
|
||||
objectives_(0),
|
||||
adjustTimeStep_
|
||||
(
|
||||
mesh.time().controlDict().getOrDefault("adjustTimeStep", false)
|
||||
),
|
||||
maxCo_
|
||||
(
|
||||
mesh.time().controlDict().getOrDefault<scalar>("maxCo", 1.0)
|
||||
),
|
||||
maxDeltaT_
|
||||
(
|
||||
mesh.time().controlDict().getOrDefault<scalar>("maxDeltaT", GREAT)
|
||||
),
|
||||
primalStartTimeIndex_(mesh_.time().timeIndex()),
|
||||
deltaTList_(0),
|
||||
timeManip_
|
||||
(
|
||||
const_cast<unsteadyTimeManipulation&>
|
||||
(
|
||||
unsteadyTimeManipulation::New(mesh)
|
||||
)
|
||||
)
|
||||
/*correctPhi_
|
||||
(
|
||||
solverControl_().dict().getOrDefault("correctPhi", mesh_.dynamic())
|
||||
),
|
||||
checkMeshCourantNo_
|
||||
(
|
||||
solverControl_().dict().getOrDefault("checkMeshCourantNo", false)
|
||||
),
|
||||
moveMeshOuterCorrectors_
|
||||
(
|
||||
solverControl_().dict().getOrDefault("moveMeshOuterCorrectors", false)
|
||||
)*/
|
||||
{
|
||||
addExtraSchemes();
|
||||
setRefCell
|
||||
(
|
||||
incoVars_.pInst(),
|
||||
solverControl_().dict(),
|
||||
solverControl_().pRefCell(),
|
||||
solverControl_().pRefValue()
|
||||
);
|
||||
|
||||
// Decide primal storage mechanism
|
||||
if (dict.isDict("storage"))
|
||||
{
|
||||
primalStorage_.reset
|
||||
(
|
||||
primalStorage::New(*this, dict.subDict("storage"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::pimple::readDict(const dictionary& dict)
|
||||
{
|
||||
if (incompressiblePrimalSolver::readDict(dict))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::solveIter()
|
||||
{
|
||||
const Time& time = mesh_.time();
|
||||
//readDyMControls();
|
||||
readTimeControls();
|
||||
setDeltaT();
|
||||
storeDeltaT();
|
||||
setTime();
|
||||
|
||||
// The primal solution at the first time-step does not need to be stored.
|
||||
// When checkpointing is used, the checkpoint at the first time step must
|
||||
// be set, else storeInitialVariables() does nothing
|
||||
if (primalStorage_.valid())
|
||||
{
|
||||
if (time.timeIndex() == timeManip_.startTimeIndex() + 1)
|
||||
{
|
||||
primalStorage_().storeInitialVariables();
|
||||
}
|
||||
else
|
||||
{
|
||||
primalStorage_().storeVariables();
|
||||
}
|
||||
}
|
||||
Info<< "Time = " << mesh_.time().timeName() << "\n" << endl;
|
||||
|
||||
// Grab references
|
||||
volScalarField& p = incoVars_.pInst();
|
||||
volVectorField& U = incoVars_.UInst();
|
||||
surfaceScalarField& phi = incoVars_.phiInst();
|
||||
autoPtr<incompressible::turbulenceModel>& turbulence =
|
||||
incoVars_.turbulence();
|
||||
label& pRefCell = solverControl_().pRefCell();
|
||||
scalar& pRefValue = solverControl_().pRefValue();
|
||||
fv::options& fvOptions(fv::options::New(this->mesh_));
|
||||
|
||||
CourantNo();
|
||||
|
||||
while (solverControl_().loop())
|
||||
{
|
||||
// No moving geometries supported for now
|
||||
/*
|
||||
if (solverControl_().firstIter() || moveMeshOuterCorrectors_)
|
||||
{
|
||||
//mesh_.update();
|
||||
|
||||
if (mesh_.changing())
|
||||
{
|
||||
MRF_.update();
|
||||
|
||||
if (correctPhi_)
|
||||
{
|
||||
// Calculate absolute flux
|
||||
// from the mapped surface velocity
|
||||
phi = mesh_.Sf() & Uf_();
|
||||
|
||||
correctPhi();
|
||||
|
||||
// Make the flux relative to the mesh motion
|
||||
fvc::makeRelative(phi, U);
|
||||
}
|
||||
if (checkMeshCourantNo_)
|
||||
{
|
||||
meshCourantNo();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Momentum predictor
|
||||
//~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
MRF_.correctBoundaryVelocity(U);
|
||||
|
||||
tmp<fvVectorMatrix> tUEqn
|
||||
(
|
||||
fvm::ddt(U) + fvm::div(phi, U)
|
||||
+ MRF_.DDt(U)
|
||||
+ turbulence->divDevReff(U)
|
||||
==
|
||||
fvOptions(U)
|
||||
);
|
||||
fvVectorMatrix& UEqn = tUEqn.ref();
|
||||
|
||||
UEqn.relax();
|
||||
|
||||
fvOptions.constrain(UEqn);
|
||||
|
||||
if (solverControl_().momentumPredictor())
|
||||
{
|
||||
Foam::solve(UEqn == -fvc::grad(p));
|
||||
|
||||
fvOptions.correct(U);
|
||||
}
|
||||
// Pressure Eq
|
||||
//~~~~~~~~~~~~
|
||||
while (solverControl_().correct())
|
||||
{
|
||||
volScalarField rAU(1.0/UEqn.A());
|
||||
volVectorField HbyA(constrainHbyA(rAU*UEqn.H(), U, p));
|
||||
surfaceScalarField phiHbyA
|
||||
(
|
||||
"phiHbyA",
|
||||
fvc::flux(HbyA)
|
||||
+ MRF_.zeroFilter(fvc::interpolate(rAU)*fvc::ddtCorr(U, phi, Uf_))
|
||||
);
|
||||
|
||||
MRF_.makeRelative(phiHbyA);
|
||||
|
||||
if (p.needReference())
|
||||
{
|
||||
fvc::makeRelative(phiHbyA, U);
|
||||
adjustPhi(phiHbyA, U, p);
|
||||
fvc::makeAbsolute(phiHbyA, U);
|
||||
}
|
||||
|
||||
tmp<volScalarField> rAtU(rAU);
|
||||
|
||||
if (solverControl_().consistent())
|
||||
{
|
||||
rAtU = 1.0/max(1.0/rAU - UEqn.H1(), 0.1/rAU);
|
||||
phiHbyA +=
|
||||
fvc::interpolate(rAtU() - rAU)*fvc::snGrad(p)*mesh_.magSf();
|
||||
HbyA -= (rAU - rAtU())*fvc::grad(p);
|
||||
}
|
||||
|
||||
if (solverControl_().nCorrPISO() <= 1)
|
||||
{
|
||||
tUEqn.clear();
|
||||
}
|
||||
|
||||
// Update the pressure BCs to ensure flux consistency
|
||||
constrainPressure(p, U, phiHbyA, rAtU(), MRF_);
|
||||
|
||||
// Non-orthogonal pressure corrector loop
|
||||
while (solverControl_().correctNonOrthogonal())
|
||||
{
|
||||
fvScalarMatrix pEqn
|
||||
(
|
||||
fvm::laplacian(rAtU(), p) == fvc::div(phiHbyA)
|
||||
);
|
||||
|
||||
pEqn.setReference(pRefCell, pRefValue);
|
||||
|
||||
fvOptions.constrain(pEqn);
|
||||
|
||||
pEqn.solve
|
||||
(
|
||||
mesh_.solver(p.select(solverControl_().finalInnerIter()))
|
||||
);
|
||||
|
||||
if (solverControl_().finalNonOrthogonalIter())
|
||||
{
|
||||
phi = phiHbyA - pEqn.flux();
|
||||
}
|
||||
}
|
||||
|
||||
continuityErrors();
|
||||
|
||||
// Explicitly relax pressure for momentum corrector
|
||||
p.relax();
|
||||
|
||||
U = HbyA - rAtU*fvc::grad(p);
|
||||
U.correctBoundaryConditions();
|
||||
fvOptions.correct(U);
|
||||
|
||||
// Correct Uf if the mesh is moving
|
||||
fvc::correctUf(Uf_, U, phi);
|
||||
|
||||
// Make the fluxes relative to the mesh motion
|
||||
fvc::makeRelative(phi, U);
|
||||
}
|
||||
|
||||
if (solverControl_().turbCorr())
|
||||
{
|
||||
incoVars_.laminarTransport().correct();
|
||||
turbulence->correct();
|
||||
}
|
||||
}
|
||||
|
||||
// Print objective values to screen and compute mean value
|
||||
Info<< nl;
|
||||
for (objective* obj : objectives_)
|
||||
{
|
||||
Info<< obj->objectiveName() << " : " << obj->J() << endl;
|
||||
obj->accumulateJMean();
|
||||
obj->writeInstantaneousValue();
|
||||
}
|
||||
|
||||
// Average fields if necessary
|
||||
incoVars_.computeMeanUnsteadyFields();
|
||||
|
||||
// Calls time.write()
|
||||
solverControl_().writeFields();
|
||||
|
||||
// Print execution time
|
||||
time.printExecutionTime(Info);
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::solve()
|
||||
{
|
||||
// Iterate
|
||||
if (active_)
|
||||
{
|
||||
preLoop();
|
||||
while (loop())
|
||||
{
|
||||
solveIter();
|
||||
}
|
||||
postLoop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::pimple::run()
|
||||
{
|
||||
//return solverControl_().run();
|
||||
return mesh_.time().run();
|
||||
}
|
||||
|
||||
|
||||
bool Foam::pimple::loop()
|
||||
{
|
||||
// mesh_.time().run() is actually needed here. Not a mistake.
|
||||
// Chosen for compatibility reasons with the simple and piso algorithms
|
||||
// and the 'solveWithArgs' function at solverTemplates.C
|
||||
return mesh_.time().run();
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::restoreInitValues()
|
||||
{
|
||||
incoVars_.restoreInitValues();
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::preLoop()
|
||||
{
|
||||
// Move to the correct time, if changed by a previous primal solver
|
||||
timeManip_.moveToPrimalStartTime();
|
||||
|
||||
// Get the objectives for this solver
|
||||
if (objectives_.empty())
|
||||
{
|
||||
objectives_ = getObjectiveFunctions();
|
||||
}
|
||||
|
||||
// Reset initial and mean fields before solving
|
||||
restoreInitValues();
|
||||
if (shouldResetMeanFields_)
|
||||
{
|
||||
incoVars_.resetMeanFields();
|
||||
}
|
||||
|
||||
// Validate turbulence model fields
|
||||
incoVars_.turbulence()->validate();
|
||||
|
||||
// nullify JMean for all objectives
|
||||
for (objective* obj : objectives_)
|
||||
{
|
||||
obj->resetJMean();
|
||||
}
|
||||
|
||||
// Reset primal storage
|
||||
if (primalStorage_.valid())
|
||||
{
|
||||
primalStorage_().scratch();
|
||||
}
|
||||
scratchDeltaTHistory();
|
||||
CourantNo();
|
||||
//createUfIfPresent();
|
||||
setInitialDeltaT();
|
||||
|
||||
// Print out
|
||||
Info<< nl << "- - - - - - - - - - - - - - - - - - - - -" << endl;
|
||||
Info<< "Solving primal equations for solver " << solverName() << endl;
|
||||
Info<< "- - - - - - - - - - - - - - - - - - - - -" << nl << endl;
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::postLoop()
|
||||
{
|
||||
// Store last time instance. Redundant if a single adjoint solver is used,
|
||||
// but necessary for more than one adjoint solvers
|
||||
if (primalStorage_.valid())
|
||||
{
|
||||
// Advance time to avoid implications with the checkpointing
|
||||
// implementation and store variables
|
||||
timeManip_.storeTime();
|
||||
const_cast<Time&>(mesh_.time())++;
|
||||
primalStorage_().storeVariables();
|
||||
|
||||
// Retrive time
|
||||
timeManip_.restoreTime();
|
||||
|
||||
// Print storage metrics
|
||||
primalStorage_().storageMetrics();
|
||||
}
|
||||
|
||||
// Write separators in objective files
|
||||
for (objective* obj : objectives_)
|
||||
{
|
||||
obj->writeInstantaneousSeparator();
|
||||
}
|
||||
// Safety
|
||||
objectives_.clear();
|
||||
|
||||
// Avoid writting fields if already in an outputTime iter
|
||||
// since results will be written by the solver class either way
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
if (!time.writeTime())
|
||||
{
|
||||
// Write all fields
|
||||
time.writeNow();
|
||||
// Write dummy turbulence fields if multiple primal solvers exist
|
||||
this->writeNow();
|
||||
}
|
||||
|
||||
// Allow mean fields to be zeroed at the next call of preLoop
|
||||
shouldResetMeanFields_ = true;
|
||||
|
||||
// Store endTimeIndex, to be retrieved later by the adjoint
|
||||
timeManip_.storeEndTimeIndex();
|
||||
}
|
||||
|
||||
|
||||
void Foam::pimple::postLineSearch()
|
||||
{
|
||||
// Update averaging window for the next optimisation cycle
|
||||
solverControl_().updateAverageStartTime();
|
||||
}
|
||||
|
||||
|
||||
bool Foam::pimple::writeData(Ostream& os) const
|
||||
{
|
||||
os.writeEntry("averageIter", solverControl_().averageIter());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,240 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::pimple
|
||||
|
||||
Description
|
||||
Base class for solution control classes
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef pimple_H
|
||||
#define pimple_H
|
||||
|
||||
#include "incompressiblePrimalSolver.H"
|
||||
#include "PIMPLEControl.H"
|
||||
#include "IOMRFZoneList.H"
|
||||
#include "objective.H"
|
||||
#include "unsteadyTimeManipulation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class pimple Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class pimple
|
||||
:
|
||||
public incompressiblePrimalSolver
|
||||
{
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
pimple(const pimple&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const pimple&) = delete;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Solver control
|
||||
autoPtr<PIMPLEControl> solverControl_;
|
||||
|
||||
//- Boolean defining if primal fields will be initialized from
|
||||
// the current or a costum time-step provided by the user
|
||||
Switch shouldResetMeanFields_;
|
||||
|
||||
//- Reference to incompressibleVars
|
||||
// Used for convenience and to avoid repetitive dynamic_casts
|
||||
// Same as getIncoVars()
|
||||
incompressibleVars& incoVars_;
|
||||
|
||||
//- MRF zones
|
||||
IOMRFZoneList MRF_;
|
||||
|
||||
//- Cumulative continuity error
|
||||
scalar cumulativeContErr_;
|
||||
|
||||
//- List of objectives related to this primal solver
|
||||
List<objective*> objectives_;
|
||||
|
||||
//- Boolean and scalar entries for readDyMControls and
|
||||
// setDeltaT functions
|
||||
bool adjustTimeStep_;
|
||||
scalar maxCo_;
|
||||
scalar maxDeltaT_;
|
||||
scalar CoNum_;
|
||||
/*bool correctPhi_;
|
||||
bool checkMeshCourantNo_;
|
||||
bool moveMeshOuterCorrectors_;*/
|
||||
|
||||
//- velocity field Uf (set only if required)
|
||||
autoPtr<surfaceVectorField> Uf_;
|
||||
|
||||
scalar deltaT0_;
|
||||
|
||||
//- Time-index at the beggining of the primal solution
|
||||
label primalStartTimeIndex_;
|
||||
|
||||
//- List with deltaT values during the solution of the primal problem
|
||||
DynamicList<scalar> deltaTList_;
|
||||
|
||||
//- Time manipulation, common for all primal and adjoint solvers
|
||||
unsteadyTimeManipulation& timeManip_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Allocate incompressibleVars and return reference to be used for
|
||||
//- convenience in the rest of the class.
|
||||
incompressibleVars& allocateVars(scalar readTime);
|
||||
|
||||
//- Read only the control parameters used by setDeltaT
|
||||
void readTimeControls();
|
||||
|
||||
//- Compute Courant No
|
||||
void CourantNo();
|
||||
|
||||
//- Compute continuity errors
|
||||
void continuityErrors();
|
||||
|
||||
//- Reset time-step to maintain a constant maximum courant Number.
|
||||
// Reduction of time-step is immediate, but increase is damped to
|
||||
// avoid unstable oscillations.
|
||||
void setDeltaT();
|
||||
|
||||
//- Set the initial timestep corresponding to the timestep
|
||||
// adjustment algorithm in setDeltaT but only if it would
|
||||
// reduce the timestep.
|
||||
void setInitialDeltaT();
|
||||
|
||||
//- Increase time
|
||||
void setTime();
|
||||
|
||||
//- Store the current deltaT
|
||||
void storeDeltaT();
|
||||
|
||||
//- Scratch deltaTList_ and deltaT0_
|
||||
void scratchDeltaTHistory();
|
||||
|
||||
/*
|
||||
//- Read among other the control parameters used by setDeltaT
|
||||
void readDyMControls();
|
||||
|
||||
//- Calculates and outputs the mean and maximum Courant Numbers.
|
||||
void meshCourantNo();
|
||||
|
||||
//- Flux correction functions to ensure continuity
|
||||
void correctPhi();
|
||||
|
||||
//- Creates and initialises the velocity field Uf if required.
|
||||
void createUfIfPresent();
|
||||
*/
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("pimple");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from mesh and dictionary
|
||||
pimple
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime = false
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~pimple() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual bool readDict(const dictionary& dict) override;
|
||||
|
||||
// Evolution
|
||||
|
||||
//- Execute one iteration of the solution algorithm
|
||||
virtual void solveIter() override;
|
||||
|
||||
//- Main control loop
|
||||
virtual void solve() override;
|
||||
|
||||
//- Looper (advances iters, time step)
|
||||
virtual bool run();
|
||||
virtual bool loop() override;
|
||||
|
||||
//- Restore initial field values if necessary
|
||||
virtual void restoreInitValues() override;
|
||||
|
||||
//- Functions to be called before loop
|
||||
virtual void preLoop() override;
|
||||
|
||||
//- Functions to be called after loop
|
||||
virtual void postLoop() override;
|
||||
|
||||
//- Functions to be called after lineSearch has converged
|
||||
virtual void postLineSearch() override;
|
||||
|
||||
//- Write average iteration
|
||||
virtual bool writeData(Ostream& os) const override;
|
||||
|
||||
|
||||
// Info to the AdjointSolver
|
||||
|
||||
//- Return a scalarList with all deltaT of the primal solution
|
||||
const DynamicList<scalar>& getDeltaTList() const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,467 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "piso.H"
|
||||
#include "findRefCell.H"
|
||||
#include "constrainHbyA.H"
|
||||
#include "constrainPressure.H"
|
||||
#include "adjustPhi.H"
|
||||
#include "Time.H"
|
||||
#include "fvOptions.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "profiling.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(piso, 0);
|
||||
addToRunTimeSelectionTable(incompressiblePrimalSolver, piso, dictionary);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::piso::printFields()
|
||||
{
|
||||
if (debug > 1)
|
||||
{
|
||||
const word timeName = mesh_.time().timeName();
|
||||
const word prefix = "after solving for t = " + timeName + " ";
|
||||
volScalarField& p = incoVars_.pInst();
|
||||
volVectorField& U = incoVars_.UInst();
|
||||
surfaceScalarField& phi = incoVars_.phiInst();
|
||||
Info<< "Debug: U.nOldTimes() = " << U.nOldTimes() << endl;
|
||||
Info<< "Debug: phi.nOldTimes() = " << phi.nOldTimes() << endl;
|
||||
Info<< prefix << "p:\n" << p << endl;
|
||||
Info<< prefix << "U:\n" << U << endl;
|
||||
Info<< prefix << "U.oldTime():\n" << U.oldTime() << endl;
|
||||
Info<< prefix << "phi:\n" << phi << endl;
|
||||
Info<< prefix << "phi.oldTime():\n" << phi.oldTime() << endl;
|
||||
incompressible::RASModelVariables& rasVars =
|
||||
incoVars_.RASModelVariables()();
|
||||
if (rasVars.hasTMVar1())
|
||||
{
|
||||
Info<< "Debug: TMVar1.nOldTimes() = "
|
||||
<< rasVars.TMVar1Inst().nOldTimes() << endl;
|
||||
Info<< prefix << " TMVar1:\n" << rasVars.TMVar1Inst() << endl;
|
||||
Info<< prefix << " TMVar1.oldTime():\n"
|
||||
<< rasVars.TMVar1Inst().oldTime() << endl;
|
||||
}
|
||||
if (rasVars.hasTMVar2())
|
||||
{
|
||||
Info<< "Debug: TMVar2.nOldTimes() = "
|
||||
<< rasVars.TMVar2Inst().nOldTimes() << endl;
|
||||
Info<< prefix << " TMVar2:\n" << rasVars.TMVar2Inst() << endl;
|
||||
Info<< prefix << " TMVar2.oldTime():\n"
|
||||
<< rasVars.TMVar2Inst().oldTime() << endl;
|
||||
}
|
||||
if (rasVars.hasNut())
|
||||
{
|
||||
Info << prefix << " nut:\n" << rasVars.nutRefInst() << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::incompressibleVars& Foam::piso::allocateVars(scalar readTime)
|
||||
{
|
||||
vars_.reset(new incompressibleVars(mesh_, solverControl_(), readTime));
|
||||
return getIncoVars();
|
||||
}
|
||||
|
||||
|
||||
void Foam::piso::CourantNo() const
|
||||
{
|
||||
const surfaceScalarField& phi = incoVars_.phiInst();
|
||||
const Time& runTime = mesh_.time();
|
||||
const fvMesh& mesh = mesh_;
|
||||
#include "CourantNo.H"
|
||||
}
|
||||
|
||||
|
||||
void Foam::piso::continuityErrors()
|
||||
{
|
||||
// Original function at
|
||||
// src/finiteVolume/cfdTools/incompressible/continuityErrs.H
|
||||
const Time& runTime = mesh_.time();
|
||||
const fvMesh& mesh = mesh_;
|
||||
const surfaceScalarField& phi = incoVars_.phiInst();
|
||||
scalar& cumulativeContErr = cumulativeContErr_;
|
||||
#include "continuityErrs.H"
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::piso::piso
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime
|
||||
)
|
||||
:
|
||||
incompressiblePrimalSolver
|
||||
(
|
||||
mesh,
|
||||
managerType,
|
||||
dict,
|
||||
useCustomReadTime
|
||||
),
|
||||
solverControl_(PISOControl::New(mesh, managerType, *this)),
|
||||
shouldResetMeanFields_(useCustomReadTime),
|
||||
incoVars_
|
||||
(
|
||||
allocateVars
|
||||
(
|
||||
useCustomReadTime ? dict.getOrDefault<scalar>("readTime", 0) : -1
|
||||
)
|
||||
),
|
||||
MRF_(mesh, word(useSolverNameForFields() ? solverName() : word::null)),
|
||||
cumulativeContErr_(Zero),
|
||||
objectives_(0),
|
||||
timeManip_
|
||||
(
|
||||
const_cast<unsteadyTimeManipulation&>
|
||||
(
|
||||
unsteadyTimeManipulation::New(mesh)
|
||||
)
|
||||
)
|
||||
{
|
||||
addExtraSchemes();
|
||||
setRefCell
|
||||
(
|
||||
incoVars_.pInst(),
|
||||
solverControl_().dict(),
|
||||
solverControl_().pRefCell(),
|
||||
solverControl_().pRefValue()
|
||||
);
|
||||
|
||||
// Decide primal storage mechanism
|
||||
if (dict.isDict("storage"))
|
||||
{
|
||||
primalStorage_.reset
|
||||
(
|
||||
primalStorage::New(*this, dict.subDict("storage"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::piso::readDict(const dictionary& dict)
|
||||
{
|
||||
if (incompressiblePrimalSolver::readDict(dict))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::piso::solveIter()
|
||||
{
|
||||
addProfiling(piso, "piso::solveIter()");
|
||||
const Time& time = mesh_.time();
|
||||
// The primal solution at the first time-step does not need to be stored.
|
||||
// However, when checkpointing is used, the checkpoint at the first time
|
||||
// step must be set; storeInitialVariables() does nothing in other cases.
|
||||
// Note: would make sense to be at the end of the iteration but
|
||||
// checkpoint intricaties suggest it should remain here
|
||||
if (primalStorage_.valid())
|
||||
{
|
||||
if (time.timeIndex() == timeManip_.startTimeIndex() + 1)
|
||||
{
|
||||
primalStorage_().storeInitialVariables();
|
||||
}
|
||||
else
|
||||
{
|
||||
primalStorage_().storeVariables();
|
||||
}
|
||||
}
|
||||
Info<< "Time = " << mesh_.time().timeName() << "\n" << endl;
|
||||
|
||||
// Grab references
|
||||
volScalarField& p = incoVars_.pInst();
|
||||
volVectorField& U = incoVars_.UInst();
|
||||
surfaceScalarField& phi = incoVars_.phiInst();
|
||||
autoPtr<incompressible::turbulenceModel>& turbulence =
|
||||
incoVars_.turbulence();
|
||||
label& pRefCell = solverControl_().pRefCell();
|
||||
scalar& pRefValue = solverControl_().pRefValue();
|
||||
fv::options& fvOptions(fv::options::New(this->mesh_));
|
||||
|
||||
CourantNo();
|
||||
|
||||
// Momentum predictor
|
||||
//~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
MRF_.correctBoundaryVelocity(U);
|
||||
|
||||
tmp<fvVectorMatrix> tUEqn
|
||||
(
|
||||
fvm::ddt(U) + fvm::div(phi, U)
|
||||
+ MRF_.DDt(U)
|
||||
+ turbulence->divDevReff(U)
|
||||
==
|
||||
fvOptions(U)
|
||||
);
|
||||
fvVectorMatrix& UEqn = tUEqn.ref();
|
||||
|
||||
UEqn.relax();
|
||||
|
||||
fvOptions.constrain(UEqn);
|
||||
|
||||
if (solverControl_().momentumPredictor())
|
||||
{
|
||||
Foam::solve(UEqn == -fvc::grad(p));
|
||||
|
||||
fvOptions.correct(U);
|
||||
}
|
||||
|
||||
// Pressure Eq
|
||||
//~~~~~~~~~~~~
|
||||
while (solverControl_().correct())
|
||||
{
|
||||
volScalarField rAU(1.0/UEqn.A());
|
||||
volVectorField HbyA(constrainHbyA(rAU*UEqn.H(), U, p));
|
||||
surfaceScalarField phiHbyA
|
||||
(
|
||||
"phiHbyA",
|
||||
fvc::flux(HbyA)
|
||||
+ MRF_.zeroFilter(fvc::interpolate(rAU)*fvc::ddtCorr(U, phi))
|
||||
);
|
||||
|
||||
MRF_.makeRelative(phiHbyA);
|
||||
|
||||
adjustPhi(phiHbyA, U, p);
|
||||
|
||||
// Update the pressure BCs to ensure flux consistency
|
||||
constrainPressure(p, U, phiHbyA, rAU, MRF_);
|
||||
|
||||
// Non-orthogonal pressure corrector loop
|
||||
while (solverControl_().correctNonOrthogonal())
|
||||
{
|
||||
fvScalarMatrix pEqn
|
||||
(
|
||||
fvm::laplacian(rAU, p) == fvc::div(phiHbyA)
|
||||
);
|
||||
|
||||
pEqn.setReference(pRefCell, pRefValue);
|
||||
|
||||
fvOptions.constrain(pEqn);
|
||||
|
||||
pEqn.solve
|
||||
(
|
||||
mesh_.solver(p.select(solverControl_().finalInnerIter()))
|
||||
);
|
||||
|
||||
if (solverControl_().finalNonOrthogonalIter())
|
||||
{
|
||||
phi = phiHbyA - pEqn.flux();
|
||||
}
|
||||
}
|
||||
|
||||
continuityErrors();
|
||||
|
||||
U = HbyA - rAU*fvc::grad(p);
|
||||
U.correctBoundaryConditions();
|
||||
fvOptions.correct(U);
|
||||
}
|
||||
// An extra correction of the BC of p would be necessary to have
|
||||
// consistency for p upon reconstruction during the adjoint run.
|
||||
// However, this would slightly affect the primal solution, which is
|
||||
// something we want to avoid. A small inconsistency between the field
|
||||
// computed by the primal solver and the reconstructed one may occur, when
|
||||
// BCs depending on the flux value (e.g. outletInlet) are used. To avoid
|
||||
// this inconsistency activate 'storeAllBoundaries' in the storade
|
||||
// subdictionary, although this means that all field boundaries will be
|
||||
// stored and the correctBCs will not be called upon reconstruction.
|
||||
// p.correctBoundaryConditions();
|
||||
|
||||
incoVars_.laminarTransport().correct();
|
||||
turbulence->correct();
|
||||
|
||||
// Print objective values to screen and compute mean value
|
||||
Info<< endl;
|
||||
for (objective* obj : objectives_)
|
||||
{
|
||||
Info<< obj->objectiveName() << " : " << obj->J() << endl;
|
||||
obj->accumulateJMean();
|
||||
obj->writeInstantaneousValue();
|
||||
}
|
||||
|
||||
// Average fields if necessary
|
||||
incoVars_.computeMeanUnsteadyFields();
|
||||
|
||||
// Calls time.write()
|
||||
solverControl_().writeFields();
|
||||
|
||||
// Print execution time
|
||||
time.printExecutionTime(Info);
|
||||
|
||||
printFields();
|
||||
}
|
||||
|
||||
|
||||
void Foam::piso::solve()
|
||||
{
|
||||
// Iterate
|
||||
if (active_)
|
||||
{
|
||||
preLoop();
|
||||
while (loop())
|
||||
{
|
||||
this->solveIter();
|
||||
}
|
||||
postLoop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::piso::loop()
|
||||
{
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
return time.loop();
|
||||
}
|
||||
|
||||
|
||||
void Foam::piso::restoreInitValues()
|
||||
{
|
||||
incoVars_.restoreInitValues();
|
||||
}
|
||||
|
||||
|
||||
void Foam::piso::preLoop()
|
||||
{
|
||||
// Move to the correct time, if changed by a previous primal solver
|
||||
timeManip_.moveToPrimalStartTime();
|
||||
|
||||
// Get the objectives for this solver
|
||||
if (objectives_.empty())
|
||||
{
|
||||
objectives_ = getObjectiveFunctions();
|
||||
}
|
||||
|
||||
// Reset initial and mean fields before solving
|
||||
restoreInitValues();
|
||||
if (shouldResetMeanFields_)
|
||||
{
|
||||
incoVars_.resetMeanFields();
|
||||
}
|
||||
|
||||
// Validate turbulence model fields
|
||||
incoVars_.turbulence()->validate();
|
||||
|
||||
// nullify JMean for all objectives
|
||||
// Note: we should cover the same of continuing avegaring the objective
|
||||
// after a primal restart
|
||||
for (objective* obj : objectives_)
|
||||
{
|
||||
obj->resetJMean();
|
||||
}
|
||||
|
||||
// Reset primal storage
|
||||
if (primalStorage_.valid())
|
||||
{
|
||||
primalStorage_().scratch();
|
||||
}
|
||||
|
||||
// Print out
|
||||
Info<< nl << "- - - - - - - - - - - - - - - - - - - - -" << endl;
|
||||
Info<< "Solving primal equations for solver " << solverName() << endl;
|
||||
Info<< "- - - - - - - - - - - - - - - - - - - - -" << nl << endl;
|
||||
|
||||
printFields();
|
||||
}
|
||||
|
||||
|
||||
void Foam::piso::postLoop()
|
||||
{
|
||||
addProfiling(piso, "piso::postLoop()");
|
||||
// Store last time instance. Redundant if a single adjoint solver is used,
|
||||
// but necessary for more than one adjoint solvers
|
||||
if (primalStorage_.valid())
|
||||
{
|
||||
// Advance time to avoid implications with the checkpointing
|
||||
// implementation and store variables
|
||||
timeManip_.storeTime();
|
||||
const_cast<Time&>(mesh_.time())++;
|
||||
primalStorage_().storeVariables();
|
||||
|
||||
// Restore time
|
||||
timeManip_.restoreTime();
|
||||
|
||||
primalStorage_().storageMetrics();
|
||||
}
|
||||
// Write separators in objective files
|
||||
for (objective* obj : objectives_)
|
||||
{
|
||||
obj->writeInstantaneousSeparator();
|
||||
}
|
||||
// Safety
|
||||
objectives_.clear();
|
||||
|
||||
// Avoid writting fields if already in an outputTime iter
|
||||
// since results will be written by the solver class either way
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
if (!time.writeTime())
|
||||
{
|
||||
// Write all fields
|
||||
time.writeNow();
|
||||
// Write dummy turbulence fields if multiple primal solvers exist,
|
||||
// to support seamless restarts
|
||||
this->writeNow();
|
||||
}
|
||||
|
||||
// Allow mean fields to be zeroed at the next call of preLoop
|
||||
shouldResetMeanFields_ = true;
|
||||
|
||||
// Store endTimeIndex, to be retrieved later by the adjoint
|
||||
timeManip_.storeEndTimeIndex();
|
||||
}
|
||||
|
||||
|
||||
void Foam::piso::postLineSearch()
|
||||
{
|
||||
// Update averaging window for the next optimisation cycle
|
||||
solverControl_().updateAverageStartTime();
|
||||
}
|
||||
|
||||
|
||||
bool Foam::piso::writeData(Ostream& os) const
|
||||
{
|
||||
os.writeEntry("averageIter", solverControl_().averageIter());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,178 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::piso
|
||||
|
||||
Description
|
||||
Base class for solution control classes
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef piso_H
|
||||
#define piso_H
|
||||
|
||||
#include "incompressiblePrimalSolver.H"
|
||||
#include "PISOControl.H"
|
||||
#include "IOMRFZoneList.H"
|
||||
#include "objective.H"
|
||||
#include "unsteadyTimeManipulation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class piso Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class piso
|
||||
:
|
||||
public incompressiblePrimalSolver
|
||||
{
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
piso(const piso&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const piso&) = delete;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Solver control
|
||||
autoPtr<PISOControl> solverControl_;
|
||||
|
||||
//- Boolean defining if primal fields will be initialized from
|
||||
// the current or a costum time-step provided by the user
|
||||
Switch shouldResetMeanFields_;
|
||||
|
||||
//- Reference to incompressibleVars
|
||||
// Used for convenience and to avoid repetitive dynamic_casts
|
||||
// Same as getIncoVars()
|
||||
incompressibleVars& incoVars_;
|
||||
|
||||
//- MRF zones
|
||||
IOMRFZoneList MRF_;
|
||||
|
||||
//- Cumulative continuity error
|
||||
scalar cumulativeContErr_;
|
||||
|
||||
//- List of objectives related to this primal solver
|
||||
List<objective*> objectives_;
|
||||
|
||||
//- Time manipulation, common for all primal and adjoint solvers
|
||||
unsteadyTimeManipulation& timeManip_;
|
||||
|
||||
|
||||
//- Protected Member Functions
|
||||
|
||||
//- Print flow fields if in debug mode
|
||||
void printFields();
|
||||
|
||||
//- Allocate incompressibleVars and return reference to be used for
|
||||
//- convenience in the rest of the class.
|
||||
incompressibleVars& allocateVars(scalar readTime);
|
||||
|
||||
//- Compute Courant No
|
||||
void CourantNo() const;
|
||||
|
||||
//- Compute continuity errors
|
||||
void continuityErrors();
|
||||
|
||||
public:
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("piso");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from mesh and dictionary
|
||||
piso
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime = false
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~piso() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual bool readDict(const dictionary& dict);
|
||||
|
||||
// Evolution
|
||||
|
||||
//- Execute one iteration of the solution algorithm
|
||||
virtual void solveIter() override;
|
||||
|
||||
//- Main control loop
|
||||
virtual void solve() override;
|
||||
|
||||
//- Looper (advances iters, time step)
|
||||
virtual bool loop() override;
|
||||
|
||||
//- Restore initial field values if necessary
|
||||
virtual void restoreInitValues() override;
|
||||
|
||||
//- Functions to be called before loop
|
||||
virtual void preLoop() override;
|
||||
|
||||
//- Functions to be called after loop
|
||||
virtual void postLoop() override;
|
||||
|
||||
//- Functions to be called after lineSearch has converged
|
||||
virtual void postLineSearch() override;
|
||||
|
||||
//- Write average iteration
|
||||
virtual bool writeData(Ostream& os) const override;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -53,20 +53,6 @@ Foam::incompressibleVars& Foam::simple::allocateVars()
|
||||
}
|
||||
|
||||
|
||||
void Foam::simple::addExtraSchemes()
|
||||
{
|
||||
if (incoVars_.useSolverNameForFields())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "useSolverNameForFields is set to true for primalSolver "
|
||||
<< solverName() << nl << tab
|
||||
<< "Appending variable names with the solver name" << nl << tab
|
||||
<< "Please adjust the necessary entries in fvSchemes and fvSolution"
|
||||
<< nl << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::simple::continuityErrors()
|
||||
{
|
||||
surfaceScalarField& phi = incoVars_.phiInst();
|
||||
@ -92,10 +78,11 @@ Foam::simple::simple
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime
|
||||
)
|
||||
:
|
||||
incompressiblePrimalSolver(mesh, managerType, dict),
|
||||
incompressiblePrimalSolver(mesh, managerType, dict, useCustomReadTime),
|
||||
solverControl_(SIMPLEControl::New(mesh, managerType, *this)),
|
||||
incoVars_(allocateVars()),
|
||||
MRF_(mesh, word(useSolverNameForFields() ? solverName() : word::null)),
|
||||
|
||||
@ -93,11 +93,6 @@ protected:
|
||||
//- convenience in the rest of the class.
|
||||
incompressibleVars& allocateVars();
|
||||
|
||||
//- In case variable names are different than the base ones,
|
||||
//- add extra schemes and relaxation factors to the appropriate dicts
|
||||
// Note: Not supported for now
|
||||
void addExtraSchemes();
|
||||
|
||||
//- Compute continuity errors
|
||||
void continuityErrors();
|
||||
|
||||
@ -117,7 +112,8 @@ public:
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime = false
|
||||
);
|
||||
|
||||
|
||||
|
||||
@ -46,10 +46,12 @@ Foam::primalSolver::primalSolver
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime
|
||||
)
|
||||
:
|
||||
solver(mesh, managerType, dict)
|
||||
solver(mesh, managerType, dict),
|
||||
primalStorage_(nullptr)
|
||||
{}
|
||||
|
||||
|
||||
@ -59,7 +61,8 @@ Foam::autoPtr<Foam::primalSolver> Foam::primalSolver::New
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime
|
||||
)
|
||||
{
|
||||
const word solverType(dict.get<word>("type"));
|
||||
@ -77,7 +80,11 @@ Foam::autoPtr<Foam::primalSolver> Foam::primalSolver::New
|
||||
) << exit(FatalIOError);
|
||||
}
|
||||
|
||||
return autoPtr<primalSolver>(ctorPtr(mesh, managerType, dict));
|
||||
return
|
||||
autoPtr<primalSolver>
|
||||
(
|
||||
ctorPtr(mesh, managerType, dict, useCustomReadTime)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -94,6 +101,12 @@ bool Foam::primalSolver::readDict(const dictionary& dict)
|
||||
}
|
||||
|
||||
|
||||
Foam::autoPtr<Foam::primalStorage>& Foam::primalSolver::getPrimalStorage()
|
||||
{
|
||||
return primalStorage_;
|
||||
}
|
||||
|
||||
|
||||
void Foam::primalSolver::correctBoundaryConditions()
|
||||
{
|
||||
// Do nothing
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
||||
Copyright (C) 2013-2019 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -40,6 +40,7 @@ Description
|
||||
#include "fvMesh.H"
|
||||
#include "solver.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
#include "primalStorage.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -65,6 +66,16 @@ private:
|
||||
void operator=(const primalSolver&) = delete;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Variables
|
||||
|
||||
//- Primal storage strategy
|
||||
// For stroring the primal history, to be later used by the
|
||||
// unsteady adjoint solvers
|
||||
autoPtr<primalStorage> primalStorage_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@ -84,9 +95,10 @@ public:
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime
|
||||
),
|
||||
(mesh, managerType, dict)
|
||||
(mesh, managerType, dict, useCustomReadTime)
|
||||
);
|
||||
|
||||
|
||||
@ -97,7 +109,8 @@ public:
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime = false
|
||||
);
|
||||
|
||||
|
||||
@ -108,7 +121,8 @@ public:
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const dictionary& dict
|
||||
const dictionary& dict,
|
||||
Switch useCustomReadTime = false
|
||||
);
|
||||
|
||||
|
||||
@ -120,6 +134,9 @@ public:
|
||||
|
||||
virtual bool readDict(const dictionary& dict);
|
||||
|
||||
//- Reference to the primal storage method
|
||||
autoPtr<primalStorage>& getPrimalStorage();
|
||||
|
||||
|
||||
// Evolution
|
||||
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
||||
Copyright (C) 2013-2019 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -146,6 +146,12 @@ void Foam::solver::postLoop()
|
||||
}
|
||||
|
||||
|
||||
void Foam::solver::postLineSearch()
|
||||
{
|
||||
// Does nothing in the base class
|
||||
}
|
||||
|
||||
|
||||
void Foam::solver::updateOptTypeSource
|
||||
(
|
||||
const autoPtr<volScalarField>& optSourcePtr
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
||||
Copyright (C) 2013-2019 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -165,6 +165,9 @@ public:
|
||||
//- Functions to be called after loop
|
||||
virtual void postLoop();
|
||||
|
||||
//- Functions to be called after lineSearch has converged
|
||||
virtual void postLineSearch();
|
||||
|
||||
//- Update source term related to optimisationType
|
||||
void updateOptTypeSource
|
||||
(
|
||||
|
||||
@ -0,0 +1,143 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "PIMPLEControl.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(PIMPLEControl, 0);
|
||||
defineRunTimeSelectionTable(PIMPLEControl, dictionary);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::PIMPLEControl::PIMPLEControl
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
)
|
||||
:
|
||||
solverControl(solver),
|
||||
pimpleControl(mesh, "PIMPLE", false),
|
||||
managerType_(managerType),
|
||||
pRefCell_(Zero),
|
||||
pRefValue_(Zero),
|
||||
timeManip_
|
||||
(
|
||||
const_cast<unsteadyTimeManipulation&>
|
||||
(
|
||||
unsteadyTimeManipulation::New(mesh)
|
||||
)
|
||||
)
|
||||
{
|
||||
read();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::PIMPLEControl> Foam::PIMPLEControl::New
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
)
|
||||
{
|
||||
auto* ctorPtr = dictionaryConstructorTable(managerType);
|
||||
|
||||
if (!ctorPtr)
|
||||
{
|
||||
FatalErrorInLookup
|
||||
(
|
||||
"control",
|
||||
managerType,
|
||||
*dictionaryConstructorTablePtr_
|
||||
) << exit(FatalError);
|
||||
}
|
||||
|
||||
return autoPtr<PIMPLEControl>(ctorPtr(mesh, managerType, solver));
|
||||
}
|
||||
|
||||
|
||||
bool Foam::PIMPLEControl::read()
|
||||
{
|
||||
pimpleControl::read();
|
||||
solverControl::read();
|
||||
|
||||
// Always store initial field values in unsteady runs
|
||||
storeInitValues_ = true;
|
||||
|
||||
/*Info<< nl << algorithmName_;
|
||||
|
||||
if (nCorrPIMPLE_ > 1)
|
||||
{
|
||||
if (residualControl_.empty())
|
||||
{
|
||||
Info<< ": no residual control data found. "
|
||||
<< "Calculations will employ " << nCorrPIMPLE_
|
||||
<< " corrector loops" << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< ": max iterations = " << nCorrPIMPLE_ << nl;
|
||||
|
||||
for (const fieldData& ctrl : residualControl_)
|
||||
{
|
||||
Info<< " field " << ctrl.name << token::TAB
|
||||
<< ": relTol " << ctrl.relTol
|
||||
<< ", tolerance " << ctrl.absTol
|
||||
<< nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< ": Operating solver in PISO mode" << nl;
|
||||
}
|
||||
|
||||
Info<< endl;*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::PIMPLEControl::updateAverageStartTime()
|
||||
{
|
||||
averageStartTime_ += timeManip_.span();
|
||||
DebugInfo
|
||||
<< "Set averageStartTime to " << averageStartTime_ << endl;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,185 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::PIMPLEControl
|
||||
|
||||
Description
|
||||
PIMPLE control class to supply convergence information/checks for
|
||||
the PIMPLE loop.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef PIMPLEControl_H
|
||||
#define PIMPLEControl_H
|
||||
|
||||
#include "solverControl.H"
|
||||
#include "pimpleControl.H"
|
||||
#include "unsteadyTimeManipulation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class PIMPLEControl Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class PIMPLEControl
|
||||
:
|
||||
public solverControl,
|
||||
public pimpleControl
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Optimisation type
|
||||
const word& managerType_;
|
||||
|
||||
//- Pressure reference cell
|
||||
label pRefCell_;
|
||||
//
|
||||
//- Pressure reference value
|
||||
scalar pRefValue_;
|
||||
|
||||
//- Time manipulation during unsteady optimisation
|
||||
unsteadyTimeManipulation& timeManip_;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
//- No copy construct
|
||||
PIMPLEControl(const PIMPLEControl&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const PIMPLEControl&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("PIMPLEControl");
|
||||
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
PIMPLEControl,
|
||||
dictionary,
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
),
|
||||
(mesh, managerType, solver)
|
||||
);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from mesh
|
||||
PIMPLEControl
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~PIMPLEControl() = default;
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Return a reference to the selected turbulence model
|
||||
static autoPtr<PIMPLEControl> New
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual bool read();
|
||||
|
||||
// Access
|
||||
|
||||
//- Return the solution dictionary
|
||||
inline virtual const dictionary dict() const;
|
||||
|
||||
//- Return pressure reference cell
|
||||
inline label& pRefCell();
|
||||
|
||||
//- Return pressure reference value
|
||||
inline scalar& pRefValue();
|
||||
|
||||
//- Return the time span of each optimisation cycle
|
||||
inline scalar timeSpan() const;
|
||||
|
||||
//- Update the start time of averaging for the next opt. cycle
|
||||
void updateAverageStartTime();
|
||||
|
||||
|
||||
// Solution control
|
||||
|
||||
//- Whether to call time.write() or not
|
||||
virtual void writeFields() = 0;
|
||||
|
||||
//- Use averaged fields?
|
||||
// For solving the adjoint equations or computing sensitivities
|
||||
// based on averaged fields
|
||||
inline bool useAveragedFields() const;
|
||||
|
||||
// Evolution
|
||||
|
||||
//- Loop
|
||||
virtual bool loop() = 0;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
#include "PIMPLEControlI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,61 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
inline const Foam::dictionary Foam::PIMPLEControl::dict() const
|
||||
{
|
||||
return solutionDict();
|
||||
}
|
||||
|
||||
|
||||
inline Foam::label& Foam::PIMPLEControl::pRefCell()
|
||||
{
|
||||
return pRefCell_;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalar& Foam::PIMPLEControl::pRefValue()
|
||||
{
|
||||
return pRefValue_;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalar Foam::PIMPLEControl::timeSpan() const
|
||||
{
|
||||
return timeManip_.span();
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::PIMPLEControl::useAveragedFields() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,71 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "PIMPLEControlOpt.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "Time.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(PIMPLEControlOpt, 0);
|
||||
addToRunTimeSelectionTable(PIMPLEControl, PIMPLEControlOpt, dictionary);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::PIMPLEControlOpt::PIMPLEControlOpt
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
)
|
||||
:
|
||||
PIMPLEControl(mesh, managerType, solver)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::PIMPLEControlOpt::writeFields()
|
||||
{
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
time.write();
|
||||
solver_.write();
|
||||
}
|
||||
|
||||
|
||||
bool Foam::PIMPLEControlOpt::loop()
|
||||
{
|
||||
return pimpleControl::loop();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,112 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::PIMPLEControlOpt
|
||||
|
||||
Description
|
||||
PIMPLE control class for single runs (i.e. not optimisation).
|
||||
Time acts as in simpleFoam, with all solver control read through
|
||||
optimisationDict
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef PIMPLEControlOpt_H
|
||||
#define PIMPLEControlOpt_H
|
||||
|
||||
#include "PIMPLEControl.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class PIMPLEControlOpt Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class PIMPLEControlOpt
|
||||
:
|
||||
public PIMPLEControl
|
||||
{
|
||||
private:
|
||||
|
||||
//- No copy construct
|
||||
PIMPLEControlOpt(const PIMPLEControlOpt&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const PIMPLEControlOpt&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("unsteadyOptimisation");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from mesh
|
||||
PIMPLEControlOpt
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~PIMPLEControlOpt() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Solution control
|
||||
|
||||
//- Whether to call time.write() or not
|
||||
virtual void writeFields();
|
||||
|
||||
|
||||
// Evolution
|
||||
|
||||
//- Loop
|
||||
virtual bool loop();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,113 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "PISOControl.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(PISOControl, 0);
|
||||
defineRunTimeSelectionTable(PISOControl, dictionary);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::PISOControl::PISOControl
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
)
|
||||
:
|
||||
solverControl(solver),
|
||||
pisoControl(mesh, "PISO"),
|
||||
managerType_(managerType),
|
||||
pRefCell_(Zero),
|
||||
pRefValue_(Zero),
|
||||
timeManip_
|
||||
(
|
||||
const_cast<unsteadyTimeManipulation&>
|
||||
(
|
||||
unsteadyTimeManipulation::New(mesh)
|
||||
)
|
||||
)
|
||||
{
|
||||
read();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::PISOControl> Foam::PISOControl::New
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
)
|
||||
{
|
||||
auto* ctorPtr = dictionaryConstructorTable(managerType);
|
||||
|
||||
if (!ctorPtr)
|
||||
{
|
||||
FatalErrorInLookup
|
||||
(
|
||||
"control",
|
||||
managerType,
|
||||
*dictionaryConstructorTablePtr_
|
||||
) << exit(FatalError);
|
||||
}
|
||||
|
||||
return autoPtr<PISOControl>(ctorPtr(mesh, managerType, solver));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::PISOControl::read()
|
||||
{
|
||||
pisoControl::read();
|
||||
solverControl::read();
|
||||
|
||||
// Always store initial field values in unsteady runs
|
||||
storeInitValues_ = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Foam::PISOControl::updateAverageStartTime()
|
||||
{
|
||||
averageStartTime_ += timeManip_.span();
|
||||
DebugInfo
|
||||
<< "Set averageStartTime to " << averageStartTime_ << endl;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,186 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::PISOControl
|
||||
|
||||
Description
|
||||
PISO control class to supply convergence information/checks for
|
||||
the PISO loop.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef PISOControl_H
|
||||
#define PISOControl_H
|
||||
|
||||
#include "solverControl.H"
|
||||
#include "pisoControl.H"
|
||||
#include "unsteadyTimeManipulation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class PISOControl Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class PISOControl
|
||||
:
|
||||
public solverControl,
|
||||
public pisoControl
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Optimisation type
|
||||
const word& managerType_;
|
||||
|
||||
//- Pressure reference cell
|
||||
label pRefCell_;
|
||||
//
|
||||
//- Pressure reference value
|
||||
scalar pRefValue_;
|
||||
|
||||
//- Time manipulation during unsteady optimisation
|
||||
unsteadyTimeManipulation& timeManip_;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
//- No copy construct
|
||||
PISOControl(const PISOControl&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const PISOControl&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("PISOControl");
|
||||
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
PISOControl,
|
||||
dictionary,
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
),
|
||||
(mesh, managerType, solver)
|
||||
);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from mesh
|
||||
PISOControl
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~PISOControl() = default;
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Return a reference to the selected turbulence model
|
||||
static autoPtr<PISOControl> New
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual bool read();
|
||||
|
||||
// Access
|
||||
|
||||
//- Return the solution dictionary
|
||||
inline virtual const dictionary dict() const;
|
||||
|
||||
//- Return pressure reference cell
|
||||
inline label& pRefCell();
|
||||
|
||||
//- Return pressure reference value
|
||||
inline scalar& pRefValue();
|
||||
|
||||
//- Return the time span of each optimisation cycle
|
||||
inline scalar timeSpan() const;
|
||||
|
||||
//- Update the start time of averaging for the next opt. cycle
|
||||
void updateAverageStartTime();
|
||||
|
||||
|
||||
// Solution control
|
||||
|
||||
//- Whether to call time.write() or not
|
||||
virtual void writeFields() = 0;
|
||||
|
||||
//- Use averaged fields?
|
||||
// For solving the adjoint equations or computing sensitivities
|
||||
// based on averaged fields
|
||||
inline bool useAveragedFields() const;
|
||||
|
||||
|
||||
// Evolution
|
||||
|
||||
//- Loop
|
||||
virtual bool loop() = 0;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
#include "PISOControlI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,62 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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/>.
|
||||
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
inline const Foam::dictionary Foam::PISOControl::dict() const
|
||||
{
|
||||
return solutionDict();
|
||||
}
|
||||
|
||||
|
||||
inline Foam::label& Foam::PISOControl::pRefCell()
|
||||
{
|
||||
return pRefCell_;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalar& Foam::PISOControl::pRefValue()
|
||||
{
|
||||
return pRefValue_;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalar Foam::PISOControl::timeSpan() const
|
||||
{
|
||||
return timeManip_.span();
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::PISOControl::useAveragedFields() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,71 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "PISOControlOpt.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "Time.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(PISOControlOpt, 0);
|
||||
addToRunTimeSelectionTable(PISOControl, PISOControlOpt, dictionary);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::PISOControlOpt::PISOControlOpt
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
)
|
||||
:
|
||||
PISOControl(mesh, managerType, solver)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::PISOControlOpt::writeFields()
|
||||
{
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
time.write();
|
||||
solver_.write();
|
||||
}
|
||||
|
||||
|
||||
bool Foam::PISOControlOpt::loop()
|
||||
{
|
||||
return pisoControl::loop();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,112 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::PISOControlOpt
|
||||
|
||||
Description
|
||||
PISO control class for single runs (i.e. not optimisation).
|
||||
Time acts as in simpleFoam, with all solver control read through
|
||||
optimisationDict
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef PISOControlOpt_H
|
||||
#define PISOControlOpt_H
|
||||
|
||||
#include "PISOControl.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class PISOControlOpt Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class PISOControlOpt
|
||||
:
|
||||
public PISOControl
|
||||
{
|
||||
private:
|
||||
|
||||
//- No copy construct
|
||||
PISOControlOpt(const PISOControlOpt&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const PISOControlOpt&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("unsteadyOptimisation");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from mesh
|
||||
PISOControlOpt
|
||||
(
|
||||
fvMesh& mesh,
|
||||
const word& managerType,
|
||||
const solver& solver
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~PISOControlOpt() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Solution control
|
||||
|
||||
//- Whether to call time.write() or not
|
||||
virtual void writeFields();
|
||||
|
||||
|
||||
// Evolution
|
||||
|
||||
//- Loop
|
||||
virtual bool loop();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -36,7 +36,7 @@ License
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(SIMPLEControlOpt, 1);
|
||||
addToRunTimeSelectionTable( SIMPLEControl, SIMPLEControlOpt, dictionary);
|
||||
addToRunTimeSelectionTable(SIMPLEControl, SIMPLEControlOpt, dictionary);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
@ -46,6 +46,7 @@ bool Foam::solverControl::read()
|
||||
// Manage averaging
|
||||
dictionary averagingDict = solutionDict().subOrEmptyDict("averaging");
|
||||
averageStartIter_ = averagingDict.getOrDefault<label>("startIter", -1);
|
||||
averageStartTime_ = averagingDict.getOrDefault<scalar>("startTime", -1);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -60,6 +61,7 @@ Foam::solverControl::solverControl(const solver& solver)
|
||||
iter_(0),
|
||||
averageIter_(solver.getOrDefault<label>("averageIter", 0)),
|
||||
averageStartIter_(-1),
|
||||
averageStartTime_(-1),
|
||||
// Non run-time modifiable options read in the constructor only
|
||||
storeInitValues_
|
||||
(
|
||||
|
||||
@ -76,6 +76,9 @@ protected:
|
||||
//- Averaging start index
|
||||
label averageStartIter_;
|
||||
|
||||
//- Averaging start time
|
||||
scalar averageStartTime_;
|
||||
|
||||
// Non run-time modifiable entries
|
||||
|
||||
//- Whether to re-initialize the solution based on the initial
|
||||
@ -151,17 +154,30 @@ public:
|
||||
//- Return iteration index
|
||||
inline label averageStartIter() const;
|
||||
|
||||
//- Return averaging start time reference for unsteady runs
|
||||
inline scalar& averageStartTime();
|
||||
|
||||
//- Return const averaging start time reference for unsteady runs
|
||||
inline scalar averageStartTime() const;
|
||||
|
||||
//- Whether or not to add fields of the current iteration to the
|
||||
//- average fields
|
||||
inline bool doAverageIter() const;
|
||||
|
||||
//- Whether or not to add fields of the current time to the
|
||||
//- average fields
|
||||
inline bool doAverageTime() const;
|
||||
|
||||
//- Use averaged fields?
|
||||
//- For solving the adjoint equations or computing sensitivities
|
||||
//- based on averaged fields
|
||||
inline bool useAveragedFields() const;
|
||||
virtual inline bool useAveragedFields() const;
|
||||
|
||||
//- Whether averaging is enabled or not
|
||||
inline bool average() const;
|
||||
|
||||
//- Return reference to the underlaying solver
|
||||
inline const solver& getSolver() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -78,6 +78,18 @@ inline Foam::label Foam::solverControl::averageStartIter() const
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalar& Foam::solverControl::averageStartTime()
|
||||
{
|
||||
return averageStartTime_;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalar Foam::solverControl::averageStartTime() const
|
||||
{
|
||||
return averageStartTime_;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::solverControl::doAverageIter() const
|
||||
{
|
||||
if (average_ && iter_ >= averageStartIter_)
|
||||
@ -91,6 +103,19 @@ inline bool Foam::solverControl::doAverageIter() const
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::solverControl::doAverageTime() const
|
||||
{
|
||||
if (average_ && solver_.mesh().time().value() >= averageStartTime_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::solverControl::useAveragedFields() const
|
||||
{
|
||||
if (average_ && averageIter_)
|
||||
@ -110,4 +135,10 @@ inline bool Foam::solverControl::average() const
|
||||
}
|
||||
|
||||
|
||||
inline const Foam::solver& Foam::solverControl::getSolver() const
|
||||
{
|
||||
return solver_;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -0,0 +1,145 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "checkPoint.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
defineTypeNameAndDebug(checkPoint, 0);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
checkPoint::checkPoint
|
||||
(
|
||||
storageParameters& storageParams
|
||||
)
|
||||
:
|
||||
vars_(),
|
||||
storageParams_(storageParams),
|
||||
mesh_(storageParams.mesh()),
|
||||
storageMetrics_(),
|
||||
deltaT_(0.),
|
||||
active_(false),
|
||||
placeHolder_(true),
|
||||
a_(-1),
|
||||
checkPointLevel_(-1),
|
||||
checkPointTimeIndex_(-1),
|
||||
checkPointTime_(-1.)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void checkPoint::retrieve()
|
||||
{
|
||||
if (!vars_)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Trying to retrieve solution at t = "
|
||||
<< storageParams_.mesh().time().value()
|
||||
<< " from checkPoint with t = "
|
||||
<< checkPointTime_ << nl
|
||||
<< "but no storage has been allocated." << nl
|
||||
<< "placeHolder checkPoint? " << placeHolder_ << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
vars_().decompress();
|
||||
}
|
||||
|
||||
|
||||
void checkPoint::setPlaceHolder(Switch newLevel)
|
||||
{
|
||||
deltaT_ = storageParams_.mesh().time().deltaTValue();
|
||||
active_ = true;
|
||||
placeHolder_ = true;
|
||||
a_ = 0;
|
||||
checkPointTimeIndex_ = storageParams_.mesh().time().timeIndex();
|
||||
checkPointTime_ = storageParams_.mesh().time().value();
|
||||
if (newLevel)
|
||||
{
|
||||
checkPointLevel_ += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
checkPointLevel_ = 0;
|
||||
}
|
||||
// Clear the previously allocated storage
|
||||
vars_.clear();
|
||||
storageMetrics_.clear();
|
||||
}
|
||||
|
||||
|
||||
void checkPoint::store(incompressibleVars& vs, const label a)
|
||||
{
|
||||
placeHolder_ = false;
|
||||
a_ = a;
|
||||
vars_.reset(new fullIncompressibleVars(vs, storageParams_, a_));
|
||||
vars_().compress();
|
||||
storageMetrics_ = vars_().storageMetrics();
|
||||
}
|
||||
|
||||
|
||||
void checkPoint::empty()
|
||||
{
|
||||
active_ = false;
|
||||
placeHolder_ = true;
|
||||
checkPointTimeIndex_ = -1;
|
||||
checkPointTime_ = -1;
|
||||
checkPointLevel_ = -1;
|
||||
a_ = -1;
|
||||
vars_.clear();
|
||||
storageMetrics_.clear();
|
||||
}
|
||||
|
||||
|
||||
void checkPoint::resetToPlaceHolder()
|
||||
{
|
||||
placeHolder_ = true;
|
||||
a_ = 0;
|
||||
vars_.clear();
|
||||
storageMetrics_.clear();
|
||||
}
|
||||
|
||||
|
||||
const scalarList& checkPoint::storageMetrics() const
|
||||
{
|
||||
return storageMetrics_;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,217 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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
|
||||
checkPoint
|
||||
|
||||
Description
|
||||
|
||||
SourceFiles
|
||||
checkPoint.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef checkPoint_H
|
||||
#define checkPoint_H
|
||||
|
||||
#include "fullIncompressibleVars.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class checkPoint Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class checkPoint
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Variables held by this checkPoint
|
||||
autoPtr<fullIncompressibleVars> vars_;
|
||||
|
||||
storageParameters& storageParams_;
|
||||
|
||||
const fvMesh& mesh_;
|
||||
|
||||
scalarList storageMetrics_;
|
||||
|
||||
//- deltaT corresponding to the time-step this checkPoint holds
|
||||
scalar deltaT_;
|
||||
|
||||
//- Whether this checkPoint is active
|
||||
Switch active_;
|
||||
|
||||
//- Whether this checkPoint is a placeHolder
|
||||
Switch placeHolder_;
|
||||
|
||||
//- schedule with size equal to nTimeSteps containing the number of
|
||||
//- time-solution that must be stored at the checkPoint:
|
||||
// -1: inactive checkPoint 0: placeholder checkPoint;
|
||||
// 1: single checkPoint 2: double checkPoint
|
||||
label a_;
|
||||
|
||||
label checkPointLevel_;
|
||||
|
||||
label checkPointTimeIndex_;
|
||||
|
||||
scalar checkPointTime_;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
checkPoint(const checkPoint&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const checkPoint&) = delete;
|
||||
|
||||
public:
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("checkPoint");
|
||||
|
||||
// Constructors
|
||||
|
||||
checkPoint(storageParameters& storageParams);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~checkPoint() = default;
|
||||
|
||||
|
||||
// Access functions
|
||||
|
||||
inline scalar deltaT() const
|
||||
{
|
||||
return deltaT_;
|
||||
}
|
||||
|
||||
inline scalar& deltaT()
|
||||
{
|
||||
return deltaT_;
|
||||
}
|
||||
|
||||
inline Switch active() const
|
||||
{
|
||||
return active_;
|
||||
}
|
||||
|
||||
inline Switch& active()
|
||||
{
|
||||
return active_;
|
||||
}
|
||||
|
||||
inline const Switch& placeHolder() const
|
||||
{
|
||||
return placeHolder_;
|
||||
}
|
||||
|
||||
inline Switch& placeHolder()
|
||||
{
|
||||
return placeHolder_;
|
||||
}
|
||||
|
||||
inline label a() const
|
||||
{
|
||||
return a_;
|
||||
}
|
||||
|
||||
inline label& a()
|
||||
{
|
||||
return a_;
|
||||
}
|
||||
|
||||
inline label level() const
|
||||
{
|
||||
return checkPointLevel_;
|
||||
}
|
||||
|
||||
inline label& level()
|
||||
{
|
||||
return checkPointLevel_;
|
||||
}
|
||||
|
||||
inline label timeIndex() const
|
||||
{
|
||||
return checkPointTimeIndex_;
|
||||
}
|
||||
|
||||
inline label& timeIndex()
|
||||
{
|
||||
return checkPointTimeIndex_;
|
||||
}
|
||||
|
||||
inline scalar timeValue() const
|
||||
{
|
||||
return checkPointTime_;
|
||||
}
|
||||
|
||||
inline scalar& timeValue()
|
||||
{
|
||||
return checkPointTime_;
|
||||
}
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
//- Function to decompress the incompressible vars and update the
|
||||
//- solver fields with the decompressed ones
|
||||
void retrieve();
|
||||
|
||||
void setPlaceHolder(Switch newLevel);
|
||||
|
||||
//- store function must be called after setPlaceHolder.
|
||||
void store(incompressibleVars& vs, const label a = 2);
|
||||
|
||||
//- Clear the chekpoint memory and reset its properties
|
||||
void empty();
|
||||
|
||||
//- Clear the storage of the checkpoint and make it a placeHolder
|
||||
//- checkpoint
|
||||
void resetToPlaceHolder();
|
||||
|
||||
const scalarList& storageMetrics() const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,371 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "compressedIncompressibleVars.H"
|
||||
#include "createZeroField.H"
|
||||
#include "IOmanip.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
defineTypeNameAndDebug(compressedIncompressibleVars, 0);
|
||||
defineRunTimeSelectionTable(compressedIncompressibleVars, dictionary);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void compressedIncompressibleVars::writeLog
|
||||
(
|
||||
const word& name
|
||||
) const
|
||||
{
|
||||
const scalar& initialSize = storageMetrics_[0];
|
||||
const scalar& uncompressedRoughSize = storageMetrics_[1];
|
||||
const scalar& uncompressedSize = storageMetrics_[2];
|
||||
const scalar& compressedSize = storageMetrics_[3];
|
||||
if (!initialSize || !uncompressedSize || !uncompressedRoughSize)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "initialSize, uncompressedRoughSize or uncompressedSize is Zero"
|
||||
<< endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
if (!compressedSize)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "compressedSize is Zero" << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
unsigned int width = 6;//IOstream::defaultPrecision();
|
||||
Info<< setprecision(width);
|
||||
Info<< name << tab << "pure algorithm's CR = "
|
||||
<< uncompressedSize/compressedSize << endl;
|
||||
if (debug)
|
||||
{
|
||||
Info<< name << ": Initial Size = "
|
||||
<< initialSize*1.e-6 << " Mb" << nl
|
||||
<< name << ": Initial Size saved = "
|
||||
<< uncompressedRoughSize*1.e-6 << " Mb" << nl
|
||||
<< name << ": Uncompressed Size = "
|
||||
<< uncompressedSize*1.e-6 << " Mb" << nl
|
||||
<< name << ": Compressed Size = "
|
||||
<< compressedSize*1.e-6 << " Mb" << endl;
|
||||
if (name == "All")
|
||||
{
|
||||
Info<< name
|
||||
<< ": Data Increase due to data manipulation before compression = "
|
||||
<< (uncompressedSize-uncompressedRoughSize)/uncompressedRoughSize*100. << "%"
|
||||
<< endl;
|
||||
}
|
||||
Info<< name << ": (%) Data Reduction = "
|
||||
<< (uncompressedSize-compressedSize)/uncompressedSize*100. << "%"
|
||||
<< endl;
|
||||
}
|
||||
Info<< setprecision(IOstream::defaultPrecision());
|
||||
if (name == "All")
|
||||
{
|
||||
Info << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void compressedIncompressibleVars::write(const label i)
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
if (storageFilePtr_.empty())
|
||||
{
|
||||
setStorageFilesPtr();
|
||||
}
|
||||
const scalar initialSize = storageMetrics_[0];
|
||||
const scalar uncompressedRoughSize = storageMetrics_[1];
|
||||
const scalar uncompressedSize = storageMetrics_[2];
|
||||
const scalar compressedSize = storageMetrics_[3];
|
||||
|
||||
unsigned int width = IOstream::defaultPrecision() + 6;
|
||||
storageFilePtr_[i]
|
||||
<< setprecision(6) << setw(8) << mesh_.time().value() << tab
|
||||
<< setprecision(IOstream::defaultPrecision())
|
||||
<< setw(width) << uncompressedSize/compressedSize << tab
|
||||
<< setw(width) << (uncompressedSize-compressedSize)/uncompressedSize*100. << tab
|
||||
<< setw(width) << initialSize*1.e-6 << tab
|
||||
<< setw(width) << uncompressedRoughSize*1.e-6 << tab
|
||||
<< setw(width) << compressedSize*1.e-6 << endl;
|
||||
storageFilePtr_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void compressedIncompressibleVars::setFields()
|
||||
{
|
||||
incompressibleVars& v = incoVars_;
|
||||
p_.reset(compressedVolScalarField::New(v.pInst(), storageParams_, 0, k_));
|
||||
phi_.reset
|
||||
(
|
||||
compressedSurfaceScalarField::New(v.phiInst(), storageParams_, 1, k_)
|
||||
);
|
||||
U_.reset(compressedVolVectorField::New(v.UInst(), storageParams_, 2, k_));
|
||||
incompressible::RASModelVariables& rasVars = v.RASModelVariables()();
|
||||
if (rasVars.hasTMVar1())
|
||||
{
|
||||
RASModelVars_.append
|
||||
(
|
||||
compressedVolScalarField::New
|
||||
(rasVars.TMVar1Inst(), storageParams_, 3, k_)
|
||||
);
|
||||
}
|
||||
if (rasVars.hasTMVar2())
|
||||
{
|
||||
RASModelVars_.append
|
||||
(
|
||||
compressedVolScalarField::New
|
||||
(rasVars.TMVar2Inst(), storageParams_, 4, k_)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void compressedIncompressibleVars::makeFolder()
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
storageFolder_ = mesh_.time().globalPath()/"optimisation"/"storage";
|
||||
if (!isDir(storageFolder_))
|
||||
{
|
||||
mkDir(storageFolder_);
|
||||
WarningInFunction
|
||||
<< "The folder storing the compression metrics should have "
|
||||
<< "been already set."
|
||||
<< nl
|
||||
<< "Possible error in: compressedFullStorage::makeFolder()."
|
||||
<< "Setting folder anyway." << nl
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void compressedIncompressibleVars::setStorageFilesPtr()
|
||||
{
|
||||
storageFilePtr_.setSize(7);
|
||||
label Ic = -1;
|
||||
names_.setSize(7, "undefined");
|
||||
names_[++Ic] = "AllFields" + solverName();
|
||||
names_[++Ic] = incoVars_.pInst().name();
|
||||
names_[++Ic] = incoVars_.phiInst().name();
|
||||
names_[++Ic] = incoVars_.UInst().name();
|
||||
incompressible::RASModelVariables& rasVars =
|
||||
incoVars_.RASModelVariables()();
|
||||
forAll(RASModelVars_, iPtr)
|
||||
{
|
||||
if (iPtr == 0)
|
||||
{
|
||||
names_[++Ic] = rasVars.TMVar1Inst().name();
|
||||
}
|
||||
else if (iPtr == 1)
|
||||
{
|
||||
names_[++Ic] = rasVars.TMVar2Inst().name();
|
||||
}
|
||||
}
|
||||
for (label i = 0; i <= Ic; i++)
|
||||
{
|
||||
fileName filePath = storageFolder_/names_[i];
|
||||
if (!isFile(filePath))
|
||||
{
|
||||
storageFilePtr_.set
|
||||
(
|
||||
i, new OFstream(filePath)
|
||||
);
|
||||
unsigned int width = IOstream::defaultPrecision() + 6;
|
||||
storageFilePtr_[i]
|
||||
<< setw(8) << "# Time" << tab
|
||||
<< setw(width) << "algorithm's CR" << tab
|
||||
<< setw(width) << "(%) Reduction" << tab
|
||||
<< setw(width) << "Initial Size (Mb)" << tab
|
||||
<< setw(width) << "Uncompressed Size (Mb)" << tab
|
||||
<< setw(width) << "Compressed Size (Mb)" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
storageFilePtr_.set
|
||||
(
|
||||
i,
|
||||
new OFstream
|
||||
(
|
||||
filePath,
|
||||
IOstream::ASCII,
|
||||
IOstream::currentVersion,
|
||||
IOstream::UNCOMPRESSED,
|
||||
true
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
compressedIncompressibleVars::compressedIncompressibleVars
|
||||
(
|
||||
incompressibleVars& vs,
|
||||
storageParameters& storageParams
|
||||
)
|
||||
:
|
||||
variablesSet
|
||||
(
|
||||
vs.mesh(),
|
||||
vs.solverControlReference().solverDict()
|
||||
),
|
||||
incoVars_(vs),
|
||||
solverControl_(vs.solverControlReference()),
|
||||
storageParams_(storageParams),
|
||||
k_(0),
|
||||
kCopy_(k_),
|
||||
p_(nullptr),
|
||||
phi_(nullptr),
|
||||
U_(nullptr),
|
||||
RASModelVars_(),
|
||||
timeIndex_(mesh_.time().timeIndex()),
|
||||
timeValue_(mesh_.time().value()),
|
||||
storageMetrics_(),
|
||||
names_(7, "undefined"),
|
||||
storageFilePtr_()
|
||||
{
|
||||
setFields();
|
||||
makeFolder();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
||||
|
||||
autoPtr<compressedIncompressibleVars> compressedIncompressibleVars::New
|
||||
(
|
||||
incompressibleVars& vs,
|
||||
storageParameters& storageParams
|
||||
)
|
||||
{
|
||||
const word type = storageParams.algorithm() + "IncompressibleVars";
|
||||
DebugInfo
|
||||
<< "compressedIncompressibleVars type for the primal fields: " << type
|
||||
<< endl;
|
||||
|
||||
auto cstrIter = dictionaryConstructorTablePtr_->cfind(type);
|
||||
|
||||
if (!cstrIter.found())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Unknown compressedIncompressibleVars type " << type << nl << nl
|
||||
<< "Valid compressedIncompressibleVars types are :" << nl
|
||||
<< dictionaryConstructorTablePtr_->sortedToc()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
return autoPtr<compressedIncompressibleVars>
|
||||
(cstrIter()(vs, storageParams));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void compressedIncompressibleVars::calculateStorageMetrics()
|
||||
{
|
||||
storageMetrics_.setSize(p_().storageMetrics().size());
|
||||
label i = 0;
|
||||
if (!storageParams_.timing())
|
||||
{
|
||||
calculateAndWrite(p_(), incoVars_.pInst().name(), i);
|
||||
calculateAndWrite(phi_(), incoVars_.phiInst().name(), i);
|
||||
calculateAndWrite(U_(), incoVars_.UInst().name(), i);
|
||||
incompressible::RASModelVariables& rasVars =
|
||||
incoVars_.RASModelVariables()();
|
||||
if (rasVars.hasTMVar1())
|
||||
{
|
||||
calculateAndWrite(RASModelVars_[0], rasVars.TMVar1Inst().name(), i);
|
||||
}
|
||||
if (rasVars.hasTMVar2())
|
||||
{
|
||||
calculateAndWrite(RASModelVars_[1], rasVars.TMVar2Inst().name(), i);
|
||||
}
|
||||
}
|
||||
storageMetrics_ =
|
||||
p_().storageMetrics()
|
||||
+ phi_().storageMetrics()
|
||||
+ U_().storageMetrics();
|
||||
|
||||
forAll(RASModelVars_, iPtr)
|
||||
{
|
||||
storageMetrics_ =
|
||||
storageMetrics_ + RASModelVars_[iPtr].storageMetrics();
|
||||
}
|
||||
if (!storageParams_.timing())
|
||||
{
|
||||
write(0);
|
||||
writeLog("All");
|
||||
}
|
||||
storageFilePtr_.clear();
|
||||
names_.clear();
|
||||
}
|
||||
|
||||
|
||||
void compressedIncompressibleVars::compress()
|
||||
{
|
||||
NotImplemented
|
||||
}
|
||||
|
||||
|
||||
void compressedIncompressibleVars::decompress
|
||||
(
|
||||
incompressibleVars& vars
|
||||
)
|
||||
{
|
||||
NotImplemented
|
||||
}
|
||||
|
||||
|
||||
void compressedIncompressibleVars::decompress()
|
||||
{
|
||||
this->decompress(incoVars_);
|
||||
}
|
||||
|
||||
|
||||
const scalarList& compressedIncompressibleVars::storageMetrics() const
|
||||
{
|
||||
return storageMetrics_;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,228 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::compressedIncompressibleVars
|
||||
|
||||
Description
|
||||
Base class for solution control classes
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef compressedIncompressibleVars_H
|
||||
#define compressedIncompressibleVars_H
|
||||
|
||||
#include "incompressibleVars.H"
|
||||
#include "compressedGeometricFields.H"
|
||||
#include "storageParameters.H"
|
||||
#include "OFstream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class compressedIncompressibleVars Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class compressedIncompressibleVars
|
||||
:
|
||||
public variablesSet
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Vars seen by the solver
|
||||
incompressibleVars& incoVars_;
|
||||
|
||||
//- Solver control related to the base variables
|
||||
const solverControl& solverControl_;
|
||||
|
||||
storageParameters& storageParams_;
|
||||
|
||||
//- Current S/N of the time-step that is compressed in the present
|
||||
//- object.
|
||||
// Useful when more than one time-steps are compressed
|
||||
// in the same compressedIncompressibleVars (e.g. iPGD algorithm)
|
||||
label k_;
|
||||
|
||||
label kCopy_;
|
||||
|
||||
//- Compressed fields including turbulence
|
||||
autoPtr<compressedVolScalarField> p_;
|
||||
autoPtr<compressedSurfaceScalarField> phi_;
|
||||
autoPtr<compressedVolVectorField> U_;
|
||||
PtrList<compressedVolScalarField> RASModelVars_;
|
||||
|
||||
//- Time value and index
|
||||
label timeIndex_;
|
||||
|
||||
scalar timeValue_;
|
||||
|
||||
//- List that holds the compression metrics (initial size, compressed
|
||||
//- size if compression is applied, etc) for all fields of the current
|
||||
//- time step.
|
||||
scalarList storageMetrics_;
|
||||
|
||||
//- Variables used for writing the compression metrics
|
||||
fileName storageFolder_;
|
||||
wordList names_;
|
||||
mutable PtrList<OFstream> storageFilePtr_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Set compressed fields including turbulence
|
||||
void setFields();
|
||||
|
||||
//- Calculate and write compression metrics for a
|
||||
//- compressedGeometricField
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void calculateAndWrite
|
||||
(
|
||||
const compressedGeometricField<Type, PatchField, GeoMesh>& compField,
|
||||
const word& name,
|
||||
label& i
|
||||
);
|
||||
|
||||
//- Function to write the compressed size, the compression ratio, etc.
|
||||
virtual void writeLog(const word&) const;
|
||||
|
||||
//- Function to write compression metrics to file
|
||||
virtual void write(const label);
|
||||
|
||||
//- Set folder
|
||||
void makeFolder();
|
||||
|
||||
//- Set File to store compression metrics
|
||||
virtual void setStorageFilesPtr();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("compressedIncompressibleVars");
|
||||
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
compressedIncompressibleVars,
|
||||
dictionary,
|
||||
(
|
||||
incompressibleVars& vs,
|
||||
storageParameters& storageParams
|
||||
),
|
||||
(vs, storageParams)
|
||||
);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
compressedIncompressibleVars
|
||||
(
|
||||
incompressibleVars& vs,
|
||||
storageParameters& storageParams
|
||||
);
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Return a reference to the selected turbulence model
|
||||
static autoPtr<compressedIncompressibleVars> New
|
||||
(
|
||||
incompressibleVars& vs,
|
||||
storageParameters& storageParams
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~compressedIncompressibleVars() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
inline label timeIndex() const
|
||||
{
|
||||
return timeIndex_;
|
||||
}
|
||||
|
||||
inline label& timeIndex()
|
||||
{
|
||||
return timeIndex_;
|
||||
}
|
||||
|
||||
inline scalar timeValue() const
|
||||
{
|
||||
return timeValue_;
|
||||
}
|
||||
|
||||
inline scalar& timeValue()
|
||||
{
|
||||
return timeValue_;
|
||||
}
|
||||
|
||||
//- Function to calculate and write the compression metrics
|
||||
virtual void calculateStorageMetrics();
|
||||
|
||||
virtual void compress();
|
||||
|
||||
virtual void decompress
|
||||
(
|
||||
incompressibleVars& vars
|
||||
);
|
||||
|
||||
void decompress();
|
||||
|
||||
//- Function to return the compression metrics (initial size,
|
||||
//- compressed size if compression is applied, etc)
|
||||
virtual const scalarList& storageMetrics() const override;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "compressedIncompressibleVarsTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,49 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
||||
Copyright (C) 2013-2019 FOSS GP
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void Foam::compressedIncompressibleVars::calculateAndWrite
|
||||
(
|
||||
const compressedGeometricField<Type, PatchField, GeoMesh>& compField,
|
||||
const word& name,
|
||||
label& i
|
||||
)
|
||||
{
|
||||
forAll(storageMetrics_, Ic)
|
||||
{
|
||||
storageMetrics_[Ic] = compField.storageMetrics()[Ic];
|
||||
}
|
||||
write(++i);
|
||||
writeLog(name);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,215 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "fullIncompressibleVars.H"
|
||||
#include "IOmanip.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
defineTypeNameAndDebug(fullIncompressibleVars, 0);
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void fullIncompressibleVars::calculateStorageMetrics()
|
||||
{
|
||||
storageMetrics_.setSize(p_().storageMetrics().size(), Zero);
|
||||
label i = 0;
|
||||
if ( !storageParams_.timing() )
|
||||
{
|
||||
this->calculateAndWrite(p_(), pOld_, incoVars_.pInst().name(), i);
|
||||
this->calculateAndWrite(phi_(), phiOld_, incoVars_.phiInst().name(), i);
|
||||
this->calculateAndWrite(U_(), UOld_, incoVars_.UInst().name(), i);
|
||||
incompressible::RASModelVariables& rasVars =
|
||||
incoVars_.RASModelVariables()();
|
||||
if (rasVars.hasTMVar1())
|
||||
{
|
||||
this->calculateAndWrite
|
||||
(RASModelVars_[0], TMVar1Old_, rasVars.TMVar1Inst().name(), i);
|
||||
}
|
||||
if (rasVars.hasTMVar2())
|
||||
{
|
||||
this->calculateAndWrite
|
||||
(RASModelVars_[1], TMVar2Old_, rasVars.TMVar2Inst().name(), i);
|
||||
}
|
||||
storageMetrics_ = Zero;
|
||||
}
|
||||
addStorageMetricsContribution(p_(), pOld_);
|
||||
addStorageMetricsContribution(phi_(), phiOld_);
|
||||
addStorageMetricsContribution(U_(), UOld_);
|
||||
incompressible::RASModelVariables& rasVars =
|
||||
incoVars_.RASModelVariables()();
|
||||
if (rasVars.hasTMVar1())
|
||||
{
|
||||
addStorageMetricsContribution(RASModelVars_[0], TMVar1Old_);
|
||||
}
|
||||
if (rasVars.hasTMVar2())
|
||||
{
|
||||
addStorageMetricsContribution(RASModelVars_[1], TMVar2Old_);
|
||||
}
|
||||
if (!storageParams_.timing())
|
||||
{
|
||||
write(0);
|
||||
writeLog("All");
|
||||
}
|
||||
names_.clear();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
fullIncompressibleVars::fullIncompressibleVars
|
||||
(
|
||||
incompressibleVars& vs,
|
||||
storageParameters& storageParams,
|
||||
label a
|
||||
)
|
||||
:
|
||||
compressedIncompressibleVars(vs, storageParams),
|
||||
a_(a),
|
||||
pOld_(),
|
||||
phiOld_(),
|
||||
UOld_(),
|
||||
TMVar1Old_(),
|
||||
TMVar2Old_()
|
||||
{
|
||||
if (a_ < 1)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Total number 'a' of time-solutions to be stored must be >= 1."
|
||||
<< nl
|
||||
<< "Object constructed with (a = " << a_ << ")"
|
||||
<< endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
storeOldTimes(incoVars_.pInst(), pOld_, 0);
|
||||
storeOldTimes(incoVars_.phiInst(), phiOld_, 1);
|
||||
storeOldTimes(incoVars_.UInst(), UOld_, 2);
|
||||
incompressible::RASModelVariables& rasVars =
|
||||
incoVars_.RASModelVariables()();
|
||||
if (rasVars.hasTMVar1())
|
||||
{
|
||||
storeOldTimes(rasVars.TMVar1Inst(), TMVar1Old_, 3);
|
||||
}
|
||||
if (rasVars.hasTMVar2())
|
||||
{
|
||||
storeOldTimes(rasVars.TMVar2Inst(), TMVar2Old_, 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void fullIncompressibleVars::compress()
|
||||
{
|
||||
//scalar startTime = mesh_.time().elapsedCpuTime();
|
||||
p_().compress();
|
||||
forAll(pOld_, iPtr)
|
||||
{
|
||||
pOld_[iPtr].compress();
|
||||
}
|
||||
phi_().compress();
|
||||
forAll(phiOld_, iPtr)
|
||||
{
|
||||
phiOld_[iPtr].compress();
|
||||
}
|
||||
U_().compress();
|
||||
forAll(UOld_, iPtr)
|
||||
{
|
||||
UOld_[iPtr].compress();
|
||||
}
|
||||
incompressible::RASModelVariables& rasVars =
|
||||
incoVars_.RASModelVariables()();
|
||||
if (rasVars.hasTMVar1())
|
||||
{
|
||||
RASModelVars_[0].compress();
|
||||
forAll(TMVar1Old_, iPtr)
|
||||
{
|
||||
TMVar1Old_[iPtr].compress();
|
||||
}
|
||||
}
|
||||
if (rasVars.hasTMVar2())
|
||||
{
|
||||
RASModelVars_[1].compress();
|
||||
forAll(TMVar2Old_, iPtr)
|
||||
{
|
||||
TMVar2Old_[iPtr].compress();
|
||||
}
|
||||
}
|
||||
//scalar endTime = mesh_.time().elapsedCpuTime();
|
||||
calculateStorageMetrics();
|
||||
}
|
||||
|
||||
|
||||
void fullIncompressibleVars::decompress
|
||||
(
|
||||
incompressibleVars& vars
|
||||
)
|
||||
{
|
||||
// Phi must be retrieved first, since the BCs of p and U might depend on
|
||||
// flux
|
||||
decompressAll(vars.phiInst(), phi_(), phiOld_);
|
||||
DebugInfo
|
||||
<< "DEBUG: phi field retrieved" << endl;
|
||||
decompressAll(vars.pInst(), p_(), pOld_);
|
||||
DebugInfo
|
||||
<< "DEBUG: p field retrieved" << endl;
|
||||
decompressAll(vars.UInst(), U_(), UOld_);
|
||||
DebugInfo
|
||||
<< "DEBUG: U field retrieved" << endl;
|
||||
incompressible::RASModelVariables& rasVars = vars.RASModelVariables()();
|
||||
if (rasVars.hasTMVar1())
|
||||
{
|
||||
decompressAll(rasVars.TMVar1Inst(), RASModelVars_[0], TMVar1Old_);
|
||||
DebugInfo
|
||||
<< "DEBUG: 1st turbulence model field retrieved" << endl;
|
||||
}
|
||||
if (rasVars.hasTMVar2())
|
||||
{
|
||||
decompressAll(rasVars.TMVar2Inst(), RASModelVars_[1], TMVar2Old_);
|
||||
DebugInfo
|
||||
<< "DEBUG: 2nd turbulence model field retrieved" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void fullIncompressibleVars::decompress()
|
||||
{
|
||||
this->decompress(incoVars_);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,190 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::fullIncompressibleVars
|
||||
|
||||
Description
|
||||
Base class storing the current and the oldTime primal variables instances
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef fullIncompressibleVars_H
|
||||
#define fullIncompressibleVars_H
|
||||
|
||||
#include "compressedIncompressibleVars.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class fullIncompressibleVars Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class fullIncompressibleVars
|
||||
:
|
||||
public compressedIncompressibleVars
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Total number of time solutions to be stored for each time instance.
|
||||
// E.g. for (a=1) only the solution at the current time-step will be
|
||||
// stored, for (a=2) the solution at the current and the previous
|
||||
// tim-step will be stored.
|
||||
label a_;
|
||||
|
||||
//- PtrLists containing the oldTimes of all primal fields.
|
||||
// The fields of the current time-step are stored upon construction of
|
||||
// the compressedGeometricField class.
|
||||
PtrList<compressedVolScalarField> pOld_;
|
||||
PtrList<compressedSurfaceScalarField> phiOld_;
|
||||
PtrList<compressedVolVectorField> UOld_;
|
||||
PtrList<compressedVolScalarField> TMVar1Old_;
|
||||
PtrList<compressedVolScalarField> TMVar2Old_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Store oldTimes (if any) of a
|
||||
//- GeometricField<Type, PatchField, GeoMesh>
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void storeOldTimes
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
PtrList<compressedGeometricField<Type, PatchField, GeoMesh>>&
|
||||
compressedField,
|
||||
const label pos
|
||||
);
|
||||
|
||||
//- Decompress field and its old times into a GeometricField
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void decompressAll
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
compressedGeometricField<Type, PatchField, GeoMesh>& current,
|
||||
PtrList<compressedGeometricField<Type, PatchField, GeoMesh>>&
|
||||
oldFields
|
||||
);
|
||||
|
||||
//- Calculate and write compression metrics for a
|
||||
//- compressedGeometricField
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void addStorageMetricsContribution
|
||||
(
|
||||
const compressedGeometricField<Type, PatchField, GeoMesh>&
|
||||
compField,
|
||||
const PtrList<compressedGeometricField<Type, PatchField, GeoMesh>>&
|
||||
compOldField
|
||||
);
|
||||
|
||||
//- Calculate and write compression metrics for a
|
||||
//- compressedGeometricField
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void calculateAndWrite
|
||||
(
|
||||
const compressedGeometricField<Type, PatchField, GeoMesh>&
|
||||
compField,
|
||||
const PtrList<compressedGeometricField<Type, PatchField, GeoMesh>>&
|
||||
compOldField,
|
||||
const word& name,
|
||||
label& i
|
||||
);
|
||||
|
||||
//- Function to calculate and write the storage metrics of the
|
||||
//- checkpoint
|
||||
virtual void calculateStorageMetrics() override;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
fullIncompressibleVars(const fullIncompressibleVars&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const fullIncompressibleVars&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("fullIncompressibleVars");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
fullIncompressibleVars
|
||||
(
|
||||
incompressibleVars& vs,
|
||||
storageParameters& storageParams,
|
||||
label a = 2
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~fullIncompressibleVars() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Function to compress the incompressibleVars
|
||||
void compress() override;
|
||||
|
||||
//- Function to decompress the incompressible vars and
|
||||
// update the incompressibleVars with the decompressed fields
|
||||
void decompress
|
||||
(
|
||||
incompressibleVars& vars
|
||||
) override;
|
||||
|
||||
void decompress();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "fullIncompressibleVarsTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,146 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
||||
Copyright (C) 2013-2019 FOSS GP
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void Foam::fullIncompressibleVars::storeOldTimes
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
PtrList<compressedGeometricField<Type, PatchField, GeoMesh>>&
|
||||
compressedField,
|
||||
const label pos
|
||||
)
|
||||
{
|
||||
// This object is constructed to store the primal solution of time-step i.
|
||||
// The implication is that this happens exactly before solving for i+1,
|
||||
// meaning that the time has shifted and so have the instanteneous primal
|
||||
// fields. So by the time the function is called, UInst() contains the
|
||||
// solution of ith time-step, as an initialization to the solution that it
|
||||
// will be computed at the (i+1)th time-step, UInst().oldTime() contains
|
||||
// also the solution of the ith time-step and UInst().oldTime().oldTime(),
|
||||
// if set, the solution of the (i-1)th time-step. The solution of the
|
||||
// (i-2)th time-step is not necessary to be stored for the continuation of
|
||||
// the run. So, UInst() and UInst().oldTime().oldTime(), if set, are
|
||||
// stored.
|
||||
label nOldTimes = min(field.nOldTimes(), a_);
|
||||
if (nOldTimes > 1)
|
||||
{
|
||||
GeometricField<Type, PatchField, GeoMesh>* oldField = &field.oldTime();
|
||||
compressedField.setSize(nOldTimes-1);
|
||||
for (label i=0; i<nOldTimes-1; i++)
|
||||
{
|
||||
oldField = &oldField->oldTime();
|
||||
compressedField.set
|
||||
(
|
||||
i,
|
||||
compressedGeometricField<Type, PatchField, GeoMesh>::New
|
||||
(
|
||||
*oldField,
|
||||
storageParams_,
|
||||
pos,
|
||||
k_
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void Foam::fullIncompressibleVars::decompressAll
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& GeomField,
|
||||
compressedGeometricField<Type, PatchField, GeoMesh>& current,
|
||||
PtrList<compressedGeometricField<Type, PatchField, GeoMesh>>& oldFields
|
||||
)
|
||||
{
|
||||
// Due to the implication described in storeOldTimes(...) function, the
|
||||
// reference to the GeometricField of the solver that each element of the
|
||||
// oldFields_ is not correct. For example, for a second order time-scheme,
|
||||
// oldFields_ has only one elememt which holds a reference to the
|
||||
// oldTime().oldTime() of the GeometricField known to the solver.
|
||||
// Nevertheless, its stored values must be appended to the oldTime() of the
|
||||
// GeometricField known to the solver.
|
||||
current.decompress();
|
||||
if ( GeomField.nOldTimes() > 1 )
|
||||
{
|
||||
GeometricField<Type, PatchField, GeoMesh>* oldGeomField = &GeomField;
|
||||
//- Scanning only what it has been stored:
|
||||
// i) At the first time-step, nOldTimes() may be zero, but upon
|
||||
// reconstruction the noldTimes of the variablesSet of the solver
|
||||
// will be 1 or 2.
|
||||
// ii) if (a=1) the oldTimes are not stored and as a result can not
|
||||
// be retrieved.
|
||||
forAll(oldFields, iPtr)
|
||||
{
|
||||
oldGeomField = &oldGeomField->oldTime();
|
||||
oldFields[iPtr].decompress(*oldGeomField);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void Foam::fullIncompressibleVars::addStorageMetricsContribution
|
||||
(
|
||||
const compressedGeometricField<Type, PatchField, GeoMesh>& compField,
|
||||
const PtrList<compressedGeometricField<Type, PatchField, GeoMesh>>&
|
||||
compOldField
|
||||
)
|
||||
{
|
||||
forAll (storageMetrics_, Ic)
|
||||
{
|
||||
storageMetrics_[Ic] += compField.storageMetrics()[Ic];
|
||||
forAll(compOldField, iPtr)
|
||||
{
|
||||
storageMetrics_[Ic] += compOldField[iPtr].storageMetrics()[Ic];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void Foam::fullIncompressibleVars::calculateAndWrite
|
||||
(
|
||||
const compressedGeometricField<Type, PatchField, GeoMesh>& compField,
|
||||
const PtrList<compressedGeometricField<Type, PatchField, GeoMesh>>&
|
||||
compOldField,
|
||||
const word& name,
|
||||
label& i
|
||||
)
|
||||
{
|
||||
addStorageMetricsContribution(compField, compOldField);
|
||||
write(++i);
|
||||
writeLog(name);
|
||||
storageMetrics_ = Zero;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,124 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "shortIncompressibleVars.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "IOmanip.H"
|
||||
#include "profiling.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
defineTypeNameAndDebug(shortIncompressibleVars, 0);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
compressedIncompressibleVars,
|
||||
shortIncompressibleVars,
|
||||
dictionary
|
||||
);
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
shortIncompressibleVars::shortIncompressibleVars
|
||||
(
|
||||
incompressibleVars& vs,
|
||||
storageParameters& storageParams
|
||||
)
|
||||
:
|
||||
compressedIncompressibleVars(vs, storageParams)
|
||||
{}
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void shortIncompressibleVars::compress()
|
||||
{
|
||||
addProfiling(shortIncompressibleVars, "shortIncompressibleVars::compress");
|
||||
//scalar startTime = mesh_.time().elapsedCpuTime();
|
||||
p_().compress();
|
||||
DebugInfo
|
||||
<< "DEBUG: p field stored" << endl;
|
||||
phi_().compress();
|
||||
DebugInfo
|
||||
<< "DEBUG: phi field stored" << endl;
|
||||
U_().compress();
|
||||
DebugInfo
|
||||
<< "DEBUG: U field stored" << endl;
|
||||
forAll (RASModelVars_, iPtr)
|
||||
{
|
||||
RASModelVars_[iPtr].compress();
|
||||
DebugInfo
|
||||
<< "DEBUG: " << iPtr + 1 << "th turbulence model field stored"
|
||||
<< endl;
|
||||
}
|
||||
//scalar endTime = mesh_.time().elapsedCpuTime();
|
||||
}
|
||||
|
||||
|
||||
void shortIncompressibleVars::decompress
|
||||
(
|
||||
incompressibleVars& vars
|
||||
)
|
||||
{
|
||||
addProfiling
|
||||
(shortIncompressibleVars, "shortIncompressibleVars::decompress");
|
||||
// Phi must be retrieved first, since the BCs of p and U might depend on
|
||||
// flux
|
||||
phi_().decompress(vars.phiInst());
|
||||
DebugInfo
|
||||
<< "DEBUG: phi field retrieved" << endl;
|
||||
p_().decompress(vars.pInst());
|
||||
DebugInfo
|
||||
<< "DEBUG: p field retrieved" << endl;
|
||||
U_().decompress(vars.UInst());
|
||||
DebugInfo
|
||||
<< "DEBUG: U field retrieved" << endl;
|
||||
incompressible::RASModelVariables& rasVars = vars.RASModelVariables()();
|
||||
if (rasVars.hasTMVar1())
|
||||
{
|
||||
RASModelVars_[0].decompress(rasVars.TMVar1Inst());
|
||||
DebugInfo
|
||||
<< "DEBUG: 1st turbulence model field retrieved" << endl;
|
||||
}
|
||||
if (rasVars.hasTMVar2())
|
||||
{
|
||||
RASModelVars_[1].decompress(rasVars.TMVar2Inst());
|
||||
DebugInfo
|
||||
<< "DEBUG: 2nd turbulence model field retrieved" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,99 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::shortIncompressibleVars
|
||||
|
||||
Description
|
||||
Compresses the current time-instance known by the primal solvers.
|
||||
Does not include oldTimes
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef shortIncompressibleVars_H
|
||||
#define shortIncompressibleVars_H
|
||||
|
||||
#include "compressedIncompressibleVars.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class shortIncompressibleVars Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class shortIncompressibleVars
|
||||
:
|
||||
public compressedIncompressibleVars
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("shortIncompressibleVars");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
shortIncompressibleVars
|
||||
(
|
||||
incompressibleVars& vs,
|
||||
storageParameters& storageParams
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~shortIncompressibleVars() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Compress the incompressibleVars
|
||||
void compress() override;
|
||||
|
||||
//- Function to return the compression metrics (initial size,
|
||||
//- compressed size if compression is applied, etc)
|
||||
void decompress
|
||||
(
|
||||
incompressibleVars& vars
|
||||
) override;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
||||
Copyright (C) 2013-2021 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -103,12 +103,11 @@ void incompressibleVars::setInitFields()
|
||||
// are allocated automatically in RASModelVariables
|
||||
if (solverControl_.storeInitValues())
|
||||
{
|
||||
pInitPtr_.reset(new volScalarField(pInst().name() + "Init", pInst()));
|
||||
UInitPtr_.reset(new volVectorField(UInst().name() + "Init", UInst()));
|
||||
phiInitPtr_.reset
|
||||
(
|
||||
new surfaceScalarField(phiInst().name() + "Init", phiInst())
|
||||
);
|
||||
DebugInfo
|
||||
<< "Allocating Initial Primal Fields" << endl;
|
||||
setInitField(pInitPtr_, pInst());
|
||||
setInitField(UInitPtr_, UInst());
|
||||
setInitField(phiInitPtr_, phiInst());
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,52 +120,9 @@ void incompressibleVars::setMeanFields()
|
||||
if (solverControl_.average())
|
||||
{
|
||||
Info<< "Allocating Mean Primal Fields" << endl;
|
||||
pMeanPtr_.reset
|
||||
(
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
pInst().name()+"Mean",
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
pInst()
|
||||
)
|
||||
);
|
||||
UMeanPtr_.reset
|
||||
(
|
||||
new volVectorField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
UInst().name()+"Mean",
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
UInst()
|
||||
)
|
||||
);
|
||||
phiMeanPtr_.reset
|
||||
(
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
phiInst().name()+"Mean",
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
phiInst()
|
||||
)
|
||||
);
|
||||
|
||||
setMeanField(pMeanPtr_, pInst(), mesh_);
|
||||
setMeanField(UMeanPtr_, UInst(), mesh_);
|
||||
setMeanField(phiMeanPtr_, phiInst(), mesh_);
|
||||
// Correct boundary conditions if necessary
|
||||
if (correctBoundaryConditions_)
|
||||
{
|
||||
@ -230,7 +186,8 @@ void incompressibleVars::correctTurbulentBoundaryConditions()
|
||||
incompressibleVars::incompressibleVars
|
||||
(
|
||||
fvMesh& mesh,
|
||||
solverControl& SolverControl
|
||||
solverControl& SolverControl,
|
||||
scalar readTime
|
||||
)
|
||||
:
|
||||
variablesSet(mesh, SolverControl.solverDict()),
|
||||
@ -242,9 +199,9 @@ incompressibleVars::incompressibleVars
|
||||
turbulence_(nullptr),
|
||||
RASModelVariables_(nullptr),
|
||||
|
||||
pInitPtr_(nullptr),
|
||||
UInitPtr_(nullptr),
|
||||
phiInitPtr_(nullptr),
|
||||
pInitPtr_(),
|
||||
UInitPtr_(),
|
||||
phiInitPtr_(),
|
||||
|
||||
pMeanPtr_(nullptr),
|
||||
UMeanPtr_(nullptr),
|
||||
@ -254,11 +211,43 @@ incompressibleVars::incompressibleVars
|
||||
(
|
||||
SolverControl.solverDict().subOrEmptyDict("fieldReconstruction").
|
||||
getOrDefault<bool>("reconstruct", false)
|
||||
),
|
||||
solDirs_((mesh.solutionD() + Vector<label>::one)/2),
|
||||
writeFields_
|
||||
(
|
||||
SolverControl.solverDict().getOrDefault<bool>("writeFields", true)
|
||||
)
|
||||
{
|
||||
// Necessary for continuation of unsteady solvers. For steady solvers
|
||||
// should have no effect
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
const dimensionedScalar startTime = mesh_.time();
|
||||
const label startTimeIndex = mesh_.time().timeIndex();
|
||||
if (readTime != -1)
|
||||
{
|
||||
// Set time to readTime. Time-index remains unchanged, since
|
||||
// it does not influence fields reading
|
||||
DebugInfo
|
||||
<< "Initializing primal fields begin: time changes to "
|
||||
<< ::Foam::name(readTime) << endl;
|
||||
time.setTime(readTime, startTimeIndex);
|
||||
}
|
||||
setFields();
|
||||
setInitFields();
|
||||
setMeanFields();
|
||||
storeAllocatedFieldNames();
|
||||
if (readTime != -1)
|
||||
{
|
||||
DebugInfo
|
||||
<< "Initializing primal fields end: time changes to "
|
||||
<< ::Foam::name(startTime.value()) << endl;
|
||||
// Restore time
|
||||
time.setTime(startTime, startTimeIndex);
|
||||
}
|
||||
if (!writeFields_)
|
||||
{
|
||||
setWriteOption(IOobject::NO_WRITE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -276,18 +265,32 @@ incompressibleVars::incompressibleVars
|
||||
turbulence_(nullptr),
|
||||
RASModelVariables_(vs.RASModelVariables_.clone()),
|
||||
|
||||
pInitPtr_(allocateRenamedField(vs.pInitPtr_)),
|
||||
UInitPtr_(allocateRenamedField(vs.UInitPtr_)),
|
||||
phiInitPtr_(allocateRenamedField(vs.phiInitPtr_)),
|
||||
pInitPtr_(vs.pInitPtr_.size()),
|
||||
UInitPtr_(vs.UInitPtr_.size()),
|
||||
phiInitPtr_(vs.phiInitPtr_.size()),
|
||||
|
||||
pMeanPtr_(allocateRenamedField(vs.pMeanPtr_)),
|
||||
UMeanPtr_(allocateRenamedField(UMeanPtr_)),
|
||||
UMeanPtr_(allocateRenamedField(vs.UMeanPtr_)),
|
||||
phiMeanPtr_(allocateRenamedField(vs.phiMeanPtr_)),
|
||||
|
||||
correctBoundaryConditions_(vs.correctBoundaryConditions_)
|
||||
correctBoundaryConditions_(vs.correctBoundaryConditions_),
|
||||
allocatedFieldNames_(vs.allocatedFieldNames_),
|
||||
solDirs_(vs.solDirs_)
|
||||
{
|
||||
DebugInfo
|
||||
<< "Calling incompressibleVars copy constructor" << endl;
|
||||
forAll(pInitPtr_, i)
|
||||
{
|
||||
pInitPtr_.set(i, allocateRenamedField(vs.pInitPtr_[i]));
|
||||
}
|
||||
forAll(UInitPtr_, i)
|
||||
{
|
||||
UInitPtr_.set(i, allocateRenamedField(vs.UInitPtr_[i]));
|
||||
}
|
||||
forAll(phiInitPtr_, i)
|
||||
{
|
||||
phiInitPtr_.set(i, allocateRenamedField(vs.phiInitPtr_[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -302,6 +305,23 @@ autoPtr<variablesSet> incompressibleVars::clone() const
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void incompressibleVars::storeAllocatedFieldNames()
|
||||
{
|
||||
allocatedFieldNames_.setSize(3);
|
||||
allocatedFieldNames_[0] = pInst().name();
|
||||
allocatedFieldNames_[1] = phiInst().name();
|
||||
allocatedFieldNames_[2] = UInst().name();
|
||||
if (RASModelVariables_().hasTMVar1())
|
||||
{
|
||||
allocatedFieldNames_.append(RASModelVariables_().TMVar1Inst().name());
|
||||
}
|
||||
if (RASModelVariables_().hasTMVar2())
|
||||
{
|
||||
allocatedFieldNames_.append(RASModelVariables_().TMVar2Inst().name());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const volScalarField& incompressibleVars::p() const
|
||||
{
|
||||
if (solverControl_.useAveragedFields())
|
||||
@ -366,6 +386,7 @@ const surfaceScalarField& incompressibleVars::phi() const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
surfaceScalarField& incompressibleVars::phi()
|
||||
{
|
||||
if (solverControl_.useAveragedFields())
|
||||
@ -384,9 +405,9 @@ void incompressibleVars::restoreInitValues()
|
||||
if (solverControl_.storeInitValues())
|
||||
{
|
||||
Info<< "Restoring field values to initial ones" << endl;
|
||||
pInst() == pInitPtr_();
|
||||
UInst() == UInitPtr_();
|
||||
phiInst() == phiInitPtr_();
|
||||
variablesSet::restoreFieldInitialization(pInitPtr_, pInst());
|
||||
variablesSet::restoreFieldInitialization(phiInitPtr_, phiInst());
|
||||
variablesSet::restoreFieldInitialization(UInitPtr_, UInst());
|
||||
RASModelVariables_().restoreInitValues();
|
||||
}
|
||||
}
|
||||
@ -428,10 +449,28 @@ void incompressibleVars::computeMeanFields()
|
||||
}
|
||||
|
||||
|
||||
void incompressibleVars::computeMeanUnsteadyFields()
|
||||
{
|
||||
if (solverControl_.doAverageTime())
|
||||
{
|
||||
Info<< "Averaging fields" << endl;
|
||||
const scalar dt = mesh_.time().deltaTValue();
|
||||
const scalar elapsedTime
|
||||
= mesh_.time().value() - solverControl_.averageStartTime();
|
||||
scalar oneOverItP1 = dt/(elapsedTime + dt);
|
||||
scalar mult = elapsedTime/(elapsedTime + dt);
|
||||
pMeanPtr_() == pMeanPtr_()*mult + pInst()*oneOverItP1;
|
||||
UMeanPtr_() == UMeanPtr_()*mult + UInst()*oneOverItP1;
|
||||
phiMeanPtr_() == phiMeanPtr_()*mult + phiInst()*oneOverItP1;
|
||||
RASModelVariables_().computeMeanUnsteadyFields();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void incompressibleVars::correctBoundaryConditions()
|
||||
{
|
||||
correctNonTurbulentBoundaryConditions();
|
||||
RASModelVariables_().correctBoundaryConditions(turbulence_());
|
||||
correctTurbulentBoundaryConditions();
|
||||
}
|
||||
|
||||
|
||||
@ -461,6 +500,16 @@ void incompressibleVars::transfer(variablesSet& vars)
|
||||
}
|
||||
|
||||
|
||||
void incompressibleVars::validateTurbulence()
|
||||
{
|
||||
// Update nut
|
||||
if (RASModelVariables_().hasNut())
|
||||
{
|
||||
turbulence()->validate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool incompressibleVars::write() const
|
||||
{
|
||||
// Write dummy fields, for continuation only
|
||||
@ -501,6 +550,56 @@ bool incompressibleVars::write() const
|
||||
}
|
||||
|
||||
|
||||
fvMesh& incompressibleVars::mesh() const
|
||||
{
|
||||
return mesh_;
|
||||
}
|
||||
|
||||
|
||||
const solverControl& incompressibleVars::solverControlReference() const
|
||||
{
|
||||
return solverControl_;
|
||||
}
|
||||
|
||||
|
||||
const wordList& incompressibleVars::allocatedFieldNames() const
|
||||
{
|
||||
return allocatedFieldNames_;
|
||||
}
|
||||
|
||||
|
||||
const Vector<label>& incompressibleVars::solDirs() const
|
||||
{
|
||||
return solDirs_;
|
||||
}
|
||||
|
||||
|
||||
void incompressibleVars::adjustAverageStartTime(const scalar& offset)
|
||||
{
|
||||
solverControl_.averageStartTime() += offset;
|
||||
}
|
||||
|
||||
|
||||
void incompressibleVars::setWriteOption(IOobject::writeOption w)
|
||||
{
|
||||
if (!writeFields_)
|
||||
{
|
||||
w = IOobject::NO_WRITE;
|
||||
}
|
||||
pInst().writeOpt() = w;
|
||||
phiInst().writeOpt() = w;
|
||||
UInst().writeOpt() = w;
|
||||
if (solverControl_.doAverageTime())
|
||||
{
|
||||
pMeanPtr_->writeOpt() = w;
|
||||
phiMeanPtr_->writeOpt() = w;
|
||||
UMeanPtr_->writeOpt() = w;
|
||||
}
|
||||
incompressible::RASModelVariables& rasVars = RASModelVariables_();
|
||||
rasVars.setWriteOption(w);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
||||
Copyright (C) 2013-2021 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -72,10 +72,12 @@ protected:
|
||||
autoPtr<incompressible::RASModelVariables> RASModelVariables_;
|
||||
//autoPtr<volScalarField> TPtr_;
|
||||
|
||||
//- Keep a copy of the initial field values if necessary
|
||||
autoPtr<volScalarField> pInitPtr_;
|
||||
autoPtr<volVectorField> UInitPtr_;
|
||||
autoPtr<surfaceScalarField> phiInitPtr_;
|
||||
//- Keep a copy of the initial values if necessary.
|
||||
// If oldTimes are present, keep them in separate GeometricFields to
|
||||
// avoid been overwritten upon calling GeometricField::storeOldTimes
|
||||
PtrList<volScalarField> pInitPtr_;
|
||||
PtrList<volVectorField> UInitPtr_;
|
||||
PtrList<surfaceScalarField> phiInitPtr_;
|
||||
|
||||
//- Manage mean fields. Turbulent mean fields are managed
|
||||
//- in RASModelVariables
|
||||
@ -88,6 +90,17 @@ protected:
|
||||
// (e.g. averaging, redistribution)
|
||||
bool correctBoundaryConditions_;
|
||||
|
||||
//- Names of the primal fields that are allocated.
|
||||
// The size of the list is properly adjusted
|
||||
wordList allocatedFieldNames_;
|
||||
|
||||
//- Return the vector of solved-for directions in mesh.
|
||||
// 1 indicates valid direction and 0 an invalid direction.
|
||||
const Vector<label> solDirs_;
|
||||
|
||||
//- Should the solver fields be written
|
||||
bool writeFields_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
@ -112,6 +125,10 @@ protected:
|
||||
//- No copy assignment
|
||||
void operator=(const incompressibleVars&);
|
||||
|
||||
//- Function to fill the wordList containing the names of the primal
|
||||
//- fields that are allocated.
|
||||
void storeAllocatedFieldNames();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
@ -127,7 +144,8 @@ public:
|
||||
incompressibleVars
|
||||
(
|
||||
fvMesh& mesh,
|
||||
solverControl& SolverControl
|
||||
solverControl& SolverControl,
|
||||
scalar readTime = -1
|
||||
);
|
||||
|
||||
//- Copy constructor
|
||||
@ -230,6 +248,9 @@ public:
|
||||
//- Compute mean fields on the fly
|
||||
void computeMeanFields();
|
||||
|
||||
//- Compute mean fields on the fly: unsteady runs
|
||||
void computeMeanUnsteadyFields();
|
||||
|
||||
//- correct boundaryconditions for all volFields
|
||||
void correctBoundaryConditions();
|
||||
|
||||
@ -250,9 +271,33 @@ public:
|
||||
//- Transfer the fields of another variablesSet to this
|
||||
virtual void transfer(variablesSet& vars);
|
||||
|
||||
//- Update nut
|
||||
virtual void validateTurbulence();
|
||||
|
||||
//- Write dummy turbulent fields to allow for continuation in
|
||||
//- multi-point, turbulent runs
|
||||
bool write() const;
|
||||
|
||||
//- Return const reference to the fvMesh
|
||||
fvMesh& mesh() const;
|
||||
|
||||
//- Return const reference to the solverDict
|
||||
const solverControl& solverControlReference() const;
|
||||
|
||||
//- const reference to the wordList containing the names of
|
||||
//- the primal fields that are allocated.
|
||||
const wordList& allocatedFieldNames() const override;
|
||||
|
||||
//- const reference to the solution directions
|
||||
//- of the solver.
|
||||
const Vector<label>& solDirs() const;
|
||||
|
||||
//- Set averaging start time in solverControl.
|
||||
// Required by unsteady runs
|
||||
void adjustAverageStartTime(const scalar& offset) override;
|
||||
|
||||
//- Set writeOption of all primal fields
|
||||
void setWriteOption(IOobject::writeOption w);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
||||
Copyright (C) 2013-2021 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -61,12 +61,34 @@ incompressibleAdjointVars::incompressibleAdjointVars
|
||||
*this,
|
||||
objManager
|
||||
)
|
||||
),
|
||||
writeFields_
|
||||
(
|
||||
SolverControl.solverDict().getOrDefault<bool>("writeFields", true)
|
||||
)
|
||||
{}
|
||||
{
|
||||
if (!writeFields_)
|
||||
{
|
||||
setWriteOption(IOobject::NO_WRITE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void incompressibleAdjointVars::restoreInitValues()
|
||||
{
|
||||
if (solverControl_.storeInitValues())
|
||||
{
|
||||
Info<< "Restoring field values to initial ones" << endl;
|
||||
variablesSet::resetAdjointField(paInst());
|
||||
variablesSet::resetAdjointField(UaInst());
|
||||
variablesSet::resetAdjointField(phiaInst());
|
||||
adjointTurbulence_().restoreInitValues();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void incompressibleAdjointVars::resetMeanFields()
|
||||
{
|
||||
if (solverControl_.average())
|
||||
@ -103,6 +125,26 @@ void incompressibleAdjointVars::computeMeanFields()
|
||||
}
|
||||
|
||||
|
||||
void incompressibleAdjointVars::computeMeanUnsteadyFields
|
||||
(
|
||||
const scalar endTime
|
||||
)
|
||||
{
|
||||
if (solverControl_.doAverageTime())
|
||||
{
|
||||
Info<< "Averaging fields" << endl;
|
||||
const scalar dt = mesh_.time().deltaTValue();
|
||||
const scalar elapsedTime = endTime - mesh_.time().value();
|
||||
scalar oneOverItP1 = dt/(elapsedTime + dt);
|
||||
scalar mult = elapsedTime/(elapsedTime + dt);
|
||||
paMeanPtr_() == paMeanPtr_()*mult + paInst()*oneOverItP1;
|
||||
UaMeanPtr_() == UaMeanPtr_()*mult + UaInst()*oneOverItP1;
|
||||
phiaMeanPtr_() == phiaMeanPtr_()*mult + phiaInst()*oneOverItP1;
|
||||
adjointTurbulence_().computeMeanUnsteadyFields(endTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void incompressibleAdjointVars::nullify()
|
||||
{
|
||||
incompressibleAdjointMeanFlowVars::nullify();
|
||||
@ -137,6 +179,28 @@ void incompressibleAdjointVars::updatePrimalBasedQuantities()
|
||||
}
|
||||
|
||||
|
||||
void incompressibleAdjointVars::write()
|
||||
{
|
||||
if (writeFields_)
|
||||
{
|
||||
incompressibleAdjointMeanFlowVars::write();
|
||||
adjointTurbulence_->writeFields();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void incompressibleAdjointVars::setWriteOption(IOobject::writeOption w)
|
||||
{
|
||||
if (!writeFields_)
|
||||
{
|
||||
w = IOobject::NO_WRITE;
|
||||
}
|
||||
|
||||
incompressibleAdjointMeanFlowVars::setWriteOption(w);
|
||||
adjointTurbulence_->setWriteOption(w);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
||||
Copyright (C) 2013-2021 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -64,6 +64,9 @@ protected:
|
||||
//- Adjoint to the turbulence model
|
||||
autoPtr<incompressibleAdjoint::adjointRASModel> adjointTurbulence_;
|
||||
|
||||
//- Should the solver fields be written
|
||||
bool writeFields_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
@ -111,18 +114,30 @@ public:
|
||||
inline autoPtr<incompressibleAdjoint::adjointRASModel>&
|
||||
adjointTurbulence();
|
||||
|
||||
//- Restore field values to the initial ones
|
||||
void restoreInitValues();
|
||||
|
||||
//- Reset mean fields to zero
|
||||
void resetMeanFields();
|
||||
|
||||
//- Compute mean fields on the fly
|
||||
//- Compute mean fields on the fly: steady runs
|
||||
void computeMeanFields();
|
||||
|
||||
//- Compute mean fields on the fly: unsteady runs
|
||||
void computeMeanUnsteadyFields(const scalar endTime);
|
||||
|
||||
//- Nullify all adjoint fields
|
||||
virtual void nullify();
|
||||
|
||||
//- Update primal based quantities of the adjoint boundary
|
||||
// conditions
|
||||
virtual void updatePrimalBasedQuantities();
|
||||
|
||||
//- Write all adjoint fields
|
||||
virtual void write();
|
||||
|
||||
//- Set writeOption of all adjoint fields
|
||||
void setWriteOption(IOobject::writeOption w);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
||||
Copyright (C) 2013-2021 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -57,6 +57,7 @@ void incompressibleAdjointMeanFlowVars::setFields()
|
||||
mesh_.setFluxRequired(paPtr_->name());
|
||||
}
|
||||
|
||||
|
||||
void incompressibleAdjointMeanFlowVars::setMeanFields()
|
||||
{
|
||||
// Allocate mean fields
|
||||
@ -65,51 +66,9 @@ void incompressibleAdjointMeanFlowVars::setMeanFields()
|
||||
if (solverControl_.average())
|
||||
{
|
||||
Info<< "Allocating Mean Adjoint Fields" << endl;
|
||||
paMeanPtr_.reset
|
||||
(
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
paInst().name() + "Mean",
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
paInst()
|
||||
)
|
||||
);
|
||||
UaMeanPtr_.reset
|
||||
(
|
||||
new volVectorField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
UaInst().name() + "Mean",
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
UaInst()
|
||||
)
|
||||
);
|
||||
phiaMeanPtr_.reset
|
||||
(
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
phiaInst().name() + "Mean",
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
phiaInst()
|
||||
)
|
||||
);
|
||||
variablesSet::setMeanField(paMeanPtr_, paInst(), mesh_);
|
||||
variablesSet::setMeanField(UaMeanPtr_, UaInst(), mesh_);
|
||||
variablesSet::setMeanField(phiaMeanPtr_, phiaInst(), mesh_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,12 +195,43 @@ const solverControl& incompressibleAdjointMeanFlowVars::getSolverControl() const
|
||||
|
||||
void incompressibleAdjointMeanFlowVars::nullify()
|
||||
{
|
||||
// Nullify instantaneous fields
|
||||
variablesSet::nullifyField(paPtr_());
|
||||
variablesSet::nullifyField(UaPtr_());
|
||||
variablesSet::nullifyField(phiaPtr_());
|
||||
}
|
||||
|
||||
|
||||
void incompressibleAdjointMeanFlowVars::write()
|
||||
{
|
||||
// Write instantaneous fields
|
||||
variablesSet::writeField(paPtr_());
|
||||
variablesSet::writeField(UaPtr_());
|
||||
variablesSet::writeField(phiaPtr_());
|
||||
// Write mean fields
|
||||
if (solverControl_.average())
|
||||
{
|
||||
variablesSet::writeField(paMeanPtr_());
|
||||
variablesSet::writeField(UaMeanPtr_());
|
||||
variablesSet::writeField(phiaMeanPtr_());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void incompressibleAdjointMeanFlowVars::setWriteOption(IOobject::writeOption w)
|
||||
{
|
||||
paPtr_().writeOpt() = w;
|
||||
UaPtr_().writeOpt() = w;
|
||||
phiaPtr_().writeOpt() = w;
|
||||
if (solverControl_.doAverageTime())
|
||||
{
|
||||
paMeanPtr_->writeOpt() = w;
|
||||
UaMeanPtr_->writeOpt() = w;
|
||||
phiaMeanPtr_->writeOpt() = w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
@ -183,6 +183,12 @@ public:
|
||||
|
||||
//- Nullify all adjoint fields
|
||||
virtual void nullify();
|
||||
|
||||
//- Write all adjoint fields
|
||||
virtual void write();
|
||||
|
||||
//- Set writeOption of all adjoint fields
|
||||
void setWriteOption(IOobject::writeOption w);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -199,6 +199,32 @@ void variablesSet::transfer(variablesSet& vars)
|
||||
}
|
||||
|
||||
|
||||
void variablesSet::validateTurbulence()
|
||||
{
|
||||
// Does nothing in base
|
||||
}
|
||||
|
||||
|
||||
const scalarList& variablesSet::storageMetrics() const
|
||||
{
|
||||
NotImplemented
|
||||
return demoScalarList_;
|
||||
}
|
||||
|
||||
|
||||
const wordList& variablesSet::allocatedFieldNames() const
|
||||
{
|
||||
NotImplemented
|
||||
return demoWordList_;
|
||||
}
|
||||
|
||||
|
||||
void variablesSet::adjustAverageStartTime(const scalar& offset)
|
||||
{
|
||||
// Does nothing in base
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
||||
Copyright (C) 2013-2019 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -84,6 +84,10 @@ private:
|
||||
const bool useSolverNameForFields
|
||||
);
|
||||
|
||||
//- Demo scalarList for virtual function storageMetrics()
|
||||
scalarList demoScalarList_;
|
||||
wordList demoWordList_;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
@ -101,12 +105,6 @@ protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
autoPtr<GeometricField<Type, PatchField, GeoMesh>> allocateRenamedField
|
||||
(
|
||||
const autoPtr<GeometricField<Type, PatchField, GeoMesh>>& bf
|
||||
);
|
||||
|
||||
//- Swap autoPtrs and rename managed fields
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void swapAndRename
|
||||
@ -155,6 +153,27 @@ public:
|
||||
|
||||
// Set functions. Static in order to be used by other classes as well
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
static autoPtr<GeometricField<Type, PatchField, GeoMesh>>
|
||||
allocateRenamedField
|
||||
(
|
||||
const refPtr<GeometricField<Type, PatchField, GeoMesh>>& bf
|
||||
);
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
static autoPtr<GeometricField<Type, PatchField, GeoMesh>>
|
||||
allocateRenamedField
|
||||
(
|
||||
const autoPtr<GeometricField<Type, PatchField, GeoMesh>>& bf
|
||||
);
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
static autoPtr<GeometricField<Type, PatchField, GeoMesh>>
|
||||
allocateRenamedField
|
||||
(
|
||||
const GeometricField<Type, PatchField, GeoMesh>& bf
|
||||
);
|
||||
|
||||
//- Read vol fields
|
||||
template<class Type>
|
||||
static void setField
|
||||
@ -221,8 +240,70 @@ public:
|
||||
GeometricField<Type, PatchField, GeoMesh>& fieldPtr
|
||||
);
|
||||
|
||||
//- Write field and old times, if present
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
static void writeField
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& fieldPtr
|
||||
);
|
||||
|
||||
//- Set initial field
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
static void setInitField
|
||||
(
|
||||
PtrList<GeometricField<Type, PatchField, GeoMesh>>& fieldInit,
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
);
|
||||
|
||||
//- Reset field to its initial state
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
static void restoreFieldInitialization
|
||||
(
|
||||
PtrList<GeometricField<Type, PatchField, GeoMesh>>& exact,
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
);
|
||||
|
||||
//- Reset field and old values to zero
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
static void resetAdjointField
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
);
|
||||
|
||||
//- Set mean field
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
static void setMeanField
|
||||
(
|
||||
refPtr<GeometricField<Type, PatchField, GeoMesh>>& meanFieldPtr,
|
||||
const GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
const fvMesh& mesh
|
||||
);
|
||||
|
||||
//- Set mean field
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
static void setMeanField
|
||||
(
|
||||
autoPtr<GeometricField<Type, PatchField, GeoMesh>>& meanFieldPtr,
|
||||
const GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
const fvMesh& mesh
|
||||
);
|
||||
|
||||
//- Transfer the fields of another variablesSet to this
|
||||
virtual void transfer(variablesSet& vars);
|
||||
|
||||
//- Update nut
|
||||
virtual void validateTurbulence();
|
||||
|
||||
//- Function to return the compression metrics (initial size,
|
||||
//- compressed size, etc)
|
||||
virtual const scalarList& storageMetrics() const;
|
||||
|
||||
//- Function to return the names of all the primal fields that are
|
||||
//- allocated
|
||||
virtual const wordList& allocatedFieldNames() const;
|
||||
|
||||
//- Does nothing in base
|
||||
virtual void adjustAverageStartTime(const scalar& offset);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
||||
Copyright (C) 2013-2019 FOSS GP
|
||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
||||
Copyright (C) 2013-2022 FOSS GP
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -76,7 +76,7 @@ GeometricField<Type, PatchField, GeoMesh>* variablesSet::allocateNamedField
|
||||
DebugInfo
|
||||
<< bField << endl;
|
||||
|
||||
return (new fieldType(io, mesh, dict));
|
||||
return (new fieldType(io, mesh, dict, true));
|
||||
}
|
||||
|
||||
|
||||
@ -161,31 +161,6 @@ bool variablesSet::readFieldOK
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
autoPtr<GeometricField<Type, PatchField, GeoMesh>>
|
||||
variablesSet::allocateRenamedField
|
||||
(
|
||||
const autoPtr<GeometricField<Type, PatchField, GeoMesh>>& bf
|
||||
)
|
||||
{
|
||||
typedef GeometricField<Type, PatchField, GeoMesh> fieldType;
|
||||
autoPtr<fieldType> returnField(nullptr);
|
||||
if (bf.valid())
|
||||
{
|
||||
const word timeName = bf().mesh().time().timeName();
|
||||
returnField.reset
|
||||
(
|
||||
new fieldType
|
||||
(
|
||||
bf().name() + timeName,
|
||||
bf()
|
||||
)
|
||||
);
|
||||
}
|
||||
return returnField;
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void variablesSet::swapAndRename
|
||||
(
|
||||
@ -217,6 +192,53 @@ void variablesSet::swapAndRename
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
autoPtr<GeometricField<Type, PatchField, GeoMesh>>
|
||||
variablesSet::allocateRenamedField
|
||||
(
|
||||
const refPtr<GeometricField<Type, PatchField, GeoMesh>>& bf
|
||||
)
|
||||
{
|
||||
typedef GeometricField<Type, PatchField, GeoMesh> fieldType;
|
||||
autoPtr<fieldType> returnField(nullptr);
|
||||
if (bf.valid())
|
||||
{
|
||||
returnField = allocateRenamedField(bf());
|
||||
}
|
||||
return returnField;
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
autoPtr<GeometricField<Type, PatchField, GeoMesh>>
|
||||
variablesSet::allocateRenamedField
|
||||
(
|
||||
const autoPtr<GeometricField<Type, PatchField, GeoMesh>>& bf
|
||||
)
|
||||
{
|
||||
typedef GeometricField<Type, PatchField, GeoMesh> fieldType;
|
||||
autoPtr<fieldType> returnField(nullptr);
|
||||
if (bf.valid())
|
||||
{
|
||||
returnField = allocateRenamedField(bf());
|
||||
}
|
||||
return returnField;
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
autoPtr<GeometricField<Type, PatchField, GeoMesh>>
|
||||
variablesSet::allocateRenamedField
|
||||
(
|
||||
const GeometricField<Type, PatchField, GeoMesh>& bf
|
||||
)
|
||||
{
|
||||
typedef GeometricField<Type, PatchField, GeoMesh> fieldType;
|
||||
const word timeName = bf.mesh().time().timeName();
|
||||
return autoPtr<fieldType>::New(bf.name() + timeName, bf);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void variablesSet::setField
|
||||
(
|
||||
@ -358,6 +380,155 @@ void variablesSet::nullifyField
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void variablesSet::writeField
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
)
|
||||
{
|
||||
field.write();
|
||||
for (label i = 0; i<field.nOldTimes() - 1; ++i)
|
||||
{
|
||||
writeField(field.oldTime());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void variablesSet::setInitField
|
||||
(
|
||||
PtrList<GeometricField<Type, PatchField, GeoMesh>>& fieldInit,
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
)
|
||||
{
|
||||
// Store fields at the current and (nOldTimes - 1) time-steps
|
||||
// since the last oldTime value is not for restarts
|
||||
// Avoiding the storage to a new GeometricField with its oldTimes set
|
||||
// due to the overwriting of the latter when time advances
|
||||
typedef GeometricField<Type, PatchField, GeoMesh> fieldType;
|
||||
fieldInit.setSize(max(field.nOldTimes(), 1));
|
||||
fieldInit.set(0, new fieldType(field.name() + "Init" + name(0), field));
|
||||
GeometricField<Type, PatchField, GeoMesh>* oldField = &field;
|
||||
for (label i = 1; i < fieldInit.size(); ++i)
|
||||
{
|
||||
oldField = &oldField->oldTime();
|
||||
fieldInit.set
|
||||
(
|
||||
i,
|
||||
new fieldType(field.name() + "Init" + name(i), *oldField)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void variablesSet::restoreFieldInitialization
|
||||
(
|
||||
PtrList<GeometricField<Type, PatchField, GeoMesh>>& exact,
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
)
|
||||
{
|
||||
if (!exact.size())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "DataList to be used for restoring primal "
|
||||
<< "fields is not set" << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
// Restore GeometricField together with its oldTimes
|
||||
field == exact[0];
|
||||
label nI(1);
|
||||
GeometricField<Type, PatchField, GeoMesh>* oldField = &field;
|
||||
// Restore old times stored in exact
|
||||
while (nI < exact.size())
|
||||
{
|
||||
oldField = &oldField->oldTime();
|
||||
*oldField == exact[nI];
|
||||
++nI;
|
||||
}
|
||||
// Covers the rare case of not having read the _0 fields (to be stored in
|
||||
// exact) but there is the need of re-setting the oldTimes
|
||||
while (nI < field.nOldTimes())
|
||||
{
|
||||
oldField = &oldField->oldTime();
|
||||
*oldField == exact[0];
|
||||
nI++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void variablesSet::resetAdjointField
|
||||
(
|
||||
GeometricField<Type, PatchField, GeoMesh>& field
|
||||
)
|
||||
{
|
||||
dimensioned<Type> zero(field.dimensions(), Zero);
|
||||
field == zero;
|
||||
// Restore oldTimes to zero too
|
||||
GeometricField<Type, PatchField, GeoMesh>* oldField = &field;
|
||||
for (label i = 0; i < field.nOldTimes(); ++i)
|
||||
{
|
||||
oldField = &oldField->oldTime();
|
||||
*oldField == zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void variablesSet::setMeanField
|
||||
(
|
||||
refPtr<GeometricField<Type, PatchField, GeoMesh>>& meanFieldPtr,
|
||||
const GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
const fvMesh& mesh
|
||||
)
|
||||
{
|
||||
meanFieldPtr.reset
|
||||
(
|
||||
new GeometricField<Type, PatchField, GeoMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
field.name() + "Mean",
|
||||
mesh.time().timeName(),
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
field,
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
void variablesSet::setMeanField
|
||||
(
|
||||
autoPtr<GeometricField<Type, PatchField, GeoMesh>>& meanFieldPtr,
|
||||
const GeometricField<Type, PatchField, GeoMesh>& field,
|
||||
const fvMesh& mesh
|
||||
)
|
||||
{
|
||||
meanFieldPtr.reset
|
||||
(
|
||||
new GeometricField<Type, PatchField, GeoMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
field.name()+"Mean",
|
||||
mesh.time().timeName(),
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
field,
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
@ -0,0 +1,748 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "Ostream.H"
|
||||
#include "binomialCheckPointing.H"
|
||||
#include "memInfo.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "IOmanip.H"
|
||||
#include "messageStream.H"
|
||||
#include "primalSolver.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(binomialCheckPointing, 0);
|
||||
defineRunTimeSelectionTable(binomialCheckPointing, dictionary);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
primalStorage,
|
||||
binomialCheckPointing,
|
||||
primalStorage
|
||||
);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::labelList Foam::binomialCheckPointing::hostStartProcess
|
||||
(
|
||||
wordList& hostNames
|
||||
) const
|
||||
{
|
||||
// Gather host names for all processors
|
||||
wordList machineName(Pstream::nProcs());
|
||||
machineName[Pstream::myProcNo()] = hostName();
|
||||
Pstream::gatherList(machineName);
|
||||
Pstream::scatterList(machineName);
|
||||
hostNames = machineName;
|
||||
|
||||
// Start processor ID for each host; to be resized
|
||||
const label nProcs(Pstream::nProcs());
|
||||
labelList hostStartProcess(nProcs + 1, 0);
|
||||
|
||||
label iHost(0);
|
||||
word prev(word::null);
|
||||
for (label procI = 0; procI < nProcs; ++procI)
|
||||
{
|
||||
if (machineName[procI] != prev)
|
||||
{
|
||||
hostStartProcess[iHost] = procI;
|
||||
prev = machineName[procI];
|
||||
iHost++;
|
||||
}
|
||||
}
|
||||
// Allocate an additional entry for easy looping over start
|
||||
// of this host and the next one
|
||||
hostStartProcess.setSize(iHost + 1);
|
||||
hostStartProcess[iHost] = nProcs;
|
||||
return hostStartProcess;
|
||||
}
|
||||
|
||||
|
||||
Foam::scalar Foam::binomialCheckPointing::checkPointSize()
|
||||
{
|
||||
Time& time = const_cast<Time&>(mesh_.time());
|
||||
label startTimeIndex = mesh_.time().timeIndex();
|
||||
dimensionedScalar startTime = mesh_.time();
|
||||
|
||||
Info<< "CheckPoint size computation:: Time = "
|
||||
<< time.timeName() << nl << endl;
|
||||
primalSolver_.solveIter();
|
||||
checkPoint temp(storageParams_());
|
||||
incompressibleVars& incoVars = refCast<incompressibleVars>(variablesSet_);
|
||||
temp.setPlaceHolder(false);
|
||||
temp.store(incoVars);
|
||||
|
||||
time.setTime(startTime, startTimeIndex);
|
||||
|
||||
return temp.storageMetrics()[1];
|
||||
}
|
||||
|
||||
|
||||
unsigned long long Foam::binomialCheckPointing::maxNumberOfCheckPoints()
|
||||
{
|
||||
// Find checkpoint size per processor (in MB)
|
||||
scalarList size(Pstream::nProcs());
|
||||
size[Pstream::myProcNo()] = checkPointSize()*1.e-6;
|
||||
Pstream::gatherList(size);
|
||||
Pstream::scatterList(size);
|
||||
if (!memInfo().valid())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "memInfo is invalid" << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
// Available memory in MB. Is stored on a per-processor base but actually
|
||||
// refers to the host. Use with caution
|
||||
scalarList free(Pstream::nProcs());
|
||||
free[Pstream::myProcNo()] = memInfo().update().free()*1.e-3;
|
||||
Pstream::gatherList(free);
|
||||
Pstream::scatterList(free);
|
||||
|
||||
// Host name, per process
|
||||
wordList hostNames(0);
|
||||
// Start processor ID per host
|
||||
labelList hostStartProcessID(hostStartProcess(hostNames));
|
||||
label nHosts(hostStartProcessID.size() - 1);
|
||||
|
||||
// Determine the number of checkpoints that can be allocated as the
|
||||
// minimum from all hosts
|
||||
labelList hostCheckPointSize(nHosts, 0);
|
||||
label nCheckPoints(pTraits<label>::max);
|
||||
label limitingHostID(-1);
|
||||
for (label iHost = 0; iHost < nHosts; ++iHost)
|
||||
{
|
||||
const label start(hostStartProcessID[iHost]);
|
||||
const label end(hostStartProcessID[iHost + 1]);
|
||||
label& hostSize = hostCheckPointSize[iHost];
|
||||
for (label procI = start; procI < end; ++procI)
|
||||
{
|
||||
hostSize += size[procI];
|
||||
}
|
||||
if (hostSize == 0)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "hostSize = 0!!" << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
scalar val = free[start]/hostSize;
|
||||
label nHostCheckPoints(pTraits<label>::max);
|
||||
if (val <= 0)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "free[start], hostSize = " << free[start]
|
||||
<< " " << hostSize << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
else if (val < pTraits<label>::max)
|
||||
{
|
||||
nHostCheckPoints = val;
|
||||
}
|
||||
if (nHostCheckPoints < nCheckPoints)
|
||||
{
|
||||
nCheckPoints = nHostCheckPoints;
|
||||
limitingHostID = iHost;
|
||||
}
|
||||
}
|
||||
|
||||
// Print global check point size
|
||||
Info<< nl << "Global size of a checkpoint is "
|
||||
<< sum(size) << " MBs" << nl
|
||||
<< "Total free memory in all hosts: "
|
||||
<< sum(free)*1.e-3 << " GBs" << endl;
|
||||
|
||||
// Print max number of check points that fit in the most limiting host
|
||||
Info<< "Approximately " << nCheckPoints
|
||||
<< " checkpoints can be stored, "
|
||||
<< "without accounting for cashed memory " << endl;
|
||||
|
||||
// Print information on a per host basis
|
||||
if (debug > 1)
|
||||
{
|
||||
Info<< nl
|
||||
<< setw(23) << "Host" << " | "
|
||||
<< setw(23) << "Checkpoint size (kBs)" << " | "
|
||||
<< setw(23) << "Available memory (kBs)" << " | "
|
||||
<< setw(23) << "Max checkpoints (local)"
|
||||
<< nl;
|
||||
for (label iHost = 0; iHost < nHosts; ++iHost)
|
||||
{
|
||||
const label start(hostStartProcessID[iHost]);
|
||||
Info<< setw(23) << hostNames[start] << " "
|
||||
<< setw(23) << hostCheckPointSize[iHost] << " "
|
||||
<< setw(23) << free[start] << " "
|
||||
<< setw(23) << free[start]/hostCheckPointSize[iHost]
|
||||
<< endl;
|
||||
}
|
||||
Info<< endl;
|
||||
}
|
||||
|
||||
string limitingHost;
|
||||
if (Pstream::myProcNo() == hostStartProcessID[limitingHostID])
|
||||
{
|
||||
limitingHost = hostName();
|
||||
}
|
||||
reduce(limitingHost, sumOp<word>());
|
||||
Info<< "Limiting factor is host " << limitingHost << nl << endl;
|
||||
|
||||
return nCheckPoints;
|
||||
}
|
||||
|
||||
|
||||
void Foam::binomialCheckPointing::initialize()
|
||||
{
|
||||
nCheckPoints_ = storageDict_.subDict("storageParameters").
|
||||
get<label>("nCheckPoints") + 1;
|
||||
if (nCheckPoints_ < 1)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "nCheckPoints = " << nCheckPoints_ << ". Please provide a "
|
||||
<< "value >=1" << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
/*if (storageDict_.subDict("storageParameters").found("nCheckPoints"))
|
||||
{
|
||||
nCheckPoints_ = storageDict_.subDict("storageParameters").
|
||||
get<label>("nCheckPoints");
|
||||
}
|
||||
else
|
||||
{
|
||||
nCheckPoints_ = maxNumberOfCheckPoints();
|
||||
}*/
|
||||
checkPoints_.setSize(nCheckPoints_);
|
||||
indirectAddressing_ = identity(nCheckPoints_);
|
||||
Info<< nl << "Total number of checkpoints = "
|
||||
<< nCheckPoints_ << nl << endl;
|
||||
for (label fI = 0; fI < nCheckPoints_; ++fI)
|
||||
{
|
||||
checkPoints_.set(fI, new checkPoint(storageParams_()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::binomialCheckPointing::gatherMetrics()
|
||||
{
|
||||
if (storageParams_().timing())
|
||||
{
|
||||
for (scalar& smI : storageMetrics_)
|
||||
{
|
||||
reduce(smI, sumOp<scalar>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::binomialCheckPointing::setMetricsFilesPtr()
|
||||
{
|
||||
fileName filePath =
|
||||
storageFolder_/"AllOptCycles" + primalSolver_.solverName();
|
||||
if (!isFile(filePath))
|
||||
{
|
||||
DebugInfo
|
||||
<< "Creating file: " << filePath << endl;
|
||||
metricsFilePtr_.reset(new OFstream(filePath));
|
||||
if (!metricsFilePtr_()())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Stream has failed." << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
if (!isFile(filePath))
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Error while creating file: " << filePath << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
unsigned int width = IOstream::defaultPrecision() + 6;
|
||||
metricsFilePtr_()
|
||||
<< setw(width) << "nCheckPoints" << tab
|
||||
<< setw(width) << "Overall CR (CR_0)" << tab
|
||||
<< setw(width) << "ZFP CR (CR_ZFP)" << tab
|
||||
<< setw(width) << "Initial Size (Mb)" << tab
|
||||
<< setw(width) << "Initial Size Saved (Mb)" << tab
|
||||
<< setw(width) << "Compressed Size (Mb)"<< endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
metricsFilePtr_.reset
|
||||
(
|
||||
new OFstream
|
||||
(
|
||||
filePath,
|
||||
IOstream::ASCII,
|
||||
IOstream::currentVersion,
|
||||
IOstream::UNCOMPRESSED,
|
||||
true
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::binomialCheckPointing::setCheckPointsFilesPtr()
|
||||
{
|
||||
fileName filePath =
|
||||
storageFolder_/"checkPoints" + primalSolver_.solverName();
|
||||
if (!isFile(filePath))
|
||||
{
|
||||
DebugInfo
|
||||
<< "Creating file: " << filePath << endl;
|
||||
checkPointsFilePtr_.reset(new OFstream(filePath));
|
||||
if (!checkPointsFilePtr_()())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Stream has failed." << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
if (!isFile(filePath))
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Error while creating file: " << filePath << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
unsigned int width = IOstream::defaultPrecision() + 6;
|
||||
checkPointsFilePtr_()
|
||||
<< setw(width) << "S/N" << tab
|
||||
<< setw(width) << "TimeIndex" << tab
|
||||
<< setw(width) << "Level" << tab
|
||||
<< setw(width) << "Time" << tab
|
||||
<< setw(width) << "Placeholder" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
checkPointsFilePtr_.reset
|
||||
(
|
||||
new OFstream
|
||||
(
|
||||
filePath,
|
||||
IOstream::ASCII,
|
||||
IOstream::currentVersion,
|
||||
IOstream::UNCOMPRESSED,
|
||||
true
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::binomialCheckPointing::writeToFile()
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
if (!metricsFilePtr_)
|
||||
{
|
||||
setMetricsFilesPtr();
|
||||
}
|
||||
const scalar& initialSize = storageMetrics_[0];
|
||||
const scalar& uncompressedRoughSize = storageMetrics_[1];
|
||||
const scalar& uncompressedSize = storageMetrics_[2];
|
||||
const scalar& compressedSize = storageMetrics_[3];
|
||||
|
||||
unsigned int width = IOstream::defaultPrecision() + 6;
|
||||
metricsFilePtr_()
|
||||
<< setprecision(IOstream::defaultPrecision());
|
||||
metricsFilePtr_()
|
||||
<< setw(width) << activeCheckPoints_ << tab
|
||||
<< setw(width) << uncompressedRoughSize/compressedSize << tab
|
||||
<< setw(width) << uncompressedSize/compressedSize << tab
|
||||
<< setw(width) << initialSize*1.e-6 << tab
|
||||
<< setw(width) << uncompressedRoughSize*1.e-6 << tab
|
||||
<< setw(width) << compressedSize*1e-6 << endl;
|
||||
if (!checkPointsFilePtr_)
|
||||
{
|
||||
setCheckPointsFilesPtr();
|
||||
}
|
||||
checkPointsFilePtr_()
|
||||
<< setprecision(IOstream::defaultPrecision());
|
||||
for (label fI = 0; fI < nCheckPoints_; ++fI)
|
||||
{
|
||||
const label pos = indirectAddressing_[fI];
|
||||
if (checkPoints_[pos].active())
|
||||
{
|
||||
checkPointsFilePtr_()
|
||||
<< setw(width) << fI << tab
|
||||
<< setw(width) << checkPoints_[pos].timeIndex() << tab
|
||||
<< setw(width) << checkPoints_[pos].level() << tab
|
||||
<< setw(width) << name(checkPoints_[pos].timeValue())
|
||||
<< setw(width) << checkPoints_[pos].placeHolder()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
checkPointsFilePtr_() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::binomialCheckPointing::calcStorageMetrics()
|
||||
{
|
||||
storageMetrics_ = checkPoints_[0].storageMetrics();
|
||||
for (label fI = 1; fI < nCheckPoints_; ++fI)
|
||||
{
|
||||
if (checkPoints_[fI].active() && !checkPoints_[fI].placeHolder())
|
||||
{
|
||||
storageMetrics_ =
|
||||
storageMetrics_
|
||||
+ checkPoints_[fI].storageMetrics();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::binomialCheckPointing::binomialCheckPointing
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
)
|
||||
:
|
||||
primalStorage(primalSolverObj, storageDict),
|
||||
totalSteps_(0),
|
||||
recomputationSteps_(0),
|
||||
storageParams_
|
||||
(
|
||||
storageParameters::New
|
||||
(mesh_, storageDict_, variablesSet_.allocatedFieldNames())
|
||||
),
|
||||
adjustTimeStep_(storageParams_->adjustTimeStep()),
|
||||
checkPoints_(),
|
||||
startingTime_(mesh_.time().startTime()),
|
||||
activeCheckPoints_(0),
|
||||
iPtr_(storagePtrs_[0])
|
||||
{
|
||||
makeFolder();
|
||||
initialize();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::binomialCheckPointing> Foam::binomialCheckPointing::New
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
)
|
||||
{
|
||||
return autoPtr<binomialCheckPointing>
|
||||
(
|
||||
new binomialCheckPointing(primalSolverObj, storageDict)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::binomialCheckPointing::scratch()
|
||||
{
|
||||
indirectAddressing_ = identity(nCheckPoints_);
|
||||
for (checkPoint& cp : checkPoints_)
|
||||
{
|
||||
cp.empty();
|
||||
}
|
||||
totalSteps_ = 0;
|
||||
recomputationSteps_ = 0;
|
||||
activeCheckPoints_ = 0;
|
||||
storageMetrics_.clear();
|
||||
iPtr_ = -1;
|
||||
}
|
||||
|
||||
|
||||
void Foam::binomialCheckPointing::storeVariables()
|
||||
{
|
||||
label jPtr(0);
|
||||
// Add current to placeholder
|
||||
|
||||
// Find the dispensable checkpoint with the largest time index
|
||||
// idis holds the index of the checkpoint that will be removed.
|
||||
label maxlevel = 0;
|
||||
// Despensable checkpoint index
|
||||
label idis = 0;
|
||||
for (label i = nCheckPoints_ - 1; i >= 1; --i)
|
||||
{
|
||||
if (maxlevel > checkPoints_[indirectAddressing_[i]].level())
|
||||
{
|
||||
// Keep the index only the first time it enters, since it
|
||||
// will have the greater index
|
||||
idis = i;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxlevel = checkPoints_[indirectAddressing_[i]].level();
|
||||
}
|
||||
}
|
||||
if (activeCheckPoints_ < nCheckPoints_)
|
||||
{
|
||||
// Scenario 1: not all checkpoints allocated yet.
|
||||
DebugInfo
|
||||
<< "Scenario 1" << endl;
|
||||
const label pos = indirectAddressing_[activeCheckPoints_];
|
||||
checkPoints_[pos].setPlaceHolder(false);
|
||||
jPtr = activeCheckPoints_;
|
||||
activeCheckPoints_++;
|
||||
}
|
||||
else if (idis > 0)
|
||||
{
|
||||
// Scenario 2:
|
||||
// at least one checkpoint is despensable. Create a new checkPoint
|
||||
// at the end of the indirect addressing list of level 0.
|
||||
DebugInfo
|
||||
<< "Scenario 2" << endl;
|
||||
const label pos = indirectAddressing_[idis];
|
||||
for (label i = idis; i < nCheckPoints_ - 1; ++i)
|
||||
{
|
||||
indirectAddressing_[i] = indirectAddressing_[i + 1];
|
||||
}
|
||||
indirectAddressing_[nCheckPoints_ - 1] = pos;
|
||||
checkPoints_[pos].setPlaceHolder(false);
|
||||
jPtr = nCheckPoints_ - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Scenario 3:
|
||||
// no checkpoint is despensable. Overwrite last checkpoint
|
||||
// and increase its level
|
||||
DebugInfo
|
||||
<< "Scenario 3" << endl;
|
||||
const label pos = indirectAddressing_[nCheckPoints_ - 1];
|
||||
checkPoints_[pos].setPlaceHolder(true);
|
||||
jPtr = nCheckPoints_ - 1;
|
||||
}
|
||||
|
||||
// If the previous time-step is in the current set of check-points and
|
||||
// checkpoint is not a placeholder checkpoint store the solution. When
|
||||
// retrieving the solution at scenario 2, the checkpoint is not set as a
|
||||
// placeholder as Wang proposes, so there is no need to store again the
|
||||
// solution in that case.
|
||||
if
|
||||
(
|
||||
(
|
||||
time_.timeIndex() - 1
|
||||
== checkPoints_[indirectAddressing_[jPtr - 1]].timeIndex()
|
||||
)
|
||||
&& checkPoints_[indirectAddressing_[jPtr - 1]].placeHolder()
|
||||
)
|
||||
{
|
||||
DebugInfo
|
||||
<< "Storing time-step with time, timeIndex = "
|
||||
<< name(checkPoints_[indirectAddressing_[jPtr - 1]].timeValue())
|
||||
<< " "
|
||||
<< checkPoints_[indirectAddressing_[jPtr - 1]].timeIndex()
|
||||
<< endl;
|
||||
incompressibleVars& incoVars =
|
||||
refCast<incompressibleVars>(variablesSet_);
|
||||
checkPoints_[indirectAddressing_[jPtr - 1]].store(incoVars);
|
||||
}
|
||||
calcStorageMetrics();
|
||||
++iPtr_;
|
||||
if (debug)
|
||||
{
|
||||
Info<< "checkPoint time values -->Start<--" << endl;
|
||||
for (label fI = 0; fI < nCheckPoints_; ++fI)
|
||||
{
|
||||
const label pos = indirectAddressing_[fI];
|
||||
Info<< "Checkpoint-ID, indirectAddressing, timeIndex, "
|
||||
<< "level, time, placeHolder = "
|
||||
<< fI << " "
|
||||
<< pos << " "
|
||||
<< checkPoints_[pos].timeIndex() << " "
|
||||
<< checkPoints_[pos].level() << " "
|
||||
<< name(checkPoints_[pos].timeValue()) << " "
|
||||
<< checkPoints_[pos].placeHolder() << endl;
|
||||
}
|
||||
Info<< "checkPoint time values --> End <--" << endl;
|
||||
}
|
||||
// Accumulate the primal step to counter
|
||||
totalSteps_++;
|
||||
}
|
||||
|
||||
|
||||
void Foam::binomialCheckPointing::storeInitialVariables()
|
||||
{
|
||||
// Store initial time-step as a placeholder checkPoint of level oo
|
||||
checkPoints_[0].setPlaceHolder(false);
|
||||
checkPoints_[0].level() = pTraits<label>::max;
|
||||
activeCheckPoints_++;
|
||||
++iPtr_;
|
||||
}
|
||||
|
||||
|
||||
void Foam::binomialCheckPointing::retrieveVariables()
|
||||
{
|
||||
DebugInfo
|
||||
<< "Retrieving checkPoint for time " << time_.timeIndex() << endl;
|
||||
dimensionedScalar adjEndingTime = time_.endTime();
|
||||
label timeIndex = time_.timeIndex();
|
||||
|
||||
// Remove the checkpoint if it is at a greater time-step than the current
|
||||
// one, or if it is at the same time-step as the current one, but it is a
|
||||
// placeHolder checkPoint.
|
||||
const label lastPos = indirectAddressing_[activeCheckPoints_ - 1];
|
||||
if
|
||||
(
|
||||
(checkPoints_[lastPos].timeIndex() > timeIndex)
|
||||
|| (
|
||||
checkPoints_[lastPos].timeIndex() == timeIndex &&
|
||||
checkPoints_[lastPos].placeHolder()
|
||||
)
|
||||
)
|
||||
{
|
||||
const label pos = indirectAddressing_[activeCheckPoints_ - 1];
|
||||
DebugInfo
|
||||
<< "Removing checkPoint: ID, timeIndex, time = " << pos << " "
|
||||
<< checkPoints_[pos].timeIndex() << " "
|
||||
<< name(checkPoints_[pos].timeValue()) << endl;
|
||||
checkPoints_[pos].empty();
|
||||
activeCheckPoints_--;
|
||||
}
|
||||
Time& time = const_cast<Time&>(time_);
|
||||
if
|
||||
(
|
||||
checkPoints_[indirectAddressing_[activeCheckPoints_ - 1]].timeIndex()
|
||||
== timeIndex
|
||||
)
|
||||
{
|
||||
// Scenario 1:
|
||||
// there is a checkpoint at the current time-step. Retrieve the
|
||||
// solution and make it a placeholder checkpoint
|
||||
DebugInfo
|
||||
<< "Scenario 1" << endl;
|
||||
const label pos = indirectAddressing_[activeCheckPoints_ - 1];
|
||||
checkPoints_[pos].retrieve();
|
||||
variablesSet_.validateTurbulence();
|
||||
if (adjustTimeStep_)
|
||||
{
|
||||
time.setDeltaT(checkPoints_[pos].deltaT());
|
||||
}
|
||||
checkPoints_[pos].resetToPlaceHolder();
|
||||
activeCheckPoints_--;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Scenario 2:
|
||||
// there is no checkpoint at the current time-step. Retrieve the
|
||||
// solution at the last checkpoint
|
||||
DebugInfo
|
||||
<< "Scenario 2" << endl;
|
||||
const label pos = indirectAddressing_[activeCheckPoints_ - 1];
|
||||
|
||||
scalar nowTime(time.value());
|
||||
if (adjustTimeStep_)
|
||||
{
|
||||
time.setDeltaT(checkPoints_[pos].deltaT());
|
||||
}
|
||||
time.setTime
|
||||
(checkPoints_[pos].timeValue(), checkPoints_[pos].timeIndex());
|
||||
time.setEndTime(nowTime);
|
||||
|
||||
checkPoints_[pos].retrieve();
|
||||
variablesSet_.validateTurbulence();
|
||||
|
||||
while (primalSolver_.loop())
|
||||
{
|
||||
Info<< "Primal-CheckPointing::";
|
||||
primalSolver_.solveIter();
|
||||
recomputationSteps_++;
|
||||
}
|
||||
}
|
||||
time.setEndTime(adjEndingTime);
|
||||
--iPtr_;
|
||||
// Accumulate the adjoint step to counter
|
||||
totalSteps_++;
|
||||
}
|
||||
|
||||
|
||||
void Foam::binomialCheckPointing::postAdjointLoop()
|
||||
{
|
||||
// Output re-computation info
|
||||
scalar recomputationLoad =
|
||||
scalar((2.*recomputationSteps_))/
|
||||
scalar((totalSteps_-recomputationSteps_));
|
||||
Info<<"\n/* * * * * * * * * * * * * * * * * * * * * * * */" << nl
|
||||
<<"Total number of steps "<<totalSteps_ << nl
|
||||
<<"Recomputations "<<recomputationSteps_ << nl
|
||||
<<"Recomputation load "<<recomputationLoad << nl
|
||||
<<"/* * * * * * * * * * * * * * * * * * * * * * * */" << nl << endl;
|
||||
|
||||
// Rewind storage pointers with a Warning
|
||||
WarningInFunction
|
||||
<< "Rewinding storage pointers, "
|
||||
<< "even though check-points have been re-arranged." << nl
|
||||
<< "Use binomialCheckPointing with caution in the presence of multiple"
|
||||
<< " adjoint solvers"
|
||||
<< endl;
|
||||
primalStorage::postAdjointLoop();
|
||||
}
|
||||
|
||||
|
||||
void Foam::binomialCheckPointing::storageMetrics()
|
||||
{
|
||||
gatherMetrics();
|
||||
writeToFile();
|
||||
|
||||
const scalar initialSize = storageMetrics_[0];
|
||||
const scalar uncompressedRoughSize = storageMetrics_[1];
|
||||
const scalar uncompressedSize = storageMetrics_[2];
|
||||
const scalar compressedSize = storageMetrics_[3];
|
||||
|
||||
Info<< nl << "- - - - - - - - - - - - - - - - - - - - -" << endl;
|
||||
Info<< "Primal Storage Statistics" << endl;
|
||||
Info<< "- - - - - - - - - - - - - - - - - - - - -" << nl << endl;
|
||||
|
||||
unsigned int width = 6;//IOstream::defaultPrecision();
|
||||
Info<< setprecision(width);
|
||||
Info<< "nCheckPoints = "
|
||||
<< activeCheckPoints_ << nl
|
||||
<< "Compression Ratio CR_0 = "
|
||||
<< uncompressedRoughSize/compressedSize << nl
|
||||
<< "ZFP Compression ratio CR_ZFP = "
|
||||
<< uncompressedSize/compressedSize << nl
|
||||
<< "Initial Size = "
|
||||
<< initialSize*1.e-6 << " Mb" << nl
|
||||
<< "Initial Size Saved = "
|
||||
<< uncompressedRoughSize*1.e-6 << " Mb" << nl
|
||||
<< "Compressed Size = "
|
||||
<< compressedSize*1.e-6 << " Mb" << endl;
|
||||
Info<< setprecision(IOstream::defaultPrecision()) << endl;
|
||||
/*
|
||||
Info << "checkPoint time values -->Start<--" << endl;
|
||||
for (label fI=0; fI<nCheckPoints_; fI++)
|
||||
{
|
||||
const label& pos = indirectAddressing_[fI];
|
||||
Info << "Checkpoint-ID, timeIndex, level, time, placeholder = " << fI << " "
|
||||
<< checkPoints_[pos].timeIndex() << " " << checkPoints_[pos].level()
|
||||
<< " " << ::Foam::name(checkPoints_[pos].timeValue()) << " "
|
||||
<< checkPoints_[pos].placeHolder() << endl;
|
||||
}
|
||||
Info << "checkPoint time values --> End <--" << endl;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,224 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::binomialCheckPointing
|
||||
|
||||
Description
|
||||
Class implementing the binomial check-pointing technique for the unsteady
|
||||
adjoint optimisation
|
||||
|
||||
SourceFiles
|
||||
binomialCheckPointing.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef binomialCheckPointing_H
|
||||
#define binomialCheckPointing_H
|
||||
|
||||
#include "primalStorage.H"
|
||||
#include "storageParameters.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
#include "OFstream.H"
|
||||
#include "checkPoint.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class binomialCheckPointing Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class binomialCheckPointing
|
||||
:
|
||||
public primalStorage
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Counter of the total number of time-steps performed to
|
||||
//- complete the optimization cycle
|
||||
// primal + adjoint + primal recomputations due to checkPointing
|
||||
label totalSteps_;
|
||||
|
||||
//- Counter of the number of recomputation time-steps
|
||||
//- performed to complete the optimization cycle
|
||||
label recomputationSteps_;
|
||||
|
||||
//- Storage parameters
|
||||
autoPtr<storageParameters> storageParams_;
|
||||
|
||||
//- Reseting deltaT causes slight disrepancies in comparison to the
|
||||
//- solution of shortFullStorage.
|
||||
// Reseting applied only with non-constant time-step. Entry taken from
|
||||
// storageParameters to avoid the possibility of the user changing
|
||||
// runTime the adjustTimeStep of controlDict
|
||||
const Switch& adjustTimeStep_;
|
||||
|
||||
//- Number of chechPoints to be stored
|
||||
label nCheckPoints_;
|
||||
|
||||
//- Accumulated storage metrics
|
||||
scalarList storageMetrics_;
|
||||
|
||||
//- All stored checkPoints
|
||||
PtrList<checkPoint> checkPoints_;
|
||||
|
||||
//- Position of each checkPoint, as stored in chronological order,
|
||||
//- in the checkPoints list
|
||||
List<label> indirectAddressing_;
|
||||
|
||||
dimensionedScalar startingTime_;
|
||||
|
||||
label activeCheckPoints_;
|
||||
|
||||
label& iPtr_;
|
||||
|
||||
mutable autoPtr<OFstream> metricsFilePtr_;
|
||||
|
||||
mutable autoPtr<OFstream> checkPointsFilePtr_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Gather metrics from all processors if timing == true.
|
||||
// If timing == false, the reduce operation has already been deployed.
|
||||
void gatherMetrics();
|
||||
|
||||
//- Set file to write metrics - one line for each optimisation cycle
|
||||
void setMetricsFilesPtr();
|
||||
|
||||
//- Set file to write checkPoints
|
||||
void setCheckPointsFilesPtr();
|
||||
|
||||
inline void writeToFile();
|
||||
|
||||
//- Calculates the compression metrics of the whole primal solution
|
||||
virtual void calcStorageMetrics();
|
||||
|
||||
//- Start process for each host
|
||||
labelList hostStartProcess(wordList& hostNames) const;
|
||||
|
||||
//- Get checkpoint size. The size of the first checkpoint size is not
|
||||
//- dependable, since it may include only the fields of the current
|
||||
//- time-step and not the oldTimes. Instead, we solve for one
|
||||
//- time-step and use its size as a reference
|
||||
scalar checkPointSize();
|
||||
|
||||
//- Print checkpoint size and estimate number of checkpoints that
|
||||
//- can be allocated based on the available memory at run time
|
||||
unsigned long long maxNumberOfCheckPoints();
|
||||
|
||||
void initialize();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
binomialCheckPointing(const binomialCheckPointing&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const binomialCheckPointing&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
TypeName("binomialCheckPointing");
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
binomialCheckPointing,
|
||||
dictionary,
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
),
|
||||
(primalSolverObj, storageDict)
|
||||
);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
binomialCheckPointing
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
);
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Allocate new binomialCheckPointing
|
||||
static autoPtr<binomialCheckPointing> New
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~binomialCheckPointing() = default;
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
//- Release all checkpoints
|
||||
virtual void scratch() override;
|
||||
|
||||
//- Store current variable set as a checkpoint if needed
|
||||
virtual void storeVariables() override;
|
||||
|
||||
virtual void storeInitialVariables() override;
|
||||
|
||||
virtual void retrieveVariables() override;
|
||||
|
||||
//- Operations performed after the end of the adjoint loop
|
||||
virtual void postAdjointLoop() override;
|
||||
|
||||
//- Function to write the storage metrics of the whole primal solution
|
||||
virtual void storageMetrics() override;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,150 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "compressedFullStorage.H"
|
||||
#include "compressedIncompressibleVars.H"
|
||||
#include "memInfo.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "IOmanip.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(compressedFullStorage, 0);
|
||||
defineRunTimeSelectionTable(compressedFullStorage, dictionary);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
primalStorage,
|
||||
compressedFullStorage,
|
||||
primalStorage
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::compressedFullStorage::compressedFullStorage
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
)
|
||||
:
|
||||
primalStorage(primalSolverObj, storageDict),
|
||||
allPrimalVars_(0),
|
||||
storageMetrics_(),
|
||||
totalSteps_(0),
|
||||
recomputationSteps_(0),
|
||||
metricsFilePtr_()
|
||||
{
|
||||
makeFolder();
|
||||
storageParams_.reset
|
||||
(
|
||||
storageParameters::New
|
||||
(
|
||||
mesh_,
|
||||
storageDict_,
|
||||
variablesSet_.allocatedFieldNames()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::compressedFullStorage> Foam::compressedFullStorage::New
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
)
|
||||
{
|
||||
const dictionary& dict = storageDict.subDict("storageParameters");
|
||||
const word type(dict.get<word>("algorithm") + "FullStorage");
|
||||
Info<< "CompressedFullStorage type" << tab << type << endl;
|
||||
|
||||
auto* ctorPtr = dictionaryConstructorTable(type);
|
||||
|
||||
if (!ctorPtr)
|
||||
{
|
||||
FatalIOErrorInLookup
|
||||
(
|
||||
storageDict,
|
||||
"compressedFullStorage",
|
||||
type,
|
||||
*dictionaryConstructorTablePtr_
|
||||
) << exit(FatalIOError);
|
||||
}
|
||||
|
||||
return autoPtr<compressedFullStorage>
|
||||
(ctorPtr(primalSolverObj, storageDict));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::compressedFullStorage::scratch()
|
||||
{
|
||||
NotImplemented
|
||||
}
|
||||
|
||||
|
||||
void Foam::compressedFullStorage::storeVariables()
|
||||
{
|
||||
NotImplemented
|
||||
}
|
||||
|
||||
|
||||
void Foam::compressedFullStorage::retrieveVariables()
|
||||
{
|
||||
NotImplemented
|
||||
}
|
||||
|
||||
|
||||
void Foam::compressedFullStorage::postAdjointLoop()
|
||||
{
|
||||
scalar recomputationLoad =
|
||||
scalar((2.*recomputationSteps_))/
|
||||
scalar((totalSteps_-recomputationSteps_));
|
||||
Info<<"\n/* * * * * * * * * * * * * * * * * * * * * * * */\n"
|
||||
<<"Total number of steps "<<totalSteps_ << nl
|
||||
<<"Recomputations "<<recomputationSteps_ << nl
|
||||
<<"Recomputation load "<<recomputationLoad << nl
|
||||
<<"/* * * * * * * * * * * * * * * * * * * * * * * */\n" << endl;
|
||||
|
||||
// Rewind storage ptrs
|
||||
primalStorage::postAdjointLoop();
|
||||
}
|
||||
|
||||
|
||||
void Foam::compressedFullStorage::storageMetrics()
|
||||
{
|
||||
NotImplemented
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,165 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::compressedFullStorage
|
||||
|
||||
Description
|
||||
Compresses and stores all instances of the primal flow fields
|
||||
|
||||
SourceFiles
|
||||
compressedFullStorage.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef compressedFullStorage_H
|
||||
#define compressedFullStorage_H
|
||||
|
||||
#include "primalStorage.H"
|
||||
#include "compressedIncompressibleVars.H"
|
||||
#include "storageParameters.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
#include "OFstream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class compressedFullStorage Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class compressedFullStorage
|
||||
:
|
||||
public primalStorage
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
PtrList<compressedIncompressibleVars> allPrimalVars_;
|
||||
|
||||
scalarList storageMetrics_;
|
||||
|
||||
//- Counter of the total number of time-steps performed to
|
||||
//- complete the optimization cycle.
|
||||
// Equal to primal + adjoint + primal recomputations
|
||||
// in case of checkPointing strategies
|
||||
label totalSteps_;
|
||||
|
||||
//- Counter of the number of recomputation time-steps
|
||||
//- performed to complete the optimization cycle
|
||||
label recomputationSteps_;
|
||||
|
||||
//- Storage parameters
|
||||
autoPtr<storageParameters> storageParams_;
|
||||
|
||||
mutable autoPtr<OFstream> metricsFilePtr_;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
compressedFullStorage(const compressedFullStorage&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const compressedFullStorage&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
TypeName("compressedFullStorage");
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
compressedFullStorage,
|
||||
dictionary,
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
),
|
||||
(primalSolverObj, storageDict)
|
||||
);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
compressedFullStorage
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
);
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Return a reference to the selected turbulence model
|
||||
static autoPtr<compressedFullStorage> New
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~compressedFullStorage() = default;
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
//- Free memory used to store the primal time-series
|
||||
virtual void scratch() override;
|
||||
|
||||
//- Store current copy of the variablesSet (could be lossy)
|
||||
virtual void storeVariables() override;
|
||||
|
||||
//- Retrieve primal-based quantities into the active variablesSet
|
||||
virtual void retrieveVariables() override;
|
||||
|
||||
//- Operations performed after the end of the adjoint loop
|
||||
virtual void postAdjointLoop() override;
|
||||
|
||||
//- Function to write the storage metrics of the whole primal solution
|
||||
virtual void storageMetrics() override;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,236 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "primalSolver.H"
|
||||
#include "shortFullStorage.H"
|
||||
#include "memInfo.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "IOmanip.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(shortFullStorage, 0);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
compressedFullStorage,
|
||||
shortFullStorage,
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::shortFullStorage::gatherMetrics()
|
||||
{
|
||||
if (storageParams_().timing())
|
||||
{
|
||||
for (scalar& storageMetric : storageMetrics_)
|
||||
{
|
||||
reduce(storageMetric, sumOp<scalar>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::shortFullStorage::setMetricsFilesPtr()
|
||||
{
|
||||
fileName filePath =
|
||||
storageFolder_/"AllOptCycles" + primalSolver_.solverName();
|
||||
if (!isFile(filePath))
|
||||
{
|
||||
DebugInfo
|
||||
<< "Creating file: " << filePath << endl;
|
||||
metricsFilePtr_.reset(new OFstream(filePath));
|
||||
if (!metricsFilePtr_()())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Stream has failed." << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
if (!isFile(filePath))
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Error while creating file: " << filePath << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
unsigned int width = IOstream::defaultPrecision() + 6;
|
||||
metricsFilePtr_()
|
||||
<< setw(width) << "Initial Size (Mb)" << tab
|
||||
<< setw(width) << "Initial Size Saved (Mb)" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
metricsFilePtr_.reset
|
||||
(
|
||||
new OFstream
|
||||
(
|
||||
filePath,
|
||||
IOstream::ASCII,
|
||||
IOstream::currentVersion,
|
||||
IOstream::UNCOMPRESSED,
|
||||
true
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::shortFullStorage::writeToFile()
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
if (!metricsFilePtr_)
|
||||
{
|
||||
setMetricsFilesPtr();
|
||||
}
|
||||
const scalar initialSize = storageMetrics_[0];
|
||||
const scalar uncompressedRoughSize = storageMetrics_[1];
|
||||
unsigned int width = IOstream::defaultPrecision() + 6;
|
||||
metricsFilePtr_()
|
||||
<< setprecision(IOstream::defaultPrecision());
|
||||
metricsFilePtr_() << setw(width) << initialSize*1.e-6 << tab
|
||||
<< setw(width) << uncompressedRoughSize*1.e-6 << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::shortFullStorage::calcStorageMetrics()
|
||||
{
|
||||
const scalarList& metrics = allPrimalVars_[iPtr_].storageMetrics();
|
||||
if (allPrimalVars_.size() == 1)
|
||||
{
|
||||
storageMetrics_ = metrics;
|
||||
}
|
||||
else
|
||||
{
|
||||
storageMetrics_ = storageMetrics_ + metrics;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::shortFullStorage::shortFullStorage
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
)
|
||||
:
|
||||
compressedFullStorage(primalSolverObj, storageDict),
|
||||
iPtr_(storagePtrs_[0])
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::shortFullStorage::scratch()
|
||||
{
|
||||
totalSteps_ = 0;
|
||||
iPtr_ = -1;
|
||||
allPrimalVars_.clear();
|
||||
storageMetrics_.clear();
|
||||
}
|
||||
|
||||
|
||||
void Foam::shortFullStorage::storeVariables()
|
||||
{
|
||||
if (allPrimalVars_.size() > iPtr_ + 1)
|
||||
{
|
||||
Info<< endl;
|
||||
WarningInFunction
|
||||
<< tab
|
||||
<< "allPrimalVars.size(), iPtr = "
|
||||
<< allPrimalVars_.size() << " " << iPtr_
|
||||
<< nl << tab
|
||||
<< "Normally, allPrimalVars.size() = iPtr + 1 in each time step"
|
||||
<< nl << tab
|
||||
<< "Possible cause: Multiple compressions/decompressions "
|
||||
<< "of the same time step"
|
||||
<< nl << tab
|
||||
<< "allPrimalVars.size() manually set to "
|
||||
<< iPtr_ + 1 << nl << endl;
|
||||
allPrimalVars_.resize(iPtr_ + 1);
|
||||
}
|
||||
incompressibleVars& incoVars = refCast<incompressibleVars>(variablesSet_);
|
||||
autoPtr<compressedIncompressibleVars> varsPtr
|
||||
(
|
||||
compressedIncompressibleVars::New
|
||||
(
|
||||
incoVars,
|
||||
storageParams_()
|
||||
)
|
||||
);
|
||||
varsPtr->compress();
|
||||
varsPtr->calculateStorageMetrics();
|
||||
allPrimalVars_.append(varsPtr);
|
||||
++iPtr_;
|
||||
calcStorageMetrics();
|
||||
// Accumulate the primal step to counter
|
||||
totalSteps_++;
|
||||
}
|
||||
|
||||
|
||||
void Foam::shortFullStorage::retrieveVariables()
|
||||
{
|
||||
if (allPrimalVars_.empty())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "allPrimalVars_ list is empty." << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
allPrimalVars_[iPtr_].decompress();
|
||||
variablesSet_.validateTurbulence();
|
||||
--iPtr_;
|
||||
// Accumulate the adjoint step to counter
|
||||
totalSteps_++;
|
||||
}
|
||||
|
||||
|
||||
void Foam::shortFullStorage::storageMetrics()
|
||||
{
|
||||
gatherMetrics();
|
||||
writeToFile();
|
||||
|
||||
const scalar initialSize = storageMetrics_[0];
|
||||
const scalar uncompressedRoughSize = storageMetrics_[1];
|
||||
|
||||
Info<< nl << "- - - - - - - - - - - - - - - - - - - - -" << endl;
|
||||
Info<< "Primal Storage Statistics" << endl;
|
||||
Info<< "- - - - - - - - - - - - - - - - - - - - -" << nl << endl;
|
||||
|
||||
Info<< setprecision(6);
|
||||
Info<< "Initial Size = " << initialSize*1.e-6 << " Mb" << endl;
|
||||
Info<< "Stored Size = " << uncompressedRoughSize*1.e-6 << " Mb" << endl;
|
||||
Info<< setprecision(IOstream::defaultPrecision()) << endl;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,135 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::shortFullStorage
|
||||
|
||||
Description
|
||||
Stores all instances of the primal flow fields.
|
||||
In constrast to full storage, parts of the fields that can be recomputed
|
||||
(fixedValue boundary conditions, processor values etc) are not stored,
|
||||
reducing slightly the memory footprint
|
||||
|
||||
SourceFiles
|
||||
shortFullStorage.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef shortFullStorage_H
|
||||
#define shortFullStorage_H
|
||||
|
||||
#include "compressedFullStorage.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class shortFullStorage Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class shortFullStorage
|
||||
:
|
||||
public compressedFullStorage
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
label& iPtr_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Gather metrics from all processors if timing == true.
|
||||
// If timing == false, the reduce operation has already been deployed.
|
||||
void gatherMetrics();
|
||||
|
||||
//- Set file to write metrics - one line per optimisation cycle
|
||||
void setMetricsFilesPtr();
|
||||
|
||||
inline void writeToFile();
|
||||
|
||||
//- Function to calculate the compression metrics of the whole primal
|
||||
//- solution
|
||||
void calcStorageMetrics();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
shortFullStorage(const shortFullStorage&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const shortFullStorage&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
TypeName("shortFullStorage");
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
shortFullStorage
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~shortFullStorage() = default;
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
//- Free memory used to store the primal time-series
|
||||
virtual void scratch() override;
|
||||
|
||||
//- Store current copy of the variablesSet (could be lossy)
|
||||
virtual void storeVariables() override;
|
||||
|
||||
//- Retrieve primal-based quantities into the active variablesSet
|
||||
virtual void retrieveVariables() override;
|
||||
|
||||
//- Function to write the storage metrics of the whole primal solution
|
||||
void storageMetrics() override;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,235 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "fullStorage.H"
|
||||
#include "memInfo.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "IOmanip.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(fullStorage, 0);
|
||||
defineRunTimeSelectionTable(fullStorage, dictionary);
|
||||
addToRunTimeSelectionTable(primalStorage, fullStorage, primalStorage);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::labelList Foam::fullStorage::hostStartProcess(wordList& hostNames) const
|
||||
{
|
||||
// Gather host names for all processors
|
||||
wordList machineName(Pstream::nProcs());
|
||||
machineName[Pstream::myProcNo()] = hostName();
|
||||
Pstream::gatherList(machineName);
|
||||
Pstream::scatterList(machineName);
|
||||
hostNames = machineName;
|
||||
|
||||
// Start process ID for each host; to be resized
|
||||
const label nProcs(Pstream::nProcs());
|
||||
labelList hostStartProcess(nProcs + 1, 0);
|
||||
|
||||
label iHost(0);
|
||||
word prev(word::null);
|
||||
for (label procI = 0; procI < nProcs; ++procI)
|
||||
{
|
||||
if (machineName[procI] != prev)
|
||||
{
|
||||
hostStartProcess[iHost] = procI;
|
||||
prev = machineName[procI];
|
||||
++iHost;
|
||||
}
|
||||
}
|
||||
// Allocate an additional entry for easy looping over start
|
||||
// of this host and the next one
|
||||
hostStartProcess.setSize(iHost + 1);
|
||||
hostStartProcess[iHost] = nProcs;
|
||||
return hostStartProcess;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::fullStorage::maxNumberOfInstances() const
|
||||
{
|
||||
// Find instance size per processor
|
||||
labelList sizeBef(Pstream::nProcs());
|
||||
sizeBef[Pstream::myProcNo()] = memInfo().size();
|
||||
Pstream::gatherList(sizeBef);
|
||||
Pstream::scatterList(sizeBef);
|
||||
|
||||
autoPtr<variablesSet> temp(variablesSet_.clone());
|
||||
|
||||
labelList sizeAft(Pstream::nProcs());
|
||||
sizeAft[Pstream::myProcNo()] = memInfo().size();
|
||||
Pstream::gatherList(sizeAft);
|
||||
Pstream::scatterList(sizeAft);
|
||||
|
||||
// Available memory. Is stored on a per-processor base but actually
|
||||
// refers to the host. Use with caution
|
||||
labelList free(Pstream::nProcs());
|
||||
free[Pstream::myProcNo()] = memInfo().free();
|
||||
Pstream::gatherList(free);
|
||||
Pstream::scatterList(free);
|
||||
|
||||
// Host name, per processor basis
|
||||
wordList hostNames(0);
|
||||
// Start process ID per host
|
||||
labelList hostStartProcessID(hostStartProcess(hostNames));
|
||||
label nHosts(hostStartProcessID.size() - 1);
|
||||
|
||||
// Determine the number of instances that can be allocated as the
|
||||
// minimum from all hosts
|
||||
labelList hostInstanceSize(nHosts, 0);
|
||||
label nInstances(pTraits<label>::max);
|
||||
label limitingHostID(-1);
|
||||
for (label iHost = 0; iHost < nHosts; ++iHost)
|
||||
{
|
||||
const label start(hostStartProcessID[iHost]);
|
||||
const label end(hostStartProcessID[iHost + 1]);
|
||||
label& hostSize = hostInstanceSize[iHost];
|
||||
for (label procI = start; procI < end; ++procI)
|
||||
{
|
||||
hostSize += sizeAft[procI] - sizeBef[procI];
|
||||
}
|
||||
label nHostCheckPoints(free[start]/hostSize);
|
||||
if (nHostCheckPoints < nInstances)
|
||||
{
|
||||
nInstances = nHostCheckPoints;
|
||||
limitingHostID = iHost;
|
||||
}
|
||||
}
|
||||
|
||||
// Print global instance size
|
||||
const label checkPointSize(sum(sizeAft) - sum(sizeBef));
|
||||
Info<< nl << "Global size of an instance is "
|
||||
<< checkPointSize << " KBs" << endl;
|
||||
|
||||
// Print max number of check points that fit in the most limiting host
|
||||
Info<< "Approximately " << nInstances
|
||||
<< " instances can be stored, "
|
||||
<< "without accounting for cached memory " << endl;
|
||||
|
||||
// Print information on a per host basis
|
||||
if (debug > 1)
|
||||
{
|
||||
Info<< nl
|
||||
<< setw(23) << "Host" << " | "
|
||||
<< setw(23) << "Instance size (kBs)" << " | "
|
||||
<< setw(23) << "Available memory (kBs)" << " | "
|
||||
<< setw(23) << "Max checkpoints (local)"
|
||||
<< nl;
|
||||
for (label iHost = 0; iHost < nHosts; ++iHost)
|
||||
{
|
||||
const label start(hostStartProcessID[iHost]);
|
||||
Info<< setw(23) << hostNames[start] << " "
|
||||
<< setw(23) << hostInstanceSize[iHost] << " "
|
||||
<< setw(23) << free[start] << " "
|
||||
<< setw(23) << free[start]/hostInstanceSize[iHost]
|
||||
<< endl;
|
||||
}
|
||||
Info<< endl;
|
||||
}
|
||||
|
||||
string limitingHost;
|
||||
if (Pstream::myProcNo() == hostStartProcessID[limitingHostID])
|
||||
{
|
||||
limitingHost = hostName();
|
||||
}
|
||||
reduce(limitingHost, sumOp<word>());
|
||||
Info<< "Limiting factor is host " << limitingHost << nl << endl;
|
||||
|
||||
return nInstances;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fullStorage::fullStorage
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
)
|
||||
:
|
||||
primalStorage(primalSolverObj, storageDict),
|
||||
allPrimalVars_(0),
|
||||
iPtr_(storagePtrs_[0])
|
||||
{
|
||||
/*if (debug)
|
||||
{
|
||||
maxNumberOfCheckPoints();
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::fullStorage> Foam::fullStorage::New
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
)
|
||||
{
|
||||
return autoPtr<fullStorage>
|
||||
(
|
||||
new fullStorage(primalSolverObj, storageDict)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::fullStorage::scratch()
|
||||
{
|
||||
allPrimalVars_.clear();
|
||||
iPtr_ = -1;
|
||||
}
|
||||
|
||||
|
||||
void Foam::fullStorage::storeVariables()
|
||||
{
|
||||
allPrimalVars_.append(variablesSet_.clone());
|
||||
++iPtr_;
|
||||
}
|
||||
|
||||
|
||||
void Foam::fullStorage::retrieveVariables()
|
||||
{
|
||||
if (allPrimalVars_.empty())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "allPrimalVars list is empty." << endl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
variablesSet_.transfer(allPrimalVars_[iPtr_]);
|
||||
//allPrimalVars_.release(iPtr_);
|
||||
--iPtr_;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,150 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::fullStorage
|
||||
|
||||
Description
|
||||
Stores all instances of the primal flow fields.
|
||||
Can lead to huge memory requirements if used with large meshes and many
|
||||
time-steps
|
||||
|
||||
SourceFiles
|
||||
fullStorage.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef fullStorage_H
|
||||
#define fullStorage_H
|
||||
|
||||
#include "primalStorage.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class fullStorage Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class fullStorage
|
||||
:
|
||||
public primalStorage
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
PtrList<variablesSet> allPrimalVars_;
|
||||
|
||||
label& iPtr_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Start process for each host
|
||||
labelList hostStartProcess(wordList& hostNames) const;
|
||||
|
||||
//- Print time instance size and estimate number of instances that
|
||||
//- can be allocated based on the available memory at run time
|
||||
label maxNumberOfInstances() const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
fullStorage(const fullStorage&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const fullStorage&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
TypeName("fullStorage");
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
fullStorage,
|
||||
dictionary,
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
),
|
||||
(primalSolverObj, storageDict)
|
||||
);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
fullStorage
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
);
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Return a reference to the selected turbulence model
|
||||
static autoPtr<fullStorage> New
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~fullStorage() = default;
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
virtual void scratch() override;
|
||||
|
||||
virtual void storeVariables() override;
|
||||
|
||||
virtual void retrieveVariables() override;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,89 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "noneStorage.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(noneStorage, 0);
|
||||
defineRunTimeSelectionTable(noneStorage, dictionary);
|
||||
addToRunTimeSelectionTable(primalStorage, noneStorage, primalStorage);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::noneStorage::noneStorage
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
)
|
||||
:
|
||||
primalStorage(primalSolverObj, storageDict)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::noneStorage> Foam::noneStorage::New
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
)
|
||||
{
|
||||
return autoPtr<noneStorage>
|
||||
(
|
||||
new noneStorage(primalSolverObj, storageDict)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::noneStorage::scratch()
|
||||
{
|
||||
// Does nothing
|
||||
}
|
||||
|
||||
|
||||
void Foam::noneStorage::storeVariables()
|
||||
{
|
||||
// Does nothing
|
||||
}
|
||||
|
||||
|
||||
void Foam::noneStorage::retrieveVariables()
|
||||
{
|
||||
// Does nothing
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,130 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::noneStorage
|
||||
|
||||
Description
|
||||
A primalStorage instance doing nothing. Used, for instance, with steady
|
||||
state simulations
|
||||
|
||||
SourceFiles
|
||||
noneStorage.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef noneStorage_H
|
||||
#define noneStorage_H
|
||||
|
||||
#include "primalStorage.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class noneStorage Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class noneStorage
|
||||
:
|
||||
public primalStorage
|
||||
{
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
noneStorage(const noneStorage&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const noneStorage&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
TypeName("none");
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
noneStorage,
|
||||
dictionary,
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
),
|
||||
(primalSolverObj, storageDict)
|
||||
);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
noneStorage
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
);
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Return a reference to the selected turbulence model
|
||||
static autoPtr<noneStorage> New
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~noneStorage() = default;
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
virtual void scratch() override;
|
||||
|
||||
virtual void storeVariables() override;
|
||||
|
||||
virtual void retrieveVariables() override;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,170 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "error.H"
|
||||
#include "primalStorage.H"
|
||||
#include "primalSolver.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(primalStorage, 0);
|
||||
defineRunTimeSelectionTable(primalStorage, primalStorage);
|
||||
|
||||
label primalStorage::counter = 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::primalStorage::makeFolder()
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
storageFolder_ = time_.globalPath()/"optimisation"/"storage";
|
||||
//- do not remove directory to allow for continuation
|
||||
//if (isDir(storageFolder_)) rmDir(storageFolder_);
|
||||
mkDir(storageFolder_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::primalStorage::primalStorage
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
)
|
||||
:
|
||||
time_(primalSolverObj.mesh().time()),
|
||||
mesh_(primalSolverObj.mesh()),
|
||||
primalSolver_(primalSolverObj),
|
||||
storageDict_(storageDict),
|
||||
variablesSet_(primalSolver_.getVariablesSet()),
|
||||
storagePtrs_(1, -1),
|
||||
storagePtrsCopy_(nullptr)
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::primalStorage> Foam::primalStorage::New
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
)
|
||||
{
|
||||
const word type(storageDict.get<word>("type"));
|
||||
Info<< "Storage type for the primal fields: " << type << endl;
|
||||
|
||||
auto* ctorPtr = primalStorageConstructorTable(type);
|
||||
|
||||
if (!ctorPtr)
|
||||
{
|
||||
FatalIOErrorInLookup
|
||||
(
|
||||
storageDict,
|
||||
"primalStorage",
|
||||
type,
|
||||
*primalStorageConstructorTablePtr_
|
||||
) << exit(FatalIOError);
|
||||
}
|
||||
|
||||
return autoPtr<primalStorage>(ctorPtr(primalSolverObj, storageDict));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
const Foam::labelList& Foam::primalStorage::storagePtrs() const
|
||||
{
|
||||
return storagePtrs_;
|
||||
}
|
||||
|
||||
|
||||
void Foam::primalStorage::copyStoragePtrs()
|
||||
{
|
||||
storagePtrsCopy_.reset(new labelList(storagePtrs_));
|
||||
}
|
||||
|
||||
|
||||
void Foam::primalStorage::rewindStoragePtrs()
|
||||
{
|
||||
if (storagePtrsCopy_)
|
||||
{
|
||||
storagePtrs_ = storagePtrsCopy_();
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted to retrieve unset storePtrs" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::primalStorage::storeInitialVariables()
|
||||
{
|
||||
// Does nothing in base
|
||||
}
|
||||
|
||||
|
||||
void Foam::primalStorage::preLoopRetrieveVariables()
|
||||
{
|
||||
// Does nothing in base
|
||||
}
|
||||
|
||||
|
||||
void Foam::primalStorage::preAdjointLoop()
|
||||
{
|
||||
// Copy pointers to storage instances to a backup variable
|
||||
copyStoragePtrs();
|
||||
// Retrive certain variables before the adjoint loop
|
||||
// (e.g. from files, for restarted cases)
|
||||
preLoopRetrieveVariables();
|
||||
}
|
||||
|
||||
|
||||
void Foam::primalStorage::postAdjointLoop()
|
||||
{
|
||||
rewindStoragePtrs();
|
||||
}
|
||||
|
||||
|
||||
void Foam::primalStorage::storageMetrics()
|
||||
{
|
||||
// Does nothing in base
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,203 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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::primalStorage
|
||||
|
||||
Description
|
||||
Abstract base class managing the storage of primal flow fields, to be later
|
||||
used for the solution of unsteady flow equations
|
||||
|
||||
SourceFiles
|
||||
primalStorage.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef primalStorage_H
|
||||
#define primalStorage_H
|
||||
|
||||
#include "Time.H"
|
||||
#include "fvMesh.H"
|
||||
#include "dictionary.H"
|
||||
#include "variablesSet.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaratrions
|
||||
class primalSolver;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class primalStorage Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class primalStorage
|
||||
{
|
||||
static label counter;
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Const reference to time
|
||||
const Time& time_;
|
||||
|
||||
//- Const reference to mesh
|
||||
const fvMesh& mesh_;
|
||||
|
||||
//- Reference to the primal solver used to create the time-series
|
||||
//- being stored
|
||||
primalSolver& primalSolver_;
|
||||
|
||||
//- Input dict
|
||||
dictionary storageDict_;
|
||||
|
||||
//- Variables set of the primal solver
|
||||
variablesSet& variablesSet_;
|
||||
|
||||
//- List of useful pointers in the flow time-series
|
||||
// For instance, time-steps holding checkpoints, etc
|
||||
labelList storagePtrs_;
|
||||
|
||||
//- Copy of the pointer's list
|
||||
// Usefull for reseting in many of many primal solvers
|
||||
autoPtr<labelList> storagePtrsCopy_;
|
||||
|
||||
//- Output folder
|
||||
fileName storageFolder_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Set Folder
|
||||
virtual void makeFolder();
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
primalStorage(const primalStorage&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const primalStorage&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
TypeName("primalStorage");
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
|
||||
declareRunTimeNewSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
primalStorage,
|
||||
primalStorage,
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
),
|
||||
(primalSolverObj, storageDict)
|
||||
);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
primalStorage
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
);
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Return a reference to the selected turbulence model
|
||||
static autoPtr<primalStorage> New
|
||||
(
|
||||
primalSolver& primalSolverObj,
|
||||
const dictionary storageDict
|
||||
);
|
||||
|
||||
|
||||
// Destructor
|
||||
|
||||
//- Virtual destructor
|
||||
virtual ~primalStorage() = default;
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
//- Get list with pointers to storage instances
|
||||
virtual const labelList& storagePtrs() const;
|
||||
|
||||
//- Copy pointers to storage instances to a backup variable
|
||||
virtual void copyStoragePtrs();
|
||||
|
||||
//- Rewind pointers to storage instance to the values set after the
|
||||
//- solution of the primal equations
|
||||
virtual void rewindStoragePtrs();
|
||||
|
||||
//- Free memory used to store the primal time-series
|
||||
virtual void scratch() = 0;
|
||||
|
||||
//- Store current copy of the variablesSet (could be lossy)
|
||||
virtual void storeVariables() = 0;
|
||||
|
||||
virtual void storeInitialVariables();
|
||||
|
||||
//- Retrieve primal-based quantities into the active variablesSet
|
||||
virtual void retrieveVariables() = 0;
|
||||
|
||||
//- Retrive certain variables before the adjoint loop
|
||||
// (e.g. from files, for restarted cases)
|
||||
virtual void preLoopRetrieveVariables();
|
||||
|
||||
//- Operations performed before the beginning of the adjoint loop
|
||||
virtual void preAdjointLoop();
|
||||
|
||||
//- Operations performed after the end of the adjoint loop
|
||||
virtual void postAdjointLoop();
|
||||
|
||||
virtual void storageMetrics();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,68 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "shortParameters.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(shortParameters, 0);
|
||||
addToRunTimeSelectionTable(storageParameters, shortParameters, dictionary);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::shortParameters::initialize()
|
||||
{
|
||||
compressionMethod_.setSize(allocatedFieldNames_.size());
|
||||
forAll(allocatedFieldNames_, iPtr)
|
||||
{
|
||||
compressionMethod_[iPtr] = algorithm_ + "GeometricField";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::shortParameters::shortParameters
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& storageDict,
|
||||
const wordList& allocatedFieldNames
|
||||
)
|
||||
:
|
||||
storageParameters(mesh, storageDict, allocatedFieldNames)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,101 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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
|
||||
shortParameters
|
||||
|
||||
Description
|
||||
Reads from dictionary and stores all parameters related to the storage
|
||||
of the primal fields
|
||||
|
||||
SourceFiles
|
||||
shortParameters.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef shortParameters_H
|
||||
#define shortParameters_H
|
||||
|
||||
#include "storageParameters.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class shortParameters Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class shortParameters
|
||||
:
|
||||
public storageParameters
|
||||
{
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
shortParameters(const shortParameters&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const shortParameters&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
TypeName("shortParameters");
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
shortParameters
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& storageDict,
|
||||
const wordList& allocatedFieldNames
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~shortParameters() = default;
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
virtual void initialize() override;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,213 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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 "Ostream.H"
|
||||
#include "storageParameters.H"
|
||||
#include "wallFvPatch.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
defineTypeNameAndDebug(storageParameters, 0);
|
||||
defineRunTimeSelectionTable(storageParameters, dictionary);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
label storageParameters::counter = 0;
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void storageParameters::findCellsNextToWall()
|
||||
{
|
||||
// Find the boundary patches that are of type wall
|
||||
const fvPatchList& patches = mesh_.boundary();
|
||||
DynamicList<label> patchList;
|
||||
label size(0);
|
||||
forAll(patches, patchI)
|
||||
{
|
||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
||||
if (isA<wallFvPatch>(patch))
|
||||
{
|
||||
patchList.append(patchI);
|
||||
size += patch.faceCells().size();
|
||||
}
|
||||
}
|
||||
// Build list containing the IDs of the first cell centers next to wall
|
||||
// boundaries
|
||||
wallList_.setSize(size, -1);
|
||||
label pos(0);
|
||||
forAll(patchList, patchI)
|
||||
{
|
||||
const fvPatch& patch = mesh_.boundary()[patchList[patchI]];
|
||||
forAll(patch, faceI)
|
||||
{
|
||||
wallList_[pos++] = patch.faceCells()[faceI];
|
||||
}
|
||||
}
|
||||
Info<< "Found " << patchList.size() << " wall boundary(ies) "
|
||||
<< "with total " << returnReduce(wallList_.size(), sumOp<label>())
|
||||
<< " cells next to them." << endl;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
||||
|
||||
autoPtr<storageParameters> storageParameters::New
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& storageDict,
|
||||
const wordList& allocatedFieldNames
|
||||
)
|
||||
{
|
||||
const dictionary& dict = storageDict.subDict("storageParameters");
|
||||
const word type(dict.get<word>("algorithm") + "Parameters" );
|
||||
Info<< "Compression parameters type" << tab << type << endl;
|
||||
|
||||
auto* ctorPtr = dictionaryConstructorTable(type);
|
||||
|
||||
if (!ctorPtr)
|
||||
{
|
||||
FatalIOErrorInLookup
|
||||
(
|
||||
storageDict,
|
||||
"storageParameters",
|
||||
type,
|
||||
*dictionaryConstructorTablePtr_
|
||||
) << exit(FatalIOError);
|
||||
}
|
||||
|
||||
return autoPtr<storageParameters>
|
||||
(ctorPtr(mesh, storageDict, allocatedFieldNames));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
storageParameters::storageParameters
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& storageDict,
|
||||
const wordList& allocatedFieldNames
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
dict_(storageDict.subDict("storageParameters")),
|
||||
allocatedFieldNames_(allocatedFieldNames),
|
||||
compressionMethod_(),
|
||||
writeFieldTimes_(),
|
||||
timing_(true),
|
||||
writeAll_(false),
|
||||
tiny_(1.e-18),
|
||||
solDirs_((mesh_.solutionD() + Vector<label>::one)/2)
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
counter++;
|
||||
}
|
||||
initialize();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void storageParameters::initialize()
|
||||
{
|
||||
// Build list containing the IDs of the first cell centers next to wall
|
||||
// boundaries
|
||||
findCellsNextToWall();
|
||||
|
||||
adjustTimeStep_ =
|
||||
mesh_.time().controlDict().getOrDefault<Switch>("adjustTimeStep", false);
|
||||
storeAllBoundaries_ =
|
||||
dict_.getOrDefault<Switch>("storeAllBoundaries", false);
|
||||
storeUniformBoundaries_ =
|
||||
dict_.getOrDefault<Switch>("storeUniformBoundaries", false);
|
||||
algorithm_ = dict_.get<word>("algorithm");
|
||||
timing_ = dict_.getOrDefault<bool>("timing", true);
|
||||
Info<< nl << "General Parameters:" << nl
|
||||
<< tab << "algorithm " << algorithm_ << nl
|
||||
<< tab << "timing " << timing_ << nl
|
||||
<< tab << "storeAllBoundaries " << storeAllBoundaries_ << endl;
|
||||
if (!timing_)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Timing should be deactivated only when a reduced performance "
|
||||
<< "is acceptable."
|
||||
<< endl;
|
||||
}
|
||||
if (!storeAllBoundaries_)
|
||||
{
|
||||
Info<< tab << "storeUniformBoundaries "
|
||||
<< storeUniformBoundaries_ << endl;
|
||||
if (storeUniformBoundaries_)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "'storeUniformBoundaries' has been activated." << nl
|
||||
<< "This is redundant but useful in debugging." << nl
|
||||
<< "Make sure it is intentional." << endl;
|
||||
}
|
||||
}
|
||||
if (storeAllBoundaries_)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "'storeAllBoundaries' should be activated only for debugging "
|
||||
<< "purposes, since unneccessary storage is allocated" << endl;
|
||||
}
|
||||
writeAll_ = dict_.getOrDefault<bool>("writeAll", false);
|
||||
Info << tab << "writeAll " << writeAll_ << endl;
|
||||
if (!writeAll_)
|
||||
{
|
||||
writeFieldTimes_ =
|
||||
dict_.getOrDefault<scalarList>("writeFieldTimes", scalarList());
|
||||
if (writeFieldTimes_.size() > 0)
|
||||
{
|
||||
Info<< tab << "Time-steps to write primal fields:" << endl
|
||||
<< tab << writeFieldTimes_ << nl << endl;
|
||||
}
|
||||
}
|
||||
Info << endl;
|
||||
}
|
||||
|
||||
|
||||
void storageParameters::reset()
|
||||
{
|
||||
// Does nothing in base
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,273 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2022 PCOpt/NTUA
|
||||
Copyright (C) 2022 FOSS GP
|
||||
-------------------------------------------------------------------------------
|
||||
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
|
||||
storageParameters
|
||||
|
||||
Description
|
||||
Reads from dictionary and stores all parameters related to the storage
|
||||
of the primal fields
|
||||
|
||||
SourceFiles
|
||||
storageParameters.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef storageParameters_H
|
||||
#define storageParameters_H
|
||||
|
||||
#include "fvMesh.H"
|
||||
#include "dictionary.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class storageParameters Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class storageParameters
|
||||
{
|
||||
static label counter;
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
// Protected Data
|
||||
|
||||
const fvMesh& mesh_;
|
||||
|
||||
const dictionary dict_;
|
||||
|
||||
const wordList& allocatedFieldNames_;
|
||||
|
||||
|
||||
// Entries read from dictionary
|
||||
|
||||
//- Entry defining if the simulation has a constant time-step or
|
||||
//- not. Added here to define whether the time-step must be updated
|
||||
//- when retrieving the variablesSet in checkPointing
|
||||
Switch adjustTimeStep_;
|
||||
|
||||
//- Entry defining if all boundaries will be stored, regardless if
|
||||
//- they contain values that can be reproduced upon reconstruction.
|
||||
// Defaults to false.
|
||||
Switch storeAllBoundaries_;
|
||||
|
||||
//- Switch defining if the uniform boundaries must be compressed or
|
||||
//- not. If false, a single value (scalar or vector) will be kept
|
||||
//- for each of these boundaries. If true, these boundaries will be
|
||||
//- stored using the same algorithm with the internalField. If
|
||||
//- 'storeAllBoundaries' is set to true, this switch should have no
|
||||
//- effect
|
||||
Switch storeUniformBoundaries_;
|
||||
|
||||
//- Algorithm to be used for the compression (ZFP, iPGD, etc)
|
||||
word algorithm_;
|
||||
|
||||
//- Entry defining the algorithm variant to be used for the
|
||||
//- compression of each field. Valid entries are the derived
|
||||
//- classes of the compressedGeometricField class. The method is
|
||||
//- defined here once for all the objects to be created during the
|
||||
//- optimization (of course the method may differ for each primal
|
||||
//- field).
|
||||
wordList compressionMethod_;
|
||||
|
||||
//- scalarList containing the times on which the primal fields must
|
||||
//- be written. Both before compression and after decompression.
|
||||
scalarList writeFieldTimes_;
|
||||
|
||||
//- boolean controling if all unnecessary actions are avoided to
|
||||
//- benchmark the code
|
||||
bool timing_;
|
||||
|
||||
//- boolean activated only if timing_ is set to false. If
|
||||
//- activated, the writeFieldTimes is ignored and the 'exact' and
|
||||
//- the reconstructed fields are written at all time-steps
|
||||
bool writeAll_;
|
||||
|
||||
|
||||
//- Small scalar value to be added in the denominator to avoid division
|
||||
//- by zero
|
||||
scalar tiny_;
|
||||
|
||||
//- Return the vector of solved-for directions in mesh.
|
||||
// 1 indicates valid direction and 0 an invalid direction.
|
||||
const Vector<label> solDirs_;
|
||||
|
||||
//- List containing the IDs of the first cell centers next to wall
|
||||
//- boundaries
|
||||
labelList wallList_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Fills in wallList_
|
||||
void findCellsNextToWall();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
storageParameters(const storageParameters&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const storageParameters&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
TypeName("storageParameters");
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
storageParameters,
|
||||
dictionary,
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& storageDict,
|
||||
const wordList& allocatedFieldNames
|
||||
),
|
||||
(mesh, storageDict, allocatedFieldNames)
|
||||
);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
storageParameters
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& storageDict,
|
||||
const wordList& allocatedFieldNames
|
||||
);
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Return a reference to the selected storageParameters
|
||||
static autoPtr<storageParameters> New
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& storageDict,
|
||||
const wordList& allocatedFieldNames
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~storageParameters() = default;
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
virtual void initialize();
|
||||
|
||||
virtual void reset();
|
||||
|
||||
inline const fvMesh& mesh() const
|
||||
{
|
||||
return mesh_;
|
||||
}
|
||||
|
||||
inline const Switch& adjustTimeStep() const
|
||||
{
|
||||
return adjustTimeStep_;
|
||||
}
|
||||
|
||||
inline const Switch& storeAllBoundaries() const
|
||||
{
|
||||
return storeAllBoundaries_;
|
||||
}
|
||||
|
||||
inline const Switch& storeUniformBoundaries() const
|
||||
{
|
||||
return storeUniformBoundaries_;
|
||||
}
|
||||
|
||||
inline const word& algorithm() const
|
||||
{
|
||||
return algorithm_;
|
||||
}
|
||||
|
||||
inline const dictionary& dict() const
|
||||
{
|
||||
return dict_;
|
||||
}
|
||||
|
||||
inline const scalarList& writeFieldTimes() const
|
||||
{
|
||||
return writeFieldTimes_;
|
||||
}
|
||||
|
||||
inline bool timing() const
|
||||
{
|
||||
return timing_;
|
||||
}
|
||||
|
||||
inline bool writeAll() const
|
||||
{
|
||||
return writeAll_;
|
||||
}
|
||||
|
||||
inline const Vector<label>& solDirs() const
|
||||
{
|
||||
return solDirs_;
|
||||
}
|
||||
|
||||
inline const wordList& compressionMethod() const
|
||||
{
|
||||
return compressionMethod_;
|
||||
}
|
||||
|
||||
inline scalar tiny() const
|
||||
{
|
||||
return tiny_;
|
||||
}
|
||||
|
||||
inline const labelList& wallList() const
|
||||
{
|
||||
return wallList_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user