foamReport.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) 2024-2025 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "foamReport.H"
30 #include "argList.H"
31 #include "clock.H"
32 #include "cloud.H"
33 #include "foamVersion.H"
34 #include "fvMesh.H"
35 #include "globalMeshData.H"
36 #include "IFstream.H"
37 #include "stringOps.H"
38 #include "substitutionModel.H"
39 
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
44 namespace functionObjects
45 {
46  defineTypeNameAndDebug(foamReport, 0);
48 }
49 }
50 
51 
52 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
53 
55 {
58  (
59  "OF_PROC_ZERO_DIR",
60  UPstream::parRun() ? "processor0" : ""
61  );
62 
68 
71 
74  substitutionModel::addBuiltinStr("OF_CASE_NAME", time().globalCaseName());
75 
77 
78  // Set mesh builtins when there is only 1 mesh
79  const auto meshes = time_.csorted<fvMesh>();
80 
81  if (meshes.size() == 1)
82  {
83  const auto& mesh = meshes[0];
84 
86  (
87  "OF_MESH_NCELLS",
88  mesh.globalData().nTotalCells()
89  );
91  (
92  "OF_MESH_NFACES",
93  mesh.globalData().nTotalFaces()
94  );
96  (
97  "OF_MESH_NEDGES",
98  returnReduce(mesh.nEdges(), sumOp<label>())
99  );
101  (
102  "OF_MESH_NPOINTS",
103  mesh.globalData().nTotalPoints()
104  );
106  (
107  "OF_MESH_NINTERNALFACES",
108  returnReduce(mesh.nInternalFaces(), sumOp<label>())
109  );
111  (
112  "OF_MESH_NBOUNDARYFACES",
113  // TBD: use mesh.boundaryMesh().nNonProcessorFaces() ?
114  returnReduce(mesh.nBoundaryFaces(), sumOp<label>())
115  );
117  (
118  "OF_MESH_NPATCHES",
119  mesh.boundaryMesh().nNonProcessor()
120  );
122  (
123  "OF_MESH_BOUNDS_MIN",
124  mesh.bounds().min()
125  );
127  (
128  "OF_MESH_BOUNDS_MAX",
129  mesh.bounds().max()
130  );
131  }
132 }
133 
134 
136 {
137  // Overwrite existing entries
138  substitutionModel::setBuiltinStr("OF_TIME", time().timeName());
139  substitutionModel::setBuiltin("OF_NTIMES", time().times().size());
140  substitutionModel::setBuiltin("OF_TIME_INDEX", time().timeIndex());
141  substitutionModel::setBuiltin("OF_TIME_DELTAT", time().deltaTValue());
142 
145 
146  substitutionModel::setBuiltin("OF_NREGIONS", time().count<fvMesh>());
147  substitutionModel::setBuiltin("OF_NCLOUDS", time().count<cloud>());
148 }
149 
150 
152 {
153  Info<< " Reading template from " << fName << endl;
154 
155  IFstream is(fName);
156 
157  if (!is.good())
158  {
160  << "Unable to open file " << fName << endl;
161  }
162 
163  DynamicList<string> contents;
164  string buffer;
165 
166  label lineNo = 0;
167  while (is.good())
168  {
169  is.getLine(buffer);
170 
171  // Collect keys for this line and clean the buffer
172  const wordList keys(substitutionModel::getKeys(buffer));
173 
175 
176  // Assemble table of keyword and lines where the keyword appears
177  for (const word& key : keys)
178  {
179  if (modelKeys_.insert(key, nullValue))
180  {
181  // Set substitution model responsible for this keyword
182  label modeli = -1;
183  forAll(substitutions_, i)
184  {
185  if (substitutions_[i].valid(key))
186  {
187  modeli = i;
188  break;
189  }
190  }
191 
192  // Note: cannot check that key/model is set here
193  // - dynamic builtins not ready yet...
194 
195  modelKeys_[key].first() = modeli;
196  }
197 
198  DynamicList<label>& lineNos = modelKeys_[key].second();
199  lineNos.push_back(lineNo);
200  }
201 
202  contents.push_back(buffer);
203 
204  ++lineNo;
205  }
207  templateContents_.transfer(contents);
208 
209  return templateContents_.size() > 0;
210 }
211 
212 
214 {
215  List<string> out(templateContents_);
216 
217  forAllConstIters(modelKeys_, iter)
218  {
219  const word& key = iter.key();
220  const label modeli = iter.val().first();
221  const DynamicList<label>& lineNos = iter.val().second();
222 
223  DebugInfo<< "key:" << key << endl;
224 
225  for (const label linei : lineNos)
226  {
227  if (modeli == -1)
228  {
229  if (!substitutionModel::replaceBuiltin(key, out[linei]))
230  {
232  << "Unable to find substitution for " << key
233  << " on line " << linei << endl;
234  }
235  }
236  else
237  {
238  substitutions_[modeli].apply(key, out[linei]);
239  }
240  }
241  }
242 
243  for (const auto& line : out)
244  {
245  os << line.c_str() << nl;
246  }
247 
248  return true;
249 }
250 
251 
252 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
253 
255 (
256  const word& name,
257  const Time& runTime,
258  const dictionary& dict
259 )
260 :
262  writeFile(runTime, name, typeName, dict),
263  templateFile_(),
264  modelKeys_(),
265  substitutions_(),
266  debugKeys_(dict.getOrDefault<bool>("debugKeys", false))
267 {
268  read(dict);
271 }
272 
273 
274 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
275 
277 {
279  {
280  Info<< type() << " " << name() << ":" << nl;
281 
282  dict.readEntry("template", templateFile_);
283 
284  Info<< " Template: " << templateFile_ << endl;
285 
286  const word ext = templateFile_.ext();
287 
288  if (ext.size())
289  {
290  setExt("." + ext);
291  }
292  else
293  {
294  setExt(ext);
295  }
296 
297  Info<< " Reading substitutions" << endl;
298 
299  const dictionary& subsDict = dict.subDict("substitutions");
300 
301  substitutions_.resize(subsDict.size());
302 
303  label i = 0;
304  for (const entry& e : subsDict)
305  {
306  if (!e.isDict())
307  {
308  FatalIOErrorInFunction(subsDict)
309  << "Substitution models must be provided in dictionary "
310  << "format"
311  << exit(FatalIOError);
312  }
313 
314  substitutions_.set(i++, substitutionModel::New(e.dict(), time()));
315  }
316 
317  parseTemplate(templateFile_.expand());
318 
319  Info<< endl;
320 
321  return true;
322  }
323 
324  return false;
325 }
326 
327 
329 {
330  for (auto& sub : substitutions_)
331  {
332  sub.update();
333  }
334 
335  return true;
336 }
337 
338 
340 {
341  if (!Pstream::master()) return true;
342 
343  setDynamicBuiltins();
344 
345  auto filePtr = newFileAtTime(name(), time().value());
346  auto& os = filePtr();
347 
348  // Reset stream width (by default assumes fixed width tabular output)
349  os.width(0);
350 
351  // Perform the substitutions
352  apply(os);
353 
354  if (debugKeys_)
355  {
356  os << "Model keys:" << nl;
357  for (const auto& model : substitutions_)
358  {
359  os << model.type() << ":" << model.keys() << nl;
360  }
361 
362  os << "Builtins:" << nl;
364  }
365 
366  return true;
367 }
368 
369 
370 // ************************************************************************* //
static bool replaceBuiltin(const word &key, string &str)
Replace key in string.
bool parseTemplate(const fileName &fName)
Parse the template and collect keyword information.
Definition: foamReport.C:144
dictionary dict
defineTypeNameAndDebug(ObukhovLength, 0)
A line primitive.
Definition: line.H:52
A class for handling file names.
Definition: fileName.H:72
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: stringOps.H:56
static autoPtr< substitutionModel > New(const dictionary &dict, const Time &time)
Return a reference to the selected substitution model.
UPtrList< const Type > csorted() const
Return sorted list of objects with a class satisfying isA<Type> or isType<Type> (with Strict) ...
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
static void setBuiltin(const word &key, const Type &value)
Set a builtin to the hash table.
static void apply(bitSet &selection, const Detail::parcelSelection::actionType action, const Predicate &accept, const UList< Type > &list, const AccessOp &aop)
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1586
static void setBuiltinStr(const word &key, const string &value)
Set a builtin to the hash table.
Abstract base-class for Time/database function objects.
static std::string date()
The current wall-clock date as a string formatted as (MON dd yyyy), where MON is Jan, Feb, etc.
Definition: clock.C:73
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
virtual bool read(const dictionary &)
Read foamReport settings.
Definition: foamReport.C:269
Macros for easy insertion into run-time selection tables.
virtual bool execute()
Execute foamReport.
Definition: foamReport.C:321
static void addBuiltinStr(const word &key, const string &value)
Add a builtin to the hash table - does not overwrite.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
void setStaticBuiltins()
Set static builtin entries.
Definition: foamReport.C:47
word ext() const
Return file name extension (part after last .)
Definition: wordI.H:171
autoPtr< OFstream > filePtr
Definition: createFields.H:37
word timeName
Definition: getTimeIndex.H:3
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:801
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1602
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
A class for handling words, derived from Foam::string.
Definition: word.H:63
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
bool apply(Ostream &os) const
Apply the substitution models to the template.
Definition: foamReport.C:206
T returnReduce(const T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
static std::string clockTime()
The current wall-clock (in local time) as a string formatted as as (hh:mm:ss).
Definition: clock.C:88
auto key(const Type &t) -> std::enable_if_t< std::is_enum_v< Type >, std::underlying_type_t< Type > >
Definition: foamGltfBase.H:103
string hostName()
Return the system&#39;s host name, as per hostname(1)
Definition: POSIX.C:373
const int api
OpenFOAM api number (integer) corresponding to the value of OPENFOAM at the time of compilation...
void setDynamicBuiltins()
Set dynamic (potentially changing per execution step) builtin entries.
Definition: foamReport.C:128
#define DebugInfo
Report an information message using Foam::Info.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
OBJstream os(runTime.globalPath()/outputName)
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary)
Input from file stream as an ISstream, normally using std::ifstream for the actual input...
Definition: IFstream.H:51
void push_back(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:558
virtual bool write()
Write foamReport results.
Definition: foamReport.C:332
static word envExecutable()
Name of the executable from environment variable.
Definition: argList.C:661
const std::string buildArch
OpenFOAM build architecture information (machine endian, label/scalar sizes) as a std::string...
const std::string version
OpenFOAM version (name or stringified number) as a std::string.
static void writeBuiltins(Ostream &os)
Write all builtins to stream.
static fileName envGlobalPath()
Global case (directory) from environment variable.
Definition: argList.C:667
static wordList getKeys(string &buffer)
Return all keys from a string buffer.
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:629
virtual bool read(const dictionary &dict)
Read and set the function object if its data have changed.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1619
const std::string patch
OpenFOAM patch number as a std::string.
Replaces user-supplied keywords by run-time computed values in a text file.
Definition: foamReport.H:222
Base class for function objects, adding functionality to read/write state information (data required ...
messageStream Info
Information stream (stdout output on master, null elsewhere)
static void addBuiltin(const word &key, const Type &value)
Add a builtin to the hash table - does not overwrite.
const Time & time() const
Return time database.
const std::string build
OpenFOAM build information as a std::string.
foamReport(const foamReport &)=delete
No copy construct.
Base class for writing single files from the function objects.
Definition: writeFile.H:112
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
label timeIndex
Definition: getTimeIndex.H:24
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
const Time & time_
Reference to the time database.