76 if (counter_ > nPrevSteps_)
80 newOrder[0] = nPrevSteps_ - 1;
81 for (label i = 1; i < nPrevSteps_; ++i)
85 list.reorder(newOrder);
88 list[nPrevSteps_ - 1] =
f;
92 list[counter_ - 1] =
f;
106 (derivatives.size() != derivativesOld.size())
107 || (derivatives.size() != designVars_().getVars().size())
111 <<
"Sizes of input derivatives and design variables do not match" 117 scalarField yRecent(derivatives - derivativesOld, activeDesignVars_);
120 scalarField sActive(correctionOld_, activeDesignVars_);
121 applyDamping(yRecent, sActive);
123 pivotFields(y_, yRecent);
124 pivotFields(s_, sActive);
130 const scalar sy(globalSum(
s*
y));
133 const scalarField Hy(invHessianVectorProduct(
y, counter_ - 1));
134 const scalar yHy(globalSum(
y*Hy));
139 <<
"y*s is below threshold. Using damped form" <<
nl 140 <<
"sy, yHy " << sy <<
" " << yHy <<
endl;
142 theta = 0.8*yHy/(yHy - sy);
144 s = theta*
s + (1 - theta)*Hy;
146 else if (useYDamping_)
148 const scalarField Bs(HessianVectorProduct(
s, counter_ - 1));
149 const scalar sBs(globalSum(
s*Bs));
154 <<
"y*s is below threshold. Using damped form" <<
nl 155 <<
"sy, sBs " << sy <<
" " << sBs <<
endl;
157 theta = 0.8*sBs/(sBs - sy);
159 y = theta*
y + (1 - theta)*Bs;
162 <<
"Curvature index (sy) is " << sy <<
endl;
169 return invHessianVectorProduct(
vector, counter_);
184 label nv = designVars_().getVars().
size();
185 label nav = activeDesignVars_.size();
197 <<
"Size of input vector " 199 <<
"is equal to neither the number of design variabes " 201 <<
" nor that of the active design variables " 210 label nSteps(
min(counter, nPrevSteps_));
211 label nLast(nSteps - 1);
214 for (label i = nLast; i > -1; --i)
216 r[i] = 1./globalSum(y_[i]*s_[i]);
217 a[i] = r[i]*globalSum(s_[i]*q);
222 globalSum(y_[nLast]*y_[nLast])/globalSum(y_[nLast]*s_[nLast]);
233 for (label i = 0; i < nSteps; ++i)
235 b = r[i]*globalSum(y_[i]*q);
236 q += s_[i]*(a[i] -
b);
251 return HessianVectorProduct(
vector, counter_);
268 if (
vector.size() == designVars_().getVars().size())
272 else if (
vector.
size() == activeDesignVars_.size())
279 <<
"Size of input vector is equal to neither the number of " 280 <<
" design variabes nor that of the active design variables" 286 const label nSteps(
min(counter, nPrevSteps_));
287 const label nLast(nSteps - 1);
289 globalSum(y_[nLast]*y_[nLast])/globalSum(y_[nLast]*s_[nLast]);
293 for (label i = 0; i < nSteps; ++i)
295 SKsource[i] =
delta*globalSum(s_[i]*source);
296 SKsource[i + nSteps] = globalSum(y_[i]*source);
300 SquareMatrix<scalar>
M(2*nSteps, 2*nSteps,
Zero);
301 for (label i = 0; i < nSteps; ++i)
304 M[nSteps + i][nSteps + i] = - globalSum(s_[i]*y_[i]);
306 for (label j = 0; j < nSteps; ++j)
308 M[i][j] =
delta*globalSum(s_[i]*s_[j]);
313 for (label j = 0; j < nSteps; ++j)
315 for (label i = j + 1; i < nSteps; ++i)
317 scalar value = globalSum(s_[i]*y_[j]);
318 M[i][j + nSteps] = value;
319 M[j + nSteps][i] = value;
322 SquareMatrix<scalar> invM(
inv(
M));
331 for (label j = 0; j < nSteps; ++j)
334 delta*s_[j][i]*invMSource[j]
335 + y_[j][i]*invMSource[j + nSteps];
353 const label
n(activeDesignVars_.size());
359 const label nSteps(
min(counter_, nPrevSteps_));
360 const label nLast(nSteps - 1);
362 globalSum(y_[nLast]*y_[nLast])/globalSum(y_[nLast]*s_[nLast]);
366 SquareMatrix<scalar>
M(2*nSteps, 2*nSteps,
Zero);
367 for (label i = 0; i < nSteps; ++i)
370 M[nSteps + i][nSteps + i] = - globalSum(s_[i]*y_[i]);
372 for (label j = 0; j < nSteps; ++j)
374 M[i][j] =
delta*globalSum(s_[i]*s_[j]);
379 for (label j = 0; j < nSteps; ++j)
381 for (label i = j + 1; i < nSteps; ++i)
383 scalar value = globalSum(s_[i]*y_[j]);
384 M[i][j + nSteps] = value;
385 M[j + nSteps][i] = value;
390 SquareMatrix<scalar> invM(
inv(
M));
394 for (label
k = 0;
k <
n; ++
k)
396 for (label i = 0; i < 2*nSteps; ++i)
398 for (label j = 0; j < nSteps; ++j)
402 + invM[i][j + nSteps]*y_[j][
k];
410 for (label
k = 0;
k <
n; ++
k)
412 for (label j = 0; j < nSteps; ++j)
415 delta*s_[j][
k]*MR[j][
k] + y_[j][
k]*MR[j + nSteps][
k];
427 return SR1HessianVectorProduct(
vector, counter_);
443 if (
vector.size() == designVars_().getVars().size())
447 else if (
vector.
size() == activeDesignVars_.size())
454 <<
"Size of input vector is equal to neither the number of " 455 <<
" design variabes nor that of the active design variables" 461 const label nSteps(
min(counter, nPrevSteps_));
462 const label nLast(nSteps - 1);
464 globalSum(y_[nLast]*y_[nLast])/globalSum(y_[nLast]*s_[nLast]);
468 for (label i = 0; i < nSteps; ++i)
470 YBSsource[i] = globalSum((y_[i] -
delta*s_[i])*source);
474 SquareMatrix<scalar>
M(nSteps, nSteps,
Zero);
475 for (label i = 0; i < nSteps; ++i)
478 M[i][i] += globalSum(s_[i]*y_[i]);
480 for (label j = 0; j < nSteps; ++j)
482 M[i][j] -=
delta*globalSum(s_[i]*s_[j]);
487 for (label j = 0; j < nSteps; ++j)
489 for (label i = j + 1; i < nSteps; ++i)
491 scalar value = globalSum(s_[i]*y_[j]);
496 SquareMatrix<scalar> invM(
inv(
M));
499 scalarField invMSource(rightMult(invM, YBSsource));
505 for (label j = 0; j < nSteps; ++j)
507 q[i] += (y_[j][i] -
delta*s_[j][i])*invMSource[j];
525 const label
n(activeDesignVars_.size());
531 const label nSteps(
min(counter_, nPrevSteps_));
532 const label nLast(nSteps - 1);
534 globalSum(y_[nLast]*y_[nLast])/globalSum(y_[nLast]*s_[nLast]);
538 SquareMatrix<scalar>
M(nSteps, nSteps,
Zero);
539 for (label i = 0; i < nSteps; ++i)
542 M[i][i] += globalSum(s_[i]*y_[i]);
544 for (label j = 0; j < nSteps; ++j)
546 M[i][j] -=
delta*globalSum(s_[i]*s_[j]);
551 for (label j = 0; j < nSteps; ++j)
553 for (label i = j + 1; i < nSteps; ++i)
555 scalar value = globalSum(s_[i]*y_[j]);
560 SquareMatrix<scalar> invM(
inv(
M));
564 for (label
k = 0;
k <
n; ++
k)
566 for (label i = 0; i < nSteps; ++i)
568 for (label j = 0; j < nSteps; ++j)
570 MR[i][
k] += invM[i][j]*(y_[j][
k] -
delta*s_[j][
k]);
578 for (label
k = 0;
k <
n; ++
k)
580 for (label j = 0; j < nSteps; ++j)
593 updateVectors(objectiveDerivatives_, derivativesOld_);
601 if (counter_ < nSteepestDescent_)
603 Info<<
"Using steepest descent to update design variables" <<
endl;
604 for (
const label varI : activeDesignVars_)
606 correction_[varI] = -eta_*objectiveDerivatives_[varI];
612 scalarField q(invHessianVectorProduct(objectiveDerivatives_));
613 forAll(activeDesignVars_, varI)
615 correction_[activeDesignVars_[varI]] = -etaHessian_*q[varI];
620 derivativesOld_ = objectiveDerivatives_;
621 correctionOld_ = correction_;
632 const label nConstraints,
637 nPrevSteps_(coeffsDict(
type).getOrDefault<label>(
"nPrevSteps", 10)),
640 useSDamping_(coeffsDict(
type).getOrDefault<bool>(
"useSDamping", false)),
641 useYDamping_(coeffsDict(
type).getOrDefault<bool>(
"useYDamping", false))
void size(const label n)
Older name for setAddressableSize.
errorManipArg< error, int > exit(error &err, const int errNo=1)
virtual void update()
Update design variables.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
tmp< scalarField > SR1HessianDiag()
Return the diagonal of the Hessian.
dimensionedSphericalTensor inv(const dimensionedSphericalTensor &dt)
constexpr char nl
The newline '\n' character (0x0a)
Ostream & endl(Ostream &os)
Add newline and flush stream.
label k
Boltzmann constant.
virtual bool writeData(Ostream &os) const
Write useful quantities to files.
virtual tmp< scalarField > invHessianVectorProduct(const scalarField &vector)
Compute the inverse Hessian - vector product.
Macros for easy insertion into run-time selection tables.
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
#define forAll(list, i)
Loop across all elements in list.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
const labelList & activeDesignVars_
Map to active design variables.
#define addProfiling(Name, Descr)
Define profiling trigger with specified name and description string.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
void pivotFields(PtrList< scalarField > &list, const scalarField &f)
Move pointers in PtrList to the left and replace last element with given field.
Base class for quasi-Newton methods.
virtual tmp< scalarField > HessianVectorProduct(const scalarField &vector)
Compute the Hessian - vector product.
A class for handling words, derived from Foam::string.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
PtrList< scalarField > s_
The previous correction. Holds nPrevSteps_ fields.
void allocateVectors()
Allocate matrices in the first optimisation cycle.
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
label nPrevSteps_
Number of old corrections and grad differences kept.
virtual void updateHessian()
Update the Hessian matrix by updating the base vectors.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
virtual bool writeData(Ostream &os) const
Write useful quantities to files.
#define DebugInfo
Report an information message using Foam::Info.
void map(const UList< Type > &mapF, const labelUList &mapAddressing)
1 to 1 map from the given field
An Ostream is an abstract base class for all output systems (streams, files, token lists...
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
OBJstream os(runTime.globalPath()/outputName)
defineTypeNameAndDebug(combustionModel, 0)
tmp< scalarField > HessianDiag()
Return the diagonal of the Hessian.
virtual tmp< scalarField > SR1HessianVectorProduct(const scalarField &vector)
Compute the Hessian - vector product.
static constexpr direction size() noexcept
The number of elements in the VectorSpace = Ncmpts.
#define WarningInFunction
Report a warning using Foam::Warning.
Mesh data needed to do the Finite Volume discretisation.
PtrList< scalarField > y_
The previous differences of derivatives. Holds nPrevSteps_ fields.
The quasi-Newton Limited-memory BFGS formula. Keeps nPrevSteps_ of the y and s vectors and approximat...
messageStream Info
Information stream (stdout output on master, null elsewhere)
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
List< label > labelList
A List of labels.
A class for managing temporary objects.
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
void updateVectors(const scalarField &derivatives, const scalarField &derivativesOld)
Update y and s vectors.
void applyDamping(scalarField &y, scalarField &s)
Use the damped version of s to ensure positive-definitiveness.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
static constexpr const zero Zero
Global zero (0)