Compare commits

...

4 Commits

Author SHA1 Message Date
07664c0de8 TUT: added two unsteady adjoint optimisation tutorials
showcasing the use of compressedFullStorage and binomialCheckPointing
2022-07-15 16:43:12 +03:00
32c8fb57b7 ENH: introduced unsteady adjoint functionality
- The unsteady adjoint equations are integrated backwards in time. Since
  each adjoint time-step requires the primal solution of that time-step
  to be known, schemes for managing the storage/retrieval of the entire
  flow series are necessary. These are implemented through the
  primalStorage class and its derived ones. The latter manipulate a new
  class of fields, called compressedGeometricFields, which provide hooks
  for compressing/decompressing a field during the time integration of
  the primal/adjoint equations. The method used for
  compressing/decompressing is run-time selectable.
- The current commit provides the shortGeometricField implementation
  which avoids the storage of patchFields that can be retrieved from the
  internalField (e.g. coupled, zeroGradient, symmetry, etc) , to cut on
  the storage requirements. More elaborate compression approaches will
  be included in the future, during the exaFoam project.
- Two primalStorage options are included: compressedFullStorage and
  binomialCheckPointing.
    - compressedFullStorage stores the entire flow time-series,
      potentially by compressing each time-step (only the
      above-mentioned short approach is available for the moment).
    - binomialCheckPointing is based on the homonymous algorithm
      found in

      \verbatim
          Wang, Q., Moin, P., & Iaccarino, G..
          Minimal Repetition Dynamic Checkpointing Algorithm for
          Unsteady Adjoint Calculation (2009).
          SIAM Journal on Scientific Computing, 31(4), 2549-2567.
          10.1137/080727890,
      \endverbatim

      which stores the solution of the flow equations in a predefined
      number of time-steps, named checkpoints. During the
      backwards-in-time integration of the adjoint equations, if the
      primal solution at a certain time-step is not available, it is
      retrieved by re-computing the primal flow field starting from the
      closest checkpoint. Checkpoints are optimally distributed
      throughout the time-series to invoke the least number of flow
      recomputations during the backwards-in-time solution of the
      adjoint equations. Binomial checkpointing is the current state of
      the art though its re-computation cost frequently amounts for an
      extra solution of the flow equations in medium-to-large cases.
- The adjoint to the PISO and PIMPLE solvers, along with their
  solverControl variants, are additionally included.
- Objective functions are integrated in time, through appropriate
  entries in the dictionaries defining them.

Authored by Andreas Margetis and reviewed by Vaggelis Papoutsis, with
earlier contributions from Dr. Ioannis Kavvadias.
2022-07-15 16:43:10 +03:00
4ee7dd50ee ENH: optionally read oldTimes in two GeometricField constructors
These are used by the adjoint code and are necessary for unsteady
adjoint simulations. Both additions are implemented through optional
arguments with default values, to maintain backwards compatibility for
the rest of the code base.
2022-07-15 16:43:07 +03:00
162f5f29ec ENH: modifications in Time to support unsteady adjoint
Since the unsteady adjoint equations are integrated backwards in time,
the -- operator and the reverseEnd and reverseLoop methods were added to
control the flow of time and the ending criteria.
2022-07-15 16:43:06 +03:00
142 changed files with 15568 additions and 539 deletions

View File

@ -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--();
}
// ************************************************************************* //

View File

@ -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);
};

View File

@ -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>
(

View File

@ -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

View File

@ -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

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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_)
{

View File

@ -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;

View File

@ -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_);

View File

@ -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)

View File

@ -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();
};

View File

@ -45,7 +45,9 @@ Foam::singleRun::singleRun(fvMesh& mesh)
:
optimisationManager(mesh),
cycles_(Zero)
{}
{
initialize();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //

View File

@ -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();
}
}
// ************************************************************************* //

View File

@ -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();
};

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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();
}
}
// ************************************************************************* //

View File

@ -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

View File

@ -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);
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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);
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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();

View File

@ -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();

View File

@ -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

View File

@ -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:

View File

@ -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())
{

View File

@ -98,7 +98,8 @@ public:
(
fvMesh& mesh,
const word& managerType,
const dictionary& dict
const dictionary& dict,
Switch useCustomReadTime = false
);

View File

@ -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)
);
}

View File

@ -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
);

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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)),

View File

@ -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
);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
(

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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();
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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();
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -36,7 +36,7 @@ License
namespace Foam
{
defineTypeNameAndDebug(SIMPLEControlOpt, 1);
addToRunTimeSelectionTable( SIMPLEControl, SIMPLEControlOpt, dictionary);
addToRunTimeSelectionTable(SIMPLEControl, SIMPLEControlOpt, dictionary);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //

View File

@ -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_
(

View File

@ -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;
};

View File

@ -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_;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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);
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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

View File

@ -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);
};

View File

@ -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

View File

@ -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);
};

View File

@ -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

View File

@ -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);
};

View File

@ -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

View File

@ -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);
};

View File

@ -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

View File

@ -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;
*/
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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_;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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();
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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