Merge branch 'fix-opt-convergence-criteria' into 'master'

BUG: optimisation convergence criteria misbehave w/o a line search (fixes #3268)

Closes #3268

See merge request Development/openfoam!709
This commit is contained in:
Andrew Heather 2024-12-10 09:28:20 +00:00
commit b9335f4989
5 changed files with 96 additions and 88 deletions

View File

@ -136,82 +136,6 @@ void Foam::designVariablesUpdate::writeToCostFile(bool zeroAdjointSolns)
}
void Foam::designVariablesUpdate::checkConvergence
(
const scalarField& oldCorrection
)
{
bool converged(false);
// Design variables convergence check
if (designVarsThreshold_)
{
const labelList& activeVarIDs =
designVars_->activeDesignVariables();
const scalarField correction(oldCorrection, activeVarIDs);
const scalarField activeVars(designVars_->getVars(), activeVarIDs);
const scalar scaledCorrection =
gMax(mag(correction)/(mag(activeVars) + SMALL));
DebugInfo
<< "Current correction " << correction << nl
<< "Active vars " << activeVars << endl;
Info<< "Max. scaled correction of the design variables = "
<< scaledCorrection
<< endl;
if (scaledCorrection < designVarsThreshold_())
{
Info<< tab << "Design variables have converged " << endl;
converged = true;
}
}
// Objective convergence check
if (objectiveThreshold_)
{
const scalar newObjective = computeObjectiveValue();
const scalar oldObjective = updateMethod_->getObjectiveValueOld();
const scalar relativeUpdate =
mag(newObjective - oldObjective)/(mag(oldObjective) + SMALL);
Info<< "Relative change of the objective value = "
<< relativeUpdate
<< endl;
if (relativeUpdate < objectiveThreshold_())
{
Info<< tab << "Objective function has converged " << endl;
converged = true;
}
}
// Feasibility check
const scalarField& constraints = updateMethod_->getConstraintValues();
const scalar feasibility = sum(pos(constraints)*constraints);
Info<< "Feasibility = " << feasibility << endl;
if (converged && feasibility < feasibilityThreshold_)
{
Info<< "Stopping criteria met and all constraints satisfied." << nl
<< "Optimisation has converged, stopping ..." << nl << nl
<< "End" << nl
<< endl;
// Force writing of all objective and constraint functions, to get
// the converged results to files
for (adjointSolverManager& am : adjointSolvManagers_)
{
for (adjointSolver& as : am.adjointSolvers())
{
// Use dummy weighted objective
as.getObjectiveManager().writeObjectives();
}
}
writeToCostFile(true);
if (UPstream::parRun())
{
UPstream::exit(0);
}
else
{
std::exit(0);
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::designVariablesUpdate::designVariablesUpdate
@ -570,10 +494,86 @@ void Foam::designVariablesUpdate::postUpdate(const scalarField& oldCorrection)
}
}
}
checkConvergence();
}
if (convergenceCriteriaDefined_)
}
void Foam::designVariablesUpdate::checkConvergence()
{
if (!convergenceCriteriaDefined_)
{
checkConvergence(oldCorrection);
return;
}
bool converged(false);
const scalarField& oldCorrection = updateMethod_->returnCorrection();
// Design variables convergence check
if (designVarsThreshold_)
{
const labelList& activeVarIDs =
designVars_->activeDesignVariables();
const scalarField correction(oldCorrection, activeVarIDs);
const scalarField activeVars(designVars_->getVars(), activeVarIDs);
const scalar scaledCorrection =
gMax(mag(correction)/(mag(activeVars) + SMALL));
DebugInfo
<< "Current correction " << correction << nl
<< "Active vars " << activeVars << endl;
Info<< "Max. scaled correction of the design variables = "
<< scaledCorrection
<< endl;
if (scaledCorrection < designVarsThreshold_())
{
Info<< tab << "Design variables have converged " << endl;
converged = true;
}
}
// Objective convergence check
if (objectiveThreshold_ && updateMethod_->getObjectiveValueOld())
{
const scalar newObjective = computeObjectiveValue();
const scalar oldObjective = updateMethod_->getObjectiveValueOld()();
const scalar relativeUpdate =
mag(newObjective - oldObjective)/(mag(oldObjective) + SMALL);
Info<< "Relative change of the objective value = "
<< relativeUpdate
<< endl;
if (relativeUpdate < objectiveThreshold_())
{
Info<< tab << "Objective function has converged " << endl;
converged = true;
}
}
// Feasibility check
const scalarField& constraints = updateMethod_->getConstraintValues();
const scalar feasibility = sum(pos(constraints)*constraints);
Info<< "Feasibility = " << feasibility << endl;
if (converged && feasibility < feasibilityThreshold_)
{
Info<< "Stopping criteria met and all constraints satisfied." << nl
<< "Optimisation has converged, stopping ..." << nl << nl
<< "End" << nl
<< endl;
// Force writing of all objective and constraint functions, to get
// the converged results to files
for (adjointSolverManager& am : adjointSolvManagers_)
{
for (adjointSolver& as : am.adjointSolvers())
{
// Use dummy weighted objective
as.getObjectiveManager().writeObjectives();
}
}
writeToCostFile(true);
if (UPstream::parRun())
{
UPstream::exit(0);
}
else
{
std::exit(0);
}
}
}

