objectiveManager.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-2021 PCOpt/NTUA
9  Copyright (C) 2013-2021 FOSS GP
10  Copyright (C) 2019-2021 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 "objectiveManager.H"
31 #include "IOmanip.H"
32 
33 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37 
38 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 
42 
43 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
44 
45 objectiveManager::objectiveManager
46 (
47  const fvMesh& mesh,
48  const dictionary& dict,
49  const word& adjointSolverName,
50  const word& primalSolverName
51 )
52 :
54  (
55  IOobject
56  (
57  "objectiveManager" + adjointSolverName,
58  mesh.time().system(),
59  mesh,
60  IOobject::NO_READ,
61  IOobject::NO_WRITE,
62  IOobject::REGISTER
63  )
64  ),
65  mesh_(mesh),
66  dict_(dict),
67  adjointSolverName_(adjointSolverName),
68  primalSolverName_(primalSolverName),
69  objectives_(0),
70  weigthedObjectiveFile_(nullptr)
71 {
72  // Construct objectives
73  //~~~~~~~~~~~~~~~~~~~~~
74  Info << "Constructing objective functions " << nl << endl;
75  const word objectiveType = dict.get<word>("type");
76  const dictionary& objectiveNamesDict(dict.subDict("objectiveNames"));
77  wordList objectiveNames(objectiveNamesDict.toc());
78  objectives_.setSize(objectiveNames.size());
79 
80  forAll(objectiveNames, objectivei)
81  {
82  const word& objectiveName = objectiveNames[objectivei];
83 
84  objectives_.set
85  (
86  objectivei,
88  (
89  mesh_,
90  objectiveNamesDict.subDict(objectiveName),
91  objectiveType,
94  )
95  );
96  }
97 
98  if (objectives_.empty())
99  {
100  FatalIOErrorInFunction(objectiveNamesDict)
101  << "No objectives have been set - cannot perform an optimisation"
102  << exit(FatalIOError);
103  }
104 
105  if (Pstream::master())
106  {
107  if (objectives_.size() > 1)
108  {
109  const Time& time = mesh_.time();
111  (
112  new OFstream
113  (
114  time.globalPath()/"optimisation"/"objective"
115  /time.timeName()/"weightedObjective"+adjointSolverName_
116  )
117  );
118 
119  unsigned int width = IOstream::defaultPrecision() + 5;
121  << setw(4) << "#" << " "
122  << setw(width) << "weightedObjective" << " ";
123  for (objective& objI : objectives_)
124  {
126  << setw(width) << objI.objectiveName() << " ";
127  }
129  << endl;
130  }
131  }
132 }
133 
134 
135 // * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
136 
137 autoPtr<objectiveManager> objectiveManager::New
138 (
139  const fvMesh& mesh,
140  const dictionary& dict,
141  const word& adjointSolverName,
142  const word& primalSolverName
143 )
144 {
145  // Determine type of objectiveManager from objectiveType
146  const word objectiveType(dict.get<word>("type"));
147  const word managerType("objectiveManager" & objectiveType);
148 
149  auto* ctorPtr = dictionaryConstructorTable(managerType);
150 
151  if (!ctorPtr)
152  {
154  (
155  dict,
156  "objectiveManagerType",
157  managerType,
158  *dictionaryConstructorTablePtr_
159  ) << exit(FatalIOError);
160  }
161 
162  return autoPtr<objectiveManager>
163  (
165  );
166 }
167 
168 
169 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
170 
172 {
173  for (objective& obj : objectives_)
174  {
175  obj.readDict
176  (
177  dict.subDict("objectiveNames").subDict(obj.objectiveName())
178  );
179  }
180 
181  return true;
182 }
183 
184 
186 {
187  // Update normalization factors for all objectives
188  for (objective& obj : objectives_)
189  {
190  if (obj.normalize())
191  {
192  obj.updateNormalizationFactor();
193  }
194  }
195 }
196 
197 
199 {
200  // Update all fields related to the objective function
201  for (objective& obj : objectives_)
202  {
203  obj.update();
204  }
205 }
206 
207 
209 {
210  // Update contributions to adjoint if true, otherwise return nulls
211  for (objective& obj : objectives_)
212  {
213  if (obj.isWithinIntegrationTime())
214  {
215  obj.update();
216  }
217  else
218  {
219  obj.nullify();
220  }
221  }
222 }
223 
224 
225 void objectiveManager::incrementIntegrationTimes(const scalar timeSpan)
226 {
227  // Update start and end integration times by adding the timeSpan
228  // of the optimisation cycle
229  for (objective& obj : objectives_)
230  {
231  obj.incrementIntegrationTimes(timeSpan);
232  }
233 }
234 
235 
237 {
238  scalar objValue(Zero);
239  Info<< "Adjoint solver " << adjointSolverName_ << endl;
240  for (objective& obj : objectives_)
241  {
242  scalar cost = obj.JCycle();
243  scalar weight = obj.weight();
244  objValue += weight*cost;
245 
246  Info<< obj.objectiveName() << " : " << cost << endl;
247  }
248 
249  Info<< "Weighted objective : " << objValue << nl << endl;
250 
251  return objValue;
252 }
253 
254 
256 (
257  const scalar weightedObjective,
258  const bool valid
259 )
260 {
261  for (const objective& obj : objectives_)
262  {
263  // Write objective function to file
264  obj.write();
265  obj.writeMeanValue();
266  }
267 
268  if (weigthedObjectiveFile_.valid())
269  {
270  unsigned int width = IOstream::defaultPrecision() + 5;
272  << setw(4) << mesh_.time().timeName() << " "
273  << setw(width) << weightedObjective << " ";
274 
275  for (objective& objI : objectives_)
276  {
278  << setw(width) << objI.JCycle() << " ";
279  }
281  }
282 
283  return true;
284 }
285 
286 
288 {
290  update();
291  scalar weightedObjective = print();
292  writeObjectives(weightedObjective);
293 }
294 
297 {
298  return objectives_;
299 }
300 
303 {
304  return objectives_;
305 }
306 
309 {
310  return adjointSolverName_;
311 }
312 
315 {
316  return primalSolverName_;
317 }
318 
319 
321 {
322  for (const objective& obj : objectives_)
323  {
324  if (!obj.hasIntegrationStartTime() || !obj.hasIntegrationEndTime())
325  {
327  << "Objective function " << obj.objectiveName()
328  << " does not have a defined integration start or end time "
329  << exit(FatalError);
330  }
331  }
332 }
333 
334 
335 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
336 
337 } // End namespace Foam
338 
339 // ************************************************************************* //
dictionary dict
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:120
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
PtrList< objective > & getObjectiveFunctions()
Return reference to objective functions.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
class for managing incompressible objective functions.
autoPtr< OFstream > weigthedObjectiveFile_
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
static unsigned int defaultPrecision() noexcept
Return the default precision.
Definition: IOstream.H:423
virtual bool writeObjectives(const scalar weightedObjective, const bool valid=true)
Write objective function history.
void incrementIntegrationTimes(const scalar timeSpan)
Increment integration times by the optimisation cycle time-span.
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:362
void updateAndWrite()
Call all functions required prior to the solution of the adjoint equations.
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:453
PtrList< objective > objectives_
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:414
static autoPtr< objective > New(const fvMesh &mesh, const dictionary &dict, const word &objectiveType, const word &adjointSolverName, const word &primalSolverName)
Return a reference to the selected turbulence model.
Definition: objective.C:198
void updateNormalizationFactor()
Update objective function related values.
dynamicFvMesh & mesh
A class for handling words, derived from Foam::string.
Definition: word.H:63
static autoPtr< objectiveManager > New(const fvMesh &mesh, const dictionary &dict, const word &adjointSolverName, const word &primalSolverName)
Return a reference to the selected turbulence model.
const word & primalSolverName() const
Return name of the primalSolver.
const Time & time() const noexcept
Return Time associated with the objectRegistry.
Definition: IOobject.C:431
Istream and Ostream manipulators taking arguments.
Abstract base class for objective functions. No point in making this runTime selectable since its chi...
Definition: objective.H:55
static word timeName(const scalar t, const int precision=precision_)
Return time name of given scalar time formatted with the given precision.
Definition: Time.C:770
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
scalar print()
Print to screen.
defineTypeNameAndDebug(combustionModel, 0)
void update()
Update objective function related values.
const word & adjointSolverName() const
Return name of the adjointSolver.
virtual bool readDict(const dictionary &dict)
void updateOrNullify()
Update contributions to adjoint if true, otherwise return nulls.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:607
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:79
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1037
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:65
messageStream Info
Information stream (stdout output on master, null elsewhere)
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
int system(const std::string &command, const bool bg=false)
Execute the specified command via the shell.
Definition: POSIX.C:1702
void checkIntegrationTimes() const
Check integration times for unsteady runs.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:171
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
Definition: error.H:615
Namespace for OpenFOAM.
fileName globalPath() const
Return global path for the case.
Definition: TimePathsI.H:73
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:133