Loading...
Searching...
No Matches
caseInfo.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) 2023-2024 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
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 "caseInfo.H"
29#include "OFstream.H"
30#include "fvMesh.H"
31#include "cloud.H"
32#include "globalMeshData.H"
33#include "volFields.H"
34#include "surfaceFields.H"
35#include "processorFvPatch.H"
36#include "JSONformatter.H"
39// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41namespace Foam
42{
43namespace functionObjects
44{
46
48 (
52 );
53}
54
56Foam::functionObjects::caseInfo::writeFormatNames_
57{
58 { writeFormat::dict, "dictionary" },
59 { writeFormat::json, "json" },
60};
61
63Foam::functionObjects::caseInfo::lookupModeNames_
64{
65 { lookupMode::none, "none" },
66 { lookupMode::warn, "warn" },
67 { lookupMode::error, "error" },
68};
69}
70
71
72// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
73
74void Foam::functionObjects::caseInfo::report(const string& str) const
75{
76 switch (lookupMode_)
77 {
79 {
80 Warning << str.c_str() << endl;
81 break;
82 }
84 {
85 FatalError << str.c_str() << exit(FatalError);
86 break;
87 }
89 {
90 break;
91 }
92 }
93}
94
95
96void Foam::functionObjects::caseInfo::processDict
97(
99 const dictionary& targetDict,
100 const entry* includePtr,
101 const entry* excludePtr
102) const
103{
104 auto sanitise = [](const wordRe& w){
105 string str = w;
106 str.replaceAll("/", "_").replaceAll(".", "_");
107
108 // Strip any leading "_"
109 while (str.starts_with('_'))
110 {
111 str = str.substr(1);
112 }
113 return str;
114 };
115
116 if (includePtr)
117 {
118 const wordRes includeEntryNames(includePtr->stream());
119 for (const auto& nameRegex : includeEntryNames)
120 {
121 const auto* e = targetDict.findScoped(nameRegex, keyType::REGEX);
122 if (e)
123 {
124 if (nameRegex.contains('/') || nameRegex.contains('.'))
125 {
126 auto copyPtr = e->clone();
127 copyPtr->keyword() = sanitise(nameRegex);
128 dict.add(copyPtr.ptr());
129 }
130 else
131 {
132 dict.add(*e);
133 }
134 }
135 else
136 {
137 report
138 (
139 "Unable to find entry "
140 + nameRegex
141 + " in dictionary "
142 + targetDict.name()
143 );
144 }
145 }
146 }
147 else
148 {
149 if (excludePtr)
150 {
151 dictionary allData(targetDict);
152
153 const wordRes excludeEntryNames(excludePtr->stream());
154
155 for (const auto& nameRegex : excludeEntryNames)
156 {
157 const auto* e = allData.findScoped(nameRegex, keyType::REGEX);
158 if (e)
159 {
160 allData.remove(e->keyword());
161 }
162 }
163
164 dict += allData;
165 }
166 else
167 {
168 // Add complete dictionary
169 dict += targetDict;
171 }
172}
173
174
175// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
176
178{
179 out.add("case", time_.globalCaseName());
180 out.add("path", time_.globalPath());
181 out.add("regions", time_.sortedNames<fvMesh>());
182 out.add("nTimes", time_.times().size());
183 out.add("nProc", Pstream::nProcs());
184}
185
186
188(
189 const objectRegistry& obr,
190 dictionary& out,
191 dictionary& dictionaries
192) const
193{
194 for (const auto& e : dictionaries)
195 {
196 const auto& keyword = e.keyword();
197
198 if (!e.isDict())
199 {
200 FatalIOErrorInFunction(dictionaries)
201 << "Entries must be specified in dictionary format. Please "
202 << "correct entry " << keyword
203 << exit(FatalIOError);
204 }
205
206 const dictionary& inputDict = e.dict();
207
208 auto* includePtr = inputDict.findEntry("include");
209 auto* excludePtr = inputDict.findEntry("exclude");
210
211 const auto* ePtr = inputDict.findEntry("name");
212
213 if (ePtr)
214 {
215 const word name(ePtr->stream());
216 auto* dictPtr = obr.cfindObject<IOdictionary>(name);
217
218 if (dictPtr)
219 {
220 processDict
221 (
222 out.subDictOrAdd(keyword),
223 *dictPtr,
224 includePtr,
225 excludePtr
226 );
227 dictionaries.remove(keyword);
228 }
229 }
230 }
231}
232
233
235(
236 dictionary& out,
237 dictionary& dictionaries
238) const
239{
240 for (auto& e : dictionaries)
241 {
242 const auto& keyword = e.keyword();
243
244 if (!e.isDict())
245 {
246 FatalIOErrorInFunction(dictionaries)
247 << "Entries must be specified in dictionary format. Please "
248 << "correct entry " << keyword
249 << exit(FatalIOError);
250 }
251
252 const dictionary& inputDict = e.dict();
253
254 auto* includePtr = inputDict.findEntry("include");
255 auto* excludePtr = inputDict.findEntry("exclude");
256
257 const auto* ePtr = inputDict.findEntry("path");
258
259 if (ePtr)
260 {
261 fileName path(ePtr->stream());
262 path.expand();
263
264 IOobject io(path, time_, IOobject::MUST_READ);
265
266 if (!io.typeHeaderOk<dictionary>(false))
267 {
268 continue;
269 }
270
271 const word oldTypeName = IOdictionary::typeName;
272 const_cast<word&>(IOdictionary::typeName) = word::null;
273
274 processDict
275 (
276 out.subDictOrAdd(keyword),
277 IOdictionary(io),
278 includePtr,
279 excludePtr
280 );
281
282 const_cast<word&>(IOdictionary::typeName) = oldTypeName;
284 dictionaries.remove(keyword);
285 }
286 }
287}
288
289
291(
292 dictionary& out
293) const
294{
295 for (const auto& fo : functionObjectNames_)
296 {
298 if (getObjectResultDict(fo, dict))
299 {
300 out.add(fo, dict);
301 }
302 else
304 report("No result entries found for function object " + fo);
305 }
306 }
307}
308
309
311(
312 const polyMesh& mesh,
314) const
315{
316 dict.add("nGeometricD", mesh.nGeometricD());
317 dict.add("nSolutionD", mesh.nSolutionD());
318
319 const auto& globalData = mesh.globalData();
320
321 dict.add("nPoints", globalData.nTotalPoints());
322 dict.add("nFaces", globalData.nTotalFaces());
323 dict.add("nCells", globalData.nTotalCells());
324
325 dict.add("nPatches", mesh.boundaryMesh().nNonProcessor());
326
327 dict.add("pointZones", mesh.pointZones().names());
328 dict.add("faceZones", mesh.faceZones().names());
329 dict.add("cellZones", mesh.cellZones().names());
330
331 dict.add("boundsMin", mesh.bounds().min());
332 dict.add("boundsMax", mesh.bounds().max());
333
334 dict.add("clouds", mesh.sortedNames<cloud>());
335}
336
337
338namespace Foam
339{
340 template<class GeoFieldType>
341 void addPatchTypeDetails(const fvMesh& mesh, dictionary& dict)
342 {
343 for (const GeoFieldType& obj : mesh.csorted<GeoFieldType>())
344 {
345 if (obj.readOpt() == IOobject::MUST_READ)
346 {
347 const auto& bf = obj.boundaryField();
348 dictionary& objDict = dict.subDictOrAdd(obj.name());
349
350 for (const auto& pf : bf)
351 {
352 if (!isA<processorFvPatch>(pf.patch()))
353 {
354 objDict.add(pf.patch().name(), pf.type());
356 }
357 }
358 }
359 }
360
361 template<template<typename> class FieldType>
363 {
369 }
370}
371
372
374(
375 const fvMesh& mesh,
377) const
378{
379 // Geometry
380 dictionary& bnd = dict.subDictOrAdd("types");
381 const auto& pbm = mesh.boundaryMesh();
382 for (const auto& pp : pbm)
383 {
385 {
386 bnd.add(pp.name(), pp.type());
387 }
388 }
389
390 // Fields
391 dictionary& fld = dict.subDictOrAdd("fields");
392 addPatchDetails<VolumeField>(mesh, fld);
394 //addPatchDetails<AreaField>(mesh, fld);
395}
396
397
398// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
399
401(
402 const word& name,
403 const Time& runTime,
404 const dictionary& dict
405)
406:
408 (
410 (
411 name,
413 runTime,
414 IOobject::NO_READ,
415 IOobject::NO_WRITE
416 )
417 ),
420 writeFormat_(writeFormat::dict),
421 lookupMode_(lookupMode::warn)
423 read(dict);
424}
425
426
427// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
428
430{
432 {
433 writeFormatNames_.readIfPresent("writeFormat", dict, writeFormat_);
434 writeFile::setExt("." + writeFormatNames_[writeFormat_]);
435
436 lookupModeNames_.readIfPresent("lookupMode", dict, lookupMode_);
437
438 dictionaries_ = dict.subOrEmptyDict("dictionaries");
439
440 dict.readIfPresent("functionObjects", functionObjectNames_);
441
442 return true;
443 }
444
445 return false;
446}
447
450{
451 return true;
452}
453
454
456{
457 // Output dictionary
458 dictionary& data = *this;
459 data.clear();
460
461 // Case meta data
462 writeMeta(data.subDictOrAdd("meta"));
463
464 // Note: copying dictionaries
465 // - these are consumed/removed when found to enable checks that all
466 // dictionaries are processed
467 dictionary dicts(dictionaries_);
468
469 dictionary& dataDicts = data.subDictOrAdd("dictionaries");
470
471 // Time-registered dictionaries
472 writeRegisteredDicts(time_, dataDicts, dicts);
473
474 // File-based dictionaries
475 writeFileDicts(dataDicts, dicts);
476
477 // Per-region information
478 dictionary& regionDict = data.subDictOrAdd("regions");
479
480 for (const fvMesh& mesh : time_.csorted<fvMesh>())
481 {
482 dictionary meshDicts(dicts);
483
484 const word& name = mesh.name();
485
486 dictionary& out = regionDict.subDictOrAdd(name);
487
488 writeMeshStats(mesh, out.subDictOrAdd("mesh"));
489
490 writePatches(mesh, out.subDictOrAdd("boundary"));
491
492 // Mesh-registered dictionaries
493 writeRegisteredDicts(mesh, out.subDictOrAdd("dictionaries"), meshDicts);
494
495 for (const word& keyword : meshDicts.sortedToc())
496 {
497 report
498 (
499 "Mesh '"
500 + keyword
501 + "' : Unable to process dictionary entry '"
502 + keyword
503 + "'"
504 );
505 }
506 }
507
508
509 writeFunctionObjects(data.subDictOrAdd("functions"));
510
511
512 if (Pstream::master())
513 {
514 auto filePtr = newFileAtTime(functionObject::name(), time_.value());
515 auto& os = filePtr();
516
517 // Reset stream width - was set in writeFile
518 os.width(0);
519
520 switch (writeFormat_)
521 {
522 case writeFormat::dict:
523 {
524 IOdictionary::writeData(os);
525 break;
526 }
527 case writeFormat::json:
528 {
529 JSONformatter json(os);
530 json.writeDict(data);
531 break;
532 }
533 }
534
535 Info<< "Written " << writeFormatNames_[writeFormat_]
536 << " file: " << os.name() << endl;
537 }
538
539 return true;
540}
541
542
543// ************************************************************************* //
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
Info<< nl;Info<< "Write faMesh in vtk format:"<< nl;{ vtk::uindirectPatchWriter writer(aMesh.patch(), fileName(aMesh.time().globalPath()/vtkBaseFileName));writer.writeGeometry();globalIndex procAddr(aMesh.nFaces());labelList cellIDs;if(UPstream::master()) { cellIDs.resize(procAddr.totalSize());for(const labelRange &range :procAddr.ranges()) { auto slice=cellIDs.slice(range);slice=identity(range);} } writer.beginCellData(4);writer.writeProcIDs();writer.write("cellID", cellIDs);writer.write("area", aMesh.S().field());writer.write("normal", aMesh.faceAreaNormals());writer.beginPointData(1);writer.write("normal", aMesh.pointAreaNormals());Info<< " "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.time().globalPath()/(vtkBaseFileName+"-edges")));writer.writeGeometry();writer.beginCellData(4);writer.writeProcIDs();{ Field< scalar > fld(faMeshTools::flattenEdgeField(aMesh.magLe(), true))
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
const polyBoundaryMesh & pbm
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition Enum.H:57
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
IOdictionary(const IOobject &io, const dictionary *fallback=nullptr)
Construct given an IOobject and optional fallback dictionary content.
@ NO_READ
Nothing to be read.
@ MUST_READ
Reading required.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
fileName path() const
The complete path for the object (with instance, local,...).
Definition IOobject.C:500
An wrapper for Ostream that outputs content in JSON format.
virtual Ostream & writeDict(const dictionary &dict)
Write OpenFOAM dictionary to JSON dictionary.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition Time.H:75
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
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:1697
virtual bool writeData(Ostream &) const
The writeData function required by regIOobject write operation.
const word & name() const
Name function is needed to disambiguate those inherited from regIOobject and dictionary.
A cloud is a registry collection of lagrangian particles.
Definition cloud.H:56
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
dictionary & subDictOrAdd(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find and return a sub-dictionary for manipulation.
Definition dictionary.C:481
dictionary()
Default construct, a top-level empty dictionary.
Definition dictionary.C:68
const entry * findEntry(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition dictionaryI.H:84
bool remove(const word &keyword)
Remove an entry specified by keyword.
wordList sortedToc() const
Return the sorted table of contents.
Definition dictionary.C:601
void clear()
Clear the dictionary.
Definition dictionary.C:862
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition dictionary.C:625
A class for handling file names.
Definition fileName.H:75
Abstract base-class for Time/database function objects.
const word & name() const noexcept
Return the name of this functionObject.
virtual bool read(const dictionary &dict)
Read and set the function object if its data have changed.
Collects and writes case information to file.
Definition caseInfo.H:200
void writeRegisteredDicts(const objectRegistry &obr, dictionary &dict, dictionary &dictionaries) const
Write registered dictionaries.
Definition caseInfo.C:181
writeFormat
Write format enumeration.
Definition caseInfo.H:209
lookupMode
Lookup mode enumeration.
Definition caseInfo.H:218
void writeMeshStats(const polyMesh &mesh, dictionary &dict) const
Write mesh statistics.
Definition caseInfo.C:304
void writeMeta(dictionary &dict) const
Write case meta data.
Definition caseInfo.C:170
caseInfo(const caseInfo &)=delete
No copy construct.
virtual bool read(const dictionary &dict)
Read the function-object dictionary.
Definition caseInfo.C:422
void writeFunctionObjects(dictionary &dict) const
Write function object results.
Definition caseInfo.C:284
void writePatches(const fvMesh &mesh, dictionary &dict) const
Write mesh patches.
Definition caseInfo.C:367
virtual bool execute()
Execute the function-object operations (no-op).
Definition caseInfo.C:442
virtual bool write()
Write the function-object results.
Definition caseInfo.C:448
void writeFileDicts(dictionary &dict, dictionary &dictionaries) const
Write file-based dictionaries.
Definition caseInfo.C:228
virtual bool read()
Read object.
Base class for function objects, adding functionality to read/write state information (data required ...
stateFunctionObject(const stateFunctionObject &)=delete
No copy construct.
bool getObjectResultDict(const word &objectName, dictionary &dict) const
const Time & time_
Reference to the time database.
Base class for writing single files from the function objects.
Definition writeFile.H:113
writeFile(const objectRegistry &obr, const fileName &prefix, const word &name="undefined", const bool writeToFile=true, const string &ext=".dat")
Construct from objectRegistry, prefix, fileName.
Definition writeFile.C:200
virtual bool read(const dictionary &dict)
Read.
Definition writeFile.C:240
virtual autoPtr< OFstream > newFileAtTime(const word &name, scalar timeValue) const
Return autoPtr to a new file for a given time.
Definition writeFile.C:110
virtual const string & setExt(const string &ext)
Set extension.
Definition writeFile.C:263
Mesh data needed to do the Finite Volume discretisation.
Definition fvMesh.H:85
@ REGEX
Regular expression.
Definition keyType.H:83
Registry of regIOobjects.
const Type * cfindObject(const word &name, const bool recursive=false) const
Return const pointer to the object of the given Type.
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
string & replaceAll(const std::string &s1, const std::string &s2, size_type pos=0)
Replace all occurrences of sub-string s1 with s2, beginning at pos in the string.
Definition string.C:117
A class for handling words, derived from Foam::string.
Definition word.H:66
static const word null
An empty word.
Definition word.H:84
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
dynamicFvMesh & mesh
engineTime & runTime
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
OBJstream os(runTime.globalPath()/outputName)
const auto & io
auto & name
word timeName
Definition getTimeIndex.H:3
Function objects are OpenFOAM utilities to ease workflow configurations and enhance workflows.
Namespace for OpenFOAM.
messageStream Info
Information stream (stdout output on master, null elsewhere).
void addPatchTypeDetails(const fvMesh &mesh, dictionary &dict)
Definition caseInfo.C:334
const word GlobalIOList< Tuple2< scalar, vector > >::typeName("scalarVectorTable")
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
Definition typeInfo.H:87
void addPatchDetails(const fvMesh &mesh, dictionary &dict)
Definition caseInfo.C:355
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition exprTraits.C:127
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
messageStream Warning
Warning stream (stdout output on master, null elsewhere), with additional 'FOAM Warning' header text.
dictionary dict
volScalarField & e
Foam::surfaceFields.
autoPtr< OFstream > filePtr