adjointSolverManager.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-2020 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 "adjointSolverManager.H"
31 
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36  defineTypeNameAndDebug(adjointSolverManager, 0);
37 }
38 
39 
40 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
41 
42 Foam::adjointSolverManager::adjointSolverManager
43 (
44  fvMesh& mesh,
45  const word& managerType,
46  const dictionary& dict
47 )
48 :
50  (
51  IOobject
52  (
53  "adjointSolverManager" + dict.dictName(),
54  mesh.time().system(),
55  mesh,
56  IOobject::NO_READ,
57  IOobject::NO_WRITE,
58  true //register object
59  )
60  ),
61  mesh_(mesh),
62  dict_(dict),
63  managerName_(dict.dictName()),
64  primalSolverName_(dict.get<word>("primalSolver")),
65  adjointSolvers_(0),
66  objectiveSolverIDs_(0),
67  constraintSolverIDs_(0),
68  operatingPointWeight_
69  (
70  dict.getOrDefault<scalar>("operatingPointWeight", 1)
71  )
72 {
73  const dictionary& adjointSolversDict = dict.subDict("adjointSolvers");
74 
75  const wordList adjSolverNames = adjointSolversDict.toc();
76  adjointSolvers_.setSize(adjSolverNames.size());
77  objectiveSolverIDs_.setSize(adjSolverNames.size());
78  constraintSolverIDs_.setSize(adjSolverNames.size());
79  label nObjectives(0);
80  label nConstraints(0);
81  forAll(adjSolverNames, namei)
82  {
83  adjointSolvers_.set
84  (
85  namei,
87  (
88  mesh_,
89  managerType,
90  adjointSolversDict.subDict(adjSolverNames[namei]),
91  primalSolverName_
92  )
93  );
94 
95  if (adjointSolvers_[namei].isConstraint())
96  {
97  constraintSolverIDs_[nConstraints++] = namei;
98  }
99  else
100  {
101  objectiveSolverIDs_[nObjectives++] = namei;
102  }
103  }
104  objectiveSolverIDs_.setSize(nObjectives);
105  constraintSolverIDs_.setSize(nConstraints);
106 
107  Info<< "Found " << nConstraints
108  << " adjoint solvers acting as constraints" << endl;
109 
110  // Having more than one non-aggregated objectives per operating point
111  // is needlessly expensive. Issue a warning
112  if (objectiveSolverIDs_.size() > 1)
113  {
115  << "Number of adjoint solvers corresponding to objectives "
116  << "is greater than 1 (" << objectiveSolverIDs_.size() << ")" << nl
117  << "Consider aggregating your objectives to one" << endl;
118  }
119 }
120 
121 
122 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
123 
125 {
126  dict_ = dict;
127 
128  const dictionary& adjointSolversDict = dict.subDict("adjointSolvers");
129 
130  // Note: only updating existing solvers
132  {
133  solver.readDict(adjointSolversDict.subDict(solver.name()));
134  }
135 
136  return true;
137 }
138 
139 
141 {
142  return managerName_;
143 }
144 
145 
147 {
148  return primalSolverName_;
149 }
150 
151 
153 {
154  return dict_;
155 }
156 
157 
160 {
161  return adjointSolvers_;
162 }
163 
164 
167 {
168  return adjointSolvers_;
169 }
170 
171 
173 {
174  return operatingPointWeight_;
175 }
176 
177 
179 {
180  return constraintSolverIDs_.size();
181 }
182 
183 
185 {
186  return objectiveSolverIDs_.size();
187 }
188 
189 
191 {
192  return nConstraints() + nObjectives();
193 }
194 
195 
197 {
198  for (adjointSolver& solver : adjointSolvers_)
199  {
200  // Solve the adjoint equations taking into consideration the weighted
201  // contribution of possibly multiple objectives
202  solver.solve();
203  }
204 }
205 
206 
209 {
210  tmp<scalarField> tsens(new scalarField(0));
211  scalarField& sens = tsens.ref();
212 
213  // Sum sensitivities from all objectives expect the constraints
214  for (const label solveri : objectiveSolverIDs_)
215  {
216  // Sum contributions
217  const scalarField& solverSens =
218  adjointSolvers_[solveri].getObjectiveSensitivities();
219 
220  if (sens.empty())
221  {
222  sens = scalarField(solverSens.size(), Zero);
223  }
224  sens += solverSens;
225  }
226 
227  return tsens;
228 }
229 
230 
233 {
234  PtrList<scalarField> constraintSens(constraintSolverIDs_.size());
235  forAll(constraintSens, cI)
236  {
237  label consI = constraintSolverIDs_[cI];
238  constraintSens.set
239  (
240  cI,
241  new scalarField(adjointSolvers_[consI].getObjectiveSensitivities())
242  );
243  }
244 
245  return constraintSens;
246 }
247 
248 
250 {
251  for (adjointSolver& adjSolver : adjointSolvers_)
252  {
253  adjSolver.computeObjectiveSensitivities();
254  }
255 }
256 
257 
259 {
260  for (adjointSolver& adjSolver : adjointSolvers_)
261  {
262  adjSolver.clearSensitivities();
263  }
264 }
265 
266 
268 {
269  scalar objValue(Zero);
270  for (const label solveri : objectiveSolverIDs_)
271  {
272  objectiveManager& objManager =
273  adjointSolvers_[solveri].getObjectiveManager();
274  objValue += objManager.print();
275  }
276 
277  return objValue;
278 }
279 
280 
282 {
283  tmp<scalarField> tconstraintValues
284  (
285  new scalarField(constraintSolverIDs_.size(), Zero)
286  );
287  scalarField& constraintValues = tconstraintValues.ref();
288  forAll(constraintValues, cI)
289  {
290  objectiveManager& objManager =
291  adjointSolvers_[constraintSolverIDs_[cI]].getObjectiveManager();
292  constraintValues[cI] = objManager.print();
293  }
294 
295  return tconstraintValues;
296 }
297 
298 
300 {
301  if (primalSolverName_ == name)
302  {
303  for (adjointSolver& solver : adjointSolvers_)
304  {
305  solver.updatePrimalBasedQuantities();
306  }
307  }
308 }
309 
310 
311 // ************************************************************************* //
Foam::adjointSolver
Base class for adjoint solvers.
Definition: adjointSolver.H:57
Foam::adjointSolverManager::adjointSolvers_
PtrList< adjointSolver > adjointSolvers_
Definition: adjointSolverManager.H:81
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:52
Foam::objectiveManager
class for managing incompressible objective functions.
Definition: objectiveManager.H:54
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::adjointSolverManager::nConstraints
label nConstraints() const
Number of adjoint solvers corresponding to constraints.
Definition: adjointSolverManager.C:178
Foam::adjointSolverManager::nObjectives
label nObjectives() const
Number of adjoint solvers corresponding to objectives.
Definition: adjointSolverManager.C:184
Foam::solver::solve
virtual void solve()=0
Main control loop.
Foam::adjointSolverManager::operatingPointWeight
scalar operatingPointWeight() const
Const access to adjoint solvers.
Definition: adjointSolverManager.C:172
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::adjointSolverManager::constraintSensitivities
virtual PtrList< scalarField > constraintSensitivities()
Get constraint sensitivities. One scalarField per constraint.
Definition: adjointSolverManager.C:232
Foam::adjointSolverManager::clearSensitivities
void clearSensitivities()
Clear sensitivity fields from all adjoint solvers.
Definition: adjointSolverManager.C:258
Foam::objectiveManager::print
scalar print()
Print to screen.
Definition: objectiveManager.C:236
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::adjointSolverManager::nAdjointSolvers
label nAdjointSolvers() const
Total number of adjoint solvers.
Definition: adjointSolverManager.C:190
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::adjointSolverManager::aggregateSensitivities
virtual tmp< scalarField > aggregateSensitivities()
Aggregate sensitivities from various adjoint solvers.
Definition: adjointSolverManager.C:208
Foam::baseIOdictionary::name
const word & name() const
Definition: baseIOdictionary.C:85
adjointSolverManager.H
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::adjointSolverManager::readDict
virtual bool readDict(const dictionary &dict)
Definition: adjointSolverManager.C:124
Foam::tmp::ref
T & ref() const
Definition: tmpI.H:227
Foam::adjointSolverManager::constraintValues
virtual tmp< scalarField > constraintValues()
Get constraint values.
Definition: adjointSolverManager.C:281
Foam::Field< scalar >
Foam::solver
Base class for solution control classes.
Definition: solver.H:51
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
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:460
Foam::PtrList< Foam::adjointSolver >
Foam::adjointSolverManager::computeAllSensitivities
void computeAllSensitivities()
Definition: adjointSolverManager.C:249
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::adjointSolverManager::dict
const dictionary & dict() const
Const access to the construction dictionary.
Definition: adjointSolverManager.C:152
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::adjointSolverManager::dict_
dictionary dict_
Definition: adjointSolverManager.H:75
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:85
Foam::adjointSolverManager::adjointSolvers
const PtrList< adjointSolver > & adjointSolvers() const
Const access to adjoint solvers.
Definition: adjointSolverManager.C:159
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::adjointSolverManager::managerName
const word & managerName() const
Const access to the manager name.
Definition: adjointSolverManager.C:140
Foam::adjointSolverManager::objectiveValue
scalar objectiveValue()
Get objective value.
Definition: adjointSolverManager.C:267
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
Foam::adjointSolverManager::solveAdjointEquations
virtual void solveAdjointEquations()
Definition: adjointSolverManager.C:196
Foam::regIOobject
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:73
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::adjointSolverManager::primalSolverName
const word & primalSolverName() const
Const access to the primal solver name.
Definition: adjointSolverManager.C:146
Foam::List< word >
Foam::adjointSolverManager::updatePrimalBasedQuantities
void updatePrimalBasedQuantities(const word &name)
Update fields related to primal solution.
Definition: adjointSolverManager.C:299
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::solver::readDict
virtual bool readDict(const dictionary &dict)
Definition: solver.C:82
Foam::dictionary::toc
wordList toc() const
Return the table of contents.
Definition: dictionary.C:602
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328