adjointSimple.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2007-2019 PCOpt/NTUA
9  Copyright (C) 2013-2019 FOSS GP
10  Copyright (C) 2019 OpenCFD Ltd.
11 -------------------------------------------------------------------------------
12 License
13  This file is part of OpenFOAM.
14 
15  OpenFOAM is free software: you can redistribute it and/or modify it
16  under the terms of the GNU General Public License as published by
17  the Free Software Foundation, either version 3 of the License, or
18  (at your option) any later version.
19 
20  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
21  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  for more details.
24 
25  You should have received a copy of the GNU General Public License
26  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
27 
28 \*---------------------------------------------------------------------------*/
29 
30 #include "adjointSimple.H"
31 #include "findRefCell.H"
32 #include "constrainHbyA.H"
33 #include "adjustPhi.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40  defineTypeNameAndDebug(adjointSimple, 0);
42  (
43  incompressibleAdjointSolver,
44  adjointSimple,
45  dictionary
46  );
47 }
48 
49 
50 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
51 
53 {
54  vars_.reset
55  (
57  (
58  mesh_,
62  )
63  );
64  return getAdjointVars();
65 }
66 
67 
69 {
70  if (adjointVars_.useSolverNameForFields())
71  {
73  << "useSolverNameForFields is set to true for adjointSolver "
74  << solverName() << nl << tab
75  << "Appending variable names with the solver name" << nl << tab
76  << "Please adjust the necessary entries in fvSchemes and fvSolution"
77  << nl << endl;
78  }
79 }
80 
81 
83 {
84  const surfaceScalarField& phia = adjointVars_.phiaInst();
86 
87  scalar sumLocalContErr = mesh_.time().deltaTValue()*
88  mag(contErr)().weightedAverage(mesh_.V()).value();
89 
90  scalar globalContErr = mesh_.time().deltaTValue()*
91  contErr.weightedAverage(mesh_.V()).value();
92  cumulativeContErr_ += globalContErr;
93 
94  Info<< "time step continuity errors : sum local = " << sumLocalContErr
95  << ", global = " << globalContErr
96  << ", cumulative = " << cumulativeContErr_
97  << endl;
98 }
99 
100 
101 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
102 
103 Foam::adjointSimple::adjointSimple
104 (
105  fvMesh& mesh,
106  const word& managerType,
107  const dictionary& dict,
108  const word& primalSolverName
109 )
110 :
111  incompressibleAdjointSolver(mesh, managerType, dict, primalSolverName),
112  solverControl_(SIMPLEControl::New(mesh, managerType, *this)),
113  adjointVars_(allocateVars()),
114  cumulativeContErr_(Zero),
115  adjointSensitivity_(nullptr)
116 {
117  ATCModel_.reset
118  (
120  (
121  mesh,
122  primalVars_,
123  adjointVars_,
124  dict.subDict("ATCModel")
125  ).ptr()
126  );
127 
128  addExtraSchemes();
129  setRefCell
130  (
131  adjointVars_.paInst(),
132  solverControl_().dict(),
133  solverControl_().pRefCell(),
134  solverControl_().pRefValue()
135  );
136 
137  if (computeSensitivities_)
138  {
139  const IOdictionary& optDict =
140  mesh.lookupObject<IOdictionary>("optimisationDict");
141 
142  adjointSensitivity_.reset
143  (
145  (
146  mesh,
147  optDict.subDict("optimisation").subDict("sensitivities"),
148  primalVars_,
149  adjointVars_,
150  objectiveManagerPtr_(),
151  fvOptionsAdjoint_
152  ).ptr()
153  );
154  }
155 }
156 
157 
158 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
159 
161 {
163  {
164  if (adjointSensitivity_.valid())
165  {
166  const IOdictionary& optDict =
167  mesh_.lookupObject<IOdictionary>("optimisationDict");
168 
169  adjointSensitivity_().readDict
170  (
171  optDict.subDict("optimisation").subDict("sensitivities")
172  );
173  }
174 
175  return true;
176  }
177 
178  return false;
179 }
180 
181 
183 {
184  const Time& time = mesh_.time();
185  Info<< "Time = " << time.timeName() << "\n" << endl;
186 
187  // Grab primal references
188  const surfaceScalarField& phi = primalVars_.phi();
189  // Grab adjoint references
190  volScalarField& pa = adjointVars_.paInst();
191  volVectorField& Ua = adjointVars_.UaInst();
192  surfaceScalarField& phia = adjointVars_.phiaInst();
194  adjointVars_.adjointTurbulence();
195  const label& paRefCell = solverControl_().pRefCell();
196  const scalar& paRefValue = solverControl_().pRefValue();
197 
198  // Momentum predictor
199  //~~~~~~~~~~~~~~~~~~~
200 
201  tmp<fvVectorMatrix> tUaEqn
202  (
203  fvm::div(-phi, Ua)
204  + adjointTurbulence->divDevReff(Ua)
205  + adjointTurbulence->adjointMeanFlowSource()
206  ==
207  fvOptionsAdjoint_(Ua)
208  );
209  fvVectorMatrix& UaEqn = tUaEqn.ref();
210 
211  // Add sources from boundary conditions
212  UaEqn.boundaryManipulate(Ua.boundaryFieldRef());
213 
214  // Add sources from volume-based objectives
215  objectiveManagerPtr_().addUaEqnSource(UaEqn);
216 
217  // Add ATC term
218  ATCModel_->addATC(UaEqn);
219 
220  // Add source from optimisationType (e.g. topology)
221  addOptimisationTypeSource(UaEqn);
222 
223  UaEqn.relax();
224 
225  fvOptionsAdjoint_.constrain(UaEqn);
226 
227  if (solverControl_().momentumPredictor())
228  {
229  Foam::solve(UaEqn == -fvc::grad(pa));
230 
231  fvOptionsAdjoint_.correct(Ua);
232  }
233 
234  // Pressure Eq
235  //~~~~~~~~~~~~
236  {
237  volScalarField rAUa(1.0/UaEqn.A());
238  // 190402: Vag: to be updated.
239  // Probably a constrainHabyA by class is needed?
240  volVectorField HabyA(constrainHbyA(rAUa*UaEqn.H(), Ua, pa));
241  surfaceScalarField phiaHbyA("phiaHbyA", fvc::flux(HabyA));
242  adjustPhi(phiaHbyA, Ua, pa);
243 
244  tmp<volScalarField> rAtUa(rAUa);
245 
246  if (solverControl_().consistent())
247  {
248  rAtUa = 1.0/(1.0/rAUa - UaEqn.H1());
249  phiaHbyA +=
250  fvc::interpolate(rAtUa() - rAUa)*fvc::snGrad(pa)*mesh_.magSf();
251  HabyA -= (rAUa - rAtUa())*fvc::grad(pa);
252  }
253 
254  tUaEqn.clear();
255 
256  // Update the pressure BCs to ensure flux consistency
257  // constrainPressure(p, U, phiHbyA, rAtU(), MRF_);
258 
259  // Non-orthogonal pressure corrector loop
260  while (solverControl_().correctNonOrthogonal())
261  {
262  fvScalarMatrix paEqn
263  (
264  fvm::laplacian(rAtUa(), pa) == fvc::div(phiaHbyA)
265  );
266 
268 
269  paEqn.setReference(paRefCell, paRefValue);
270 
271  paEqn.solve();
272 
273  if (solverControl_().finalNonOrthogonalIter())
274  {
275  phia = phiaHbyA - paEqn.flux();
276  }
277  }
278 
279  continuityErrors();
280 
281  // Explicitly relax pressure for adjoint momentum corrector
282  pa.relax();
283 
284  // Momentum corrector
285  Ua = HabyA - rAtUa()*fvc::grad(pa);
287  fvOptionsAdjoint_.correct(Ua);
289  }
290 
291  adjointTurbulence->correct();
292 
293  if (solverControl_().printMaxMags())
294  {
295  dimensionedScalar maxUa = max(mag(Ua));
296  dimensionedScalar maxpa = max(mag(pa));
297  Info<< "Max mag of adjoint velocity = " << maxUa.value() << endl;
298  Info<< "Max mag of adjoint pressure = " << maxpa.value() << endl;
299  }
300 
301  solverControl_().write();
302 
303  // Average fields if necessary
304  adjointVars_.computeMeanFields();
305 
306  // Print execution time
307  time.printExecutionTime(Info);
308 }
309 
310 
312 {
313  if (active_)
314  {
315  // Update objective function related quantities
316  objectiveManagerPtr_->updateAndWrite();
317 
318  // Reset mean fields before solving
319  adjointVars_.resetMeanFields();
320 
321  // Iterate
322  while (solverControl_().loop())
323  {
324  solveIter();
325  }
326  }
327 }
328 
329 
331 {
332  return solverControl_().loop();
333 }
334 
335 
337 {
338  if (computeSensitivities_)
339  {
340  adjointSensitivity_->accumulateIntegrand(scalar(1));
341  const scalarField& sens = adjointSensitivity_->calculateSensitivities();
342  if (sensitivities_.empty())
343  {
344  sensitivities_.reset(new scalarField(sens.size(), Zero));
345  }
346  sensitivities_.ref() = sens;
347  }
348  else
349  {
350  sensitivities_.reset(new scalarField());
351  }
352 }
353 
354 
356 {
357  if (!sensitivities_.valid())
358  {
359  computeObjectiveSensitivities();
360  }
361 
362  return sensitivities_();
363 }
364 
365 
367 {
368  if (computeSensitivities_)
369  {
370  adjointSensitivity_->clearSensitivities();
372  }
373 }
374 
375 
377 {
378  if (!adjointSensitivity_.valid())
379  {
381  << "Sensitivity object not allocated" << nl
382  << "Turn computeSensitivities on in "
383  << solverName_
384  << nl << nl
385  << exit(FatalError);
386  }
387 
388  return adjointSensitivity_();
389 }
390 
391 
393 {
394  os.writeEntry("averageIter", solverControl_().averageIter());
395 
396  return true;
397 }
398 
399 
400 // ************************************************************************* //
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
Foam::adjointSimple::continuityErrors
void continuityErrors()
Compute continuity errors.
Definition: adjointSimple.C:82
Foam::IOdictionary
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:54
Foam::constrainHbyA
tmp< volVectorField > constrainHbyA(const tmp< volVectorField > &tHbyA, const volVectorField &U, const volScalarField &p)
Definition: constrainHbyA.C:35
Foam::fvc::snGrad
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > snGrad(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvcSnGrad.C:47
sumLocalContErr
scalar sumLocalContErr
Definition: compressibleContinuityErrs.H:34
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:52
Foam::fvMatrix::boundaryManipulate
void boundaryManipulate(typename GeometricField< Type, fvPatchField, volMesh >::Boundary &values)
Manipulate based on a boundary field.
Definition: fvMatrix.C:742
contErr
volScalarField::Internal contErr((fvc::ddt(rho)+fvc::div(rhoPhi) -(fvOptions(alpha1, mixture.thermo1().rho())&rho1) -(fvOptions(alpha2, mixture.thermo2().rho())&rho2))())
Foam::adjustPhi
bool adjustPhi(surfaceScalarField &phi, const volVectorField &U, volScalarField &p)
Adjust the balance of fluxes to obey continuity.
Definition: adjustPhi.C:37
momentumPredictor
const bool momentumPredictor
Definition: readFluidMultiRegionSIMPLEControls.H:6
Foam::fvc::grad
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcGrad.C:54
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::adjointSimple::clearSensitivities
virtual void clearSensitivities()
Definition: adjointSimple.C:366
Foam::incompressibleAdjointSolver
Base class for incompressibleAdjoint solvers.
Definition: incompressibleAdjointSolver.H:54
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::adjointSimple::solveIter
virtual void solveIter()
Execute one iteration of the solution algorithm.
Definition: adjointSimple.C:182
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:59
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
findRefCell.H
Find the reference cell nearest (in index) to the given cell but which is not on a cyclic,...
Foam::adjointSimple::computeObjectiveSensitivities
virtual void computeObjectiveSensitivities()
Compute sensitivities of the underlaying objectives.
Definition: adjointSimple.C:336
Foam::incompressibleAdjointSolver::getAdjointVars
virtual const incompressibleAdjointVars & getAdjointVars() const
Access to the incompressible adjoint variables set.
Definition: incompressibleAdjointSolver.C:136
Foam::objectRegistry::time
const Time & time() const
Return time.
Definition: objectRegistry.H:186
Foam::solver::mesh_
fvMesh & mesh_
Reference to the mesh database.
Definition: solver.H:71
Foam::Time::timeName
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:764
Foam::incompressibleAdjoint::adjointRASModel::correct
virtual void correct()
Solve the adjoint turbulence equations.
Definition: adjointRASModel.C:215
Foam::fvc::div
tmp< GeometricField< Type, fvPatchField, volMesh > > div(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcDiv.C:49
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::dimensioned::value
const Type & value() const
Return const reference to value.
Definition: dimensionedType.C:404
Foam::fvMatrix::setReference
void setReference(const label celli, const Type &value, const bool forceReference=false)
Set reference level for solution.
Definition: fvMatrix.C:509
adjustPhi.H
For cases which do no have a pressure boundary adjust the balance of fluxes to obey continuity....
Foam::incompressibleAdjointVars
Class including all adjoint fields for incompressible flows.
Definition: incompressibleAdjointVars.H:52
Foam::adjointSolver::objectiveManagerPtr_
autoPtr< objectiveManager > objectiveManagerPtr_
Object to manage objective functions.
Definition: adjointSolver.H:80
Foam::Time::printExecutionTime
Ostream & printExecutionTime(OSstream &os) const
Print the elapsed ExecutionTime (cpu-time), ClockTime.
Definition: TimeIO.C:614
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:62
Foam::Field< scalar >
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::adjointSimple::getSensitivityBase
virtual sensitivity & getSensitivityBase()
Return the base sensitivity object.
Definition: adjointSimple.C:376
Foam::fvm::laplacian
tmp< fvMatrix< Type > > laplacian(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvmLaplacian.C:48
Foam::dictionary::subDict
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:523
Foam::setRefCell
bool setRefCell(const volScalarField &field, const volScalarField &fieldRef, const dictionary &dict, label &refCelli, scalar &refValue, const bool forceReference=false)
If the field fieldRef needs referencing find the reference cell nearest.
Definition: findRefCell.C:34
Foam::incompressible::adjointSensitivity::New
static autoPtr< adjointSensitivity > New(const fvMesh &mesh, const dictionary &dict, incompressibleVars &primalVars, incompressibleAdjointVars &adjointVars, objectiveManager &objectiveManager, fv::optionAdjointList &fvOptionsAdjoint)
Return a reference to the selected turbulence model.
Definition: adjointSensitivityIncompressible.C:73
Foam::solve
SolverPerformance< Type > solve(faMatrix< Type > &, Istream &)
Solve returning the solution statistics given convergence tolerance.
phi
surfaceScalarField & phi
Definition: setRegionFluidFields.H:8
Foam::objectRegistry::lookupObject
const Type & lookupObject(const word &name, const bool recursive=false) const
Definition: objectRegistryTemplates.C:434
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
Foam::adjointSolver::clearSensitivities
virtual void clearSensitivities()
Clears the sensitivity field known by the adjoint solver.
Definition: adjointSolver.C:160
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::dimensioned< scalar >
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:84
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::fvc::interpolate
static tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > interpolate(const GeometricField< Type, fvPatchField, volMesh > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
Foam::adjointSimple::solve
virtual void solve()
Main control loop.
Definition: adjointSimple.C:311
Foam::SIMPLEControl::New
static autoPtr< SIMPLEControl > New(fvMesh &mesh, const word &managerType, const solver &solver)
Return a reference to the selected turbulence model.
Definition: SIMPLEControl.C:64
globalContErr
scalar globalContErr
Definition: compressibleContinuityErrs.H:37
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::GeometricField::correctBoundaryConditions
void correctBoundaryConditions()
Correct boundary field.
Definition: GeometricField.C:909
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::adjointSimple::readDict
virtual bool readDict(const dictionary &dict)
Read dict if updated.
Definition: adjointSimple.C:160
Foam::tab
constexpr char tab
Definition: Ostream.H:371
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::solver::vars_
autoPtr< variablesSet > vars_
Base variableSet pointer.
Definition: solver.H:93
Foam::DimensionedField::weightedAverage
dimensioned< Type > weightedAverage(const DimensionedField< scalar, GeoMesh > &weightField) const
Calculate and return weighted average.
Definition: DimensionedField.C:461
Foam::GeometricField::boundaryFieldRef
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
Definition: GeometricField.C:752
Foam::incompressibleAdjoint::adjointRASModel::adjointMeanFlowSource
virtual tmp< volVectorField > adjointMeanFlowSource()=0
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
adjointSimple.H
Foam::incompressibleAdjointSolver::primalVars_
incompressibleVars & primalVars_
Primal variable set.
Definition: incompressibleAdjointSolver.H:77
Foam::GeometricField::relax
void relax(const scalar alpha)
Relax field (for steady-state solution).
Definition: GeometricField.C:941
Foam::fvMatrix
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Definition: fvPatchField.H:76
Foam::fvMatrix::solve
SolverPerformance< Type > solve(const dictionary &)
Solve returning the solution statistics.
Definition: fvMatrixSolve.C:298
Foam::Ostream::writeEntry
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:219
Foam::adjointSimple::writeData
virtual bool writeData(Ostream &os) const
Write average iteration.
Definition: adjointSimple.C:392
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::fvc::flux
tmp< surfaceScalarField > flux(const volVectorField &vvf)
Return the face-flux field obtained from the given volVectorField.
Definition: fvcFlux.C:34
Foam::GeometricField< scalar, fvsPatchField, surfaceMesh >
Foam::adjointSimple::getObjectiveSensitivities
virtual const scalarField & getObjectiveSensitivities()
Grab a reference to the computed sensitivities.
Definition: adjointSimple.C:355
Foam::sensitivity
Abstract base class for adjoint sensitivities.
Definition: sensitivity.H:63
Foam::fvm::div
tmp< fvMatrix< Type > > div(const surfaceScalarField &flux, const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvmDiv.C:48
Foam::incompressibleAdjointSolver::readDict
virtual bool readDict(const dictionary &dict)
Read dict if updated.
Definition: incompressibleAdjointSolver.C:109
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::adjointSimple::addExtraSchemes
void addExtraSchemes()
Definition: adjointSimple.C:68
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:294
constrainHbyA.H
Foam::fvMatrix::flux
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > flux() const
Return the face-flux field from the matrix.
Definition: fvMatrix.C:927
Foam::adjointSimple::loop
virtual bool loop()
Looper (advances iters, time step)
Definition: adjointSimple.C:330
Foam::adjointSimple::solverControl_
autoPtr< SIMPLEControl > solverControl_
Solver control.
Definition: adjointSimple.H:85
Foam::ATCModel::New
static autoPtr< ATCModel > New(const fvMesh &mesh, const incompressibleVars &primalVars, const incompressibleAdjointVars &adjointVars, const dictionary &dict)
Return a reference to the selected turbulence model.
Definition: ATCModel.C:129
Foam::adjointSimple::allocateVars
incompressibleAdjointVars & allocateVars()
Definition: adjointSimple.C:52
Foam::incompressibleAdjoint::adjointRASModel::divDevReff
virtual tmp< fvVectorMatrix > divDevReff(volVectorField &U) const =0
Return the diffusion term for the momentum equation.