View File

@ -138,11 +138,6 @@ protected:
//- Write to cost file
void writeToCostFile(bool zeroAdjointSolns = false);
//- Check if the optimisation loop has converged based on the provided
//- criteria
// May terminate the program
void checkConvergence(const scalarField& oldCorrection);
private:
@ -216,6 +211,11 @@ public:
//- in the fixedStep approach
void postUpdate(const scalarField& oldCorrection);
//- Check if the optimisation loop has converged based on the provided
//- criteria
// May terminate the program
void checkConvergence();
//- Get access to design variables
inline autoPtr<designVariables>& getDesignVariables()
{

View File

@ -172,6 +172,9 @@ void Foam::optimisationManager::fixedStepUpdate()
// Solve primal equations
solvePrimalEquations();
// Check the convergence criteria of the optimisation loop
dvUpdate_->checkConvergence();
// Reset adjoint sensitivities in all adjoint solver managers
clearSensitivities();

View File

@ -237,7 +237,7 @@ Foam::updateMethod::updateMethod
objectiveDerivatives_(designVars().getVars().size(), Zero),
constraintDerivatives_(0),
objectiveValue_(0),
objectiveValueOld_(0),
objectiveValueOld_(nullptr),
cValues_(0),
correction_(readOrZeroField("correction", designVars().getVars().size())),
cumulativeCorrection_(0),
@ -334,7 +334,11 @@ void Foam::updateMethod::setObjectiveValue(const scalar value)
void Foam::updateMethod::setObjectiveValueOld(const scalar value)
{
objectiveValueOld_ = value;
if (!objectiveValueOld_)
{
objectiveValueOld_.reset(new scalar(Zero));
}
objectiveValueOld_.ref() = value;
}
@ -350,7 +354,8 @@ Foam::scalar Foam::updateMethod::getObjectiveValue() const
}
Foam::scalar Foam::updateMethod::getObjectiveValueOld() const
const Foam::autoPtr<Foam::scalar>&
Foam::updateMethod::getObjectiveValueOld() const
{
return objectiveValueOld_;
}

View File

@ -84,7 +84,7 @@ protected:
//- Old objective value
// Used for convergence checking
scalar objectiveValueOld_;
autoPtr<scalar> objectiveValueOld_;
//- Constraint values
scalarField cValues_;
@ -239,7 +239,7 @@ public:
scalar getObjectiveValue() const;
//- Get old objective value
scalar getObjectiveValueOld() const;
const autoPtr<scalar>& getObjectiveValueOld() const;
//- Get values of constraints
const scalarField& getConstraintValues() const;