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 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 "IFstream.H"
36 #include "stringOps.H"
37 #include "substitutionModel.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43 namespace functionObjects
44 {
45  defineTypeNameAndDebug(foamReport, 0);
47 }
48 }
49 
50 
51 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
52 
54 {
57  (
58  "OF_PROC_ZERO_DIR",
59  Pstream::parRun() ? "processor0" : ""
60  );
61 
67 
70 
73  substitutionModel::addBuiltinStr("OF_CASE_NAME", time().globalCaseName());
74 
76 
77  // Set mesh builtins when there is only 1 mesh
78  const auto meshes = time_.lookupClass<fvMesh>();
79  if (meshes.size() == 1)
80  {
81  const auto& mesh = *(meshes.begin().val());
82  substitutionModel::addBuiltin("OF_MESH_NCELLS", mesh.nCells());
83  substitutionModel::addBuiltin("OF_MESH_NFACES", mesh.nFaces());
84  substitutionModel::addBuiltin("OF_MESH_NEDGES", mesh.nEdges());
85  substitutionModel::addBuiltin("OF_MESH_NPOINTS", mesh.nPoints());
87  (
88  "OF_MESH_NINTERNALFACES",
89  mesh.nInternalFaces()
90  );
92  (
93  "OF_MESH_NBOUNDARYFACES",
94  mesh.nBoundaryFaces()
95  );
97  (
98  "OF_MESH_NPATCHES",
99  mesh.boundaryMesh().nNonProcessor()
100  );
102  (
103  "OF_MESH_BOUNDS_MIN",
104  mesh.bounds().min()
105  );
107  (
108  "OF_MESH_BOUNDS_MAX",
109  mesh.bounds().max()
110  );
111  }
112 }
113 
114 
116 {
117  // Overwrite existing entries
118  substitutionModel::setBuiltinStr("OF_TIME", time().timeName());
119  substitutionModel::setBuiltin("OF_NTIMES", time().times().size());
120  substitutionModel::setBuiltin("OF_TIME_INDEX", time().timeIndex());
121  substitutionModel::setBuiltin("OF_TIME_DELTAT", time().deltaTValue());
122 
125 
126  substitutionModel::setBuiltin("OF_NREGIONS", time().names<fvMesh>().size());
127  substitutionModel::setBuiltin("OF_NCLOUDS", time().names<cloud>().size());
128 }
129 
130 
132 {
133  Info<< " Reading template from " << fName << endl;
134 
135  IFstream is(fName);
136 
137  if (!is.good())
138  {
140  << "Unable to open file " << fName << endl;
141  }
142 
143  DynamicList<string> contents;
144  string buffer;
145 
146  label lineNo = 0;
147  while (is.good())
148  {
149  is.getLine(buffer);
150 
151  // Collect keys for this line and clean the buffer
152  const wordList keys(substitutionModel::getKeys(buffer));
153 
155 
156  // Assemble table of keyword and lines where the keyword appears
157  for (const word& key : keys)
158  {
159  if (modelKeys_.insert(key, nullValue))
160  {
161  // Set substitution model responsible for this keyword
162  label modeli = -1;
163  forAll(substitutions_, i)
164  {
165  if (substitutions_[i].valid(key))
166  {
167  modeli = i;
168  break;
169  }
170  }
171 
172  // Note: cannot check that key/model is set here
173  // - dynamic builtins not ready yet...
174 
175  modelKeys_[key].first() = modeli;
176  }
177 
178  DynamicList<label>& lineNos = modelKeys_[key].second();
179  lineNos.push_back(lineNo);
180  }
181 
182  contents.push_back(buffer);
183 
184  ++lineNo;
185  }
187  templateContents_.transfer(contents);
188 
189  return templateContents_.size() > 0;
190 }
191 
192 
194 {
195  List<string> out(templateContents_);
196 
197  forAllConstIters(modelKeys_, iter)
198  {
199  const word& key = iter.key();
200  const label modeli = iter.val().first();
201  const DynamicList<label>& lineNos = iter.val().second();
202 
203  DebugInfo<< "key:" << key << endl;
204 
205  for (const label linei : lineNos)
206  {
207  if (modeli == -1)
208  {
209  if (!substitutionModel::replaceBuiltin(key, out[linei]))
210  {
212  << "Unable to find substitution for " << key
213  << " on line " << linei << endl;
214  }
215  }
216  else
217  {
218  substitutions_[modeli].apply(key, out[linei]);
219  }
220  }
221  }
222 
223  for (const auto& line : out)
224  {
225  os << line.c_str() << nl;
226  }
227 
228  return true;
229 }
230 
231 
232 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
233 
235 (
236  const word& name,
237  const Time& runTime,
238  const dictionary& dict
239 )
240 :
242  writeFile(runTime, name, typeName, dict),
243  templateFile_(),
244  modelKeys_(),
245  substitutions_(),
246  debugKeys_(dict.getOrDefault<bool>("debugKeys", false))
247 {
248  read(dict);
251 }
252 
253 
254 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
255 
257 {
259  {
260  Info<< type() << " " << name() << ":" << nl;
261 
262  dict.readEntry("template", templateFile_);
263 
264  Info<< " Template: " << templateFile_ << endl;
265 
266  const word ext = templateFile_.ext();
267 
268  if (ext.size())
269  {
270  setExt("." + ext);
271  }
272  else
273  {
274  setExt(ext);
275  }
276 
277  Info<< " Reading substitutions" << endl;
278 
279  const dictionary& subsDict = dict.subDict("substitutions");
280 
281  substitutions_.resize(subsDict.size());
282 
283  label i = 0;
284  for (const entry& e : subsDict)
285  {
286  if (!e.isDict())
287  {
288  FatalIOErrorInFunction(subsDict)
289  << "Substitution models must be provided in dictionary "
290  << "format"
291  << exit(FatalIOError);
292  }
293 
294  substitutions_.set(i++, substitutionModel::New(e.dict(), time()));
295  }
296 
297  parseTemplate(templateFile_.expand());
298 
299  Info<< endl;
300 
301  return true;
302  }
303 
304  return false;
305 }
306 
307 
309 {
310  for (auto& sub : substitutions_)
311  {
312  sub.update();
313  }
314 
315  return true;
316 }
317 
318 
320 {
321  if (!Pstream::master()) return true;
322 
323  setDynamicBuiltins();
324 
325  auto filePtr = newFileAtTime(name(), time().value());
326  auto& os = filePtr();
327 
328  // Reset stream width (by default assumes fixed width tabular output)
329  os.width(0);
330 
331  // Perform the substitutions
332  apply(os);
333 
334  if (debugKeys_)
335  {
336  os << "Model keys:" << nl;
337  for (const auto& model : substitutions_)
338  {
339  os << model.type() << ":" << model.keys() << nl;
340  }
341 
342  os << "Builtins:" << nl;
344  }
345 
346  return true;
347 }
348 
349 
350 // ************************************************************************* //
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:124
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:608
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: stringOps.H:54
static autoPtr< substitutionModel > New(const dictionary &dict, const Time &time)
Return a reference to the selected substitution model.
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:531
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1061
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:249
Macros for easy insertion into run-time selection tables.
HashTable< const Type * > lookupClass() const
Return all objects with a class satisfying isA<Type> or isType<Type> (with Strict) ...
virtual bool execute()
Execute foamReport.
Definition: foamReport.C:301
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:421
void setStaticBuiltins()
Set static builtin entries.
Definition: foamReport.C:46
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:799
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:1077
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:186
static std::string clockTime()
The current wall-clock (in local time) as a string formatted as as (hh:mm:ss).
Definition: clock.C:88
string hostName()
Return the system&#39;s host name, as per hostname(1)
Definition: POSIX.C:371
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:108
#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:555
virtual bool write()
Write foamReport results.
Definition: foamReport.C:312
static word envExecutable()
Name of the executable from environment variable.
Definition: argList.C:645
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.
iterator begin()
Return iterator to begin traversal of non-nullptr entries.
Definition: UPtrListI.H:416
static fileName envGlobalPath()
Global case (directory) from environment variable.
Definition: argList.C:651
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:637
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:103
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:1094
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.