foamToEnsight.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2016-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Application
28  foamToEnsight
29 
30 Group
31  grpPostProcessingUtilitie
32 
33 Description
34  Translate OpenFOAM data to EnSight format.
35  An Ensight part is created for cellZones (unzoned cells are "internalMesh")
36  and patches.
37 
38  - Handles volume fields, dimensioned fields, point fields
39  - Handles mesh topology changes.
40 
41 Usage
42  \b foamToEnsight [OPTION]
43 
44  Options:
45  - \par -ascii
46  Write Ensight data in ASCII format instead of "C Binary"
47 
48  - \par -fields <fields>
49  Specify single or multiple fields to write (all by default)
50  For example,
51  \verbatim
52  -fields T
53  -fields '(p T U \"alpha.*\")'
54  \endverbatim
55  The quoting is required to avoid shell expansions and to pass the
56  information as a single argument.
57 
58  - \par -nearCellValue
59  Use zero-gradient cell values on patches
60 
61  - \par -nodeValues
62  Force interpolation of values to nodes
63 
64  - \par -no-boundary
65  Suppress output for all boundary patches
66 
67  - \par -no-internal
68  Suppress output for internal (volume) mesh
69 
70  - \par -no-cellZones
71  Suppress cellZone handling
72 
73  - \par -no-lagrangian
74  Suppress writing lagrangian positions and fields.
75 
76  - \par -no-mesh
77  Suppress writing the geometry. Can be useful for converting partial
78  results for a static geometry.
79 
80  - \par -no-point-data
81  Suppress conversion of pointFields. No interpolated PointData.
82 
83  - \par -noZero
84  Exclude the often incomplete initial conditions.
85 
86  - \par -index <start>
87  Use consecutive indexing for \c data/######## files with the
88  specified start index.
89  Ignore the time index contained in the uniform/time file.
90 
91  - \par -name <subdir>
92  Define sub-directory name to use for Ensight data (default: "EnSight")
93 
94  - \par -width <n>
95  Width of Ensight data subdir (default: 8)
96 
97  - \par -cellZones NAME | LIST
98  Specify single zone or multiple cell zones (name or regex) to write
99 
100  - \par -faceZones NAME | LIST
101  Specify single zone or multiple face zones (name or regex) to write
102 
103  - \par -patches NAME | LIST
104  Specify single patch or multiple patches (name or regex) to write
105  For example,
106  \verbatim
107  -patches top
108  -patches '( front \".*back\" )'
109  \endverbatim
110 
111  - \par -exclude-patches NAME | LIST
112  Exclude single or multiple patches (name or regex) from writing.
113  For example,
114  \verbatim
115  -exclude-patches '( inlet_1 inlet_2 "proc.*" )'
116  \endverbatim
117 
118 \*---------------------------------------------------------------------------*/
119 
120 #include "argList.H"
121 #include "timeSelector.H"
122 #include "IOobjectList.H"
123 #include "IOmanip.H"
124 #include "OFstream.H"
125 #include "Pstream.H"
126 #include "HashOps.H"
127 #include "regionProperties.H"
128 
129 #include "fvc.H"
130 #include "fvMesh.H"
131 #include "fieldTypes.H"
132 #include "volFields.H"
133 #include "scalarIOField.H"
134 #include "vectorIOField.H"
135 
136 // file-format/conversion
137 #include "ensightCase.H"
138 #include "ensightGeoFile.H"
139 #include "ensightFaMesh.H"
140 #include "ensightMesh.H"
141 #include "ensightOutputCloud.H"
142 #include "ensightOutputAreaField.H"
143 #include "ensightOutputVolField.H"
144 
145 // local files
146 #include "readFields.H"
147 #include "writeVolFields.H"
148 #include "writeDimFields.H"
149 #include "writePointFields.H"
150 #include "writeAreaFields.H"
151 
152 #include "memInfo.H"
153 
154 #undef foamToEnsight_useTimeIndex
155 
156 using namespace Foam;
157 
158 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
159 
160 int main(int argc, char *argv[])
161 {
163  (
164  "Translate OpenFOAM data to Ensight format with individual parts"
165  " for cellZones, unzoned cells and patches"
166  );
168 
169  // Less frequently used - reduce some clutter
170  argList::setAdvanced("decomposeParDict");
171 
172  argList::addVerboseOption("Additional verbosity");
173 
174  #include "addAllRegionOptions.H"
175 
177  (
178  "ascii",
179  "Write in ASCII format instead of 'C Binary'"
180  );
182  (
183  "index",
184  "start",
185  "Starting index for consecutive number of Ensight data/ files."
186  " Ignore the time index contained in the uniform/time file."
187  , true // mark as an advanced option
188  );
190  (
191  "name",
192  "subdir",
193  "Sub-directory name for Ensight output (default: 'EnSight')"
194  );
196  (
197  "no-overwrite",
198  "Suppress removal of existing EnSight output directory"
199  );
201  (
202  "width",
203  "n",
204  "Width of Ensight data subdir"
205  );
207  (
208  "nearCellValue",
209  "Use zero-gradient cell values on patches"
210  , true // mark as an advanced option
211  );
213  (
214  "nodeValues",
215  "Force interpolation of values to nodes"
216  , true // mark as an advanced option
217  );
219  (
220  "no-boundary", // noPatches
221  "Suppress writing any patches"
222  );
223  argList::addOptionCompat("no-boundary", {"noPatches", 1806});
224 
226  (
227  "no-internal",
228  "Suppress writing the internal mesh"
229  );
231  (
232  "no-cellZones",
233  "Suppress writing any cellZones"
234  );
236  (
237  "no-lagrangian", // noLagrangian
238  "Suppress writing lagrangian positions and fields"
239  );
240  argList::addOptionCompat("no-lagrangian", {"noLagrangian", 1806});
241 
243  (
244  "no-point-data",
245  "Suppress conversion of pointFields, disable -nodeValues"
246  );
248  (
249  "no-mesh", // noMesh
250  "Suppress writing the geometry."
251  " Can be useful for converting partial results for a static geometry"
252  , true // mark as an advanced option
253  );
254 
255  // Future?
256  // argList::addBoolOption
257  // (
258  // "one-boundary", // allPatches
259  // "Combine all patches into a single part"
260  // );
262  (
263  "no-finite-area",
264  "Suppress output of finite-area mesh/fields",
265  true // mark as an advanced option
266  );
268  (
269  {"finite-area", 2112}, // use -no-finite-area to disable
270  false // bool option, no argument
271  );
272 
274  (
275  "patches",
276  "wordRes",
277  "Specify single patch or multiple patches to write\n"
278  "Eg, 'inlet' or '(outlet \"inlet.*\")'"
279  );
281  (
282  "exclude-patches",
283  "wordRes",
284  "Exclude single or multiple patches from writing\n"
285  "Eg, 'outlet' or '( inlet \".*Wall\" )'"
286  , true // mark as an advanced option
287  );
288  argList::addOptionCompat("exclude-patches", {"excludePatches", 2112});
289 
291  (
292  "faceZones",
293  "wordRes",
294  "Specify single or multiple faceZones to write\n"
295  "Eg, 'cells' or '( slice \"mfp-.*\" )'."
296  );
298  (
299  "fields",
300  "wordRes",
301  "Specify single or multiple fields to write (all by default)\n"
302  "Eg, 'T' or '( \"U.*\" )'"
303  );
305  (
306  "exclude-fields",
307  "wordRes",
308  "Exclude single or multiple fields",
309  true // mark as an advanced option
310  );
312  (
313  "no-fields",
314  "Suppress conversion of fields"
315  );
316 
318  (
319  "cellZones",
320  "wordRes",
321  "Specify single or multiple cellZones to write\n"
322  "Eg, 'cells' or '( slice \"mfp-.*\" )'."
323  );
324  argList::addOptionCompat("cellZones", {"cellZone", 1912});
325 
326  #include "setRootCase.H"
327 
328  // ------------------------------------------------------------------------
329  // Configuration
330 
331  // Default to binary output, unless otherwise specified
333  (
334  args.found("ascii")
337  );
338 
339  const int optVerbose = args.verbose();
340  const bool doBoundary = !args.found("no-boundary");
341  const bool doInternal = !args.found("no-internal");
342  const bool doCellZones = !args.found("no-cellZones");
343  const bool doLagrangian = !args.found("no-lagrangian");
344  const bool doFiniteArea = !args.found("no-finite-area");
345  const bool doPointValues = !args.found("no-point-data");
346  const bool nearCellValue = args.found("nearCellValue") && doBoundary;
347 
348  // Control for numbering iterations
349  label indexingNumber(0);
350  const bool doConsecutive = args.readIfPresent("index", indexingNumber);
351 
352  // Write the geometry, unless otherwise specified
353  bool doGeometry = !args.found("no-mesh");
354 
355  if (nearCellValue)
356  {
357  Info<< "Using neighbouring cell value instead of patch value"
358  << nl << endl;
359  }
360  if (!doPointValues)
361  {
362  Info<< "Point fields and interpolated point data"
363  << " disabled with the '-no-point-data' option"
364  << nl;
365  }
366 
367  //
368  // General (case) output options
369  //
370  ensightCase::options caseOpts(format);
371 
372  // Forced point interpolation?
373  caseOpts.nodeValues(doPointValues && args.found("nodeValues"));
374  caseOpts.width(args.getOrDefault<label>("width", 8));
375  caseOpts.overwrite(!args.found("no-overwrite")); // Remove existing?
376 
377  // Can also have separate directory for lagrangian
378  // caseOpts.separateCloud(true);
379 
380  ensightMesh::options writeOpts;
381  writeOpts.useBoundaryMesh(doBoundary);
382  writeOpts.useInternalMesh(doInternal);
383  writeOpts.useCellZones(doCellZones);
384 
385  // Patch selection/deselection
386  if (args.found("patches"))
387  {
388  writeOpts.patchSelection(args.getList<wordRe>("patches"));
389  }
390  if (args.found("exclude-patches"))
391  {
392  writeOpts.patchExclude(args.getList<wordRe>("exclude-patches"));
393  }
394 
395  if (args.found("faceZones"))
396  {
397  writeOpts.faceZoneSelection(args.getList<wordRe>("faceZones"));
398  }
399  if (args.found("cellZones"))
400  {
401  writeOpts.cellZoneSelection(args.getList<wordRe>("cellZones"));
402  }
403 
404  // Report the setup
405  writeOpts.print(Info);
406 
407  // Field selection/deselection
408  wordRes includedFields, excludedFields;
409  autoPtr<wordRes::filter> fieldSelector(nullptr);
410  const bool doConvertFields = !args.found("no-fields");
411  if (doConvertFields)
412  {
413  bool resetFilter = false;
414  if (args.readListIfPresent<wordRe>("fields", includedFields))
415  {
416  resetFilter = true;
417  Info<< "Including fields "
418  << flatOutput(includedFields) << nl << endl;
419  }
420  if (args.readListIfPresent<wordRe>("exclude-fields", excludedFields))
421  {
422  resetFilter = true;
423  Info<< "Excluding fields "
424  << flatOutput(excludedFields) << nl << endl;
425  }
426  if (resetFilter)
427  {
428  fieldSelector =
429  autoPtr<wordRes::filter>::New(includedFields, excludedFields);
430  }
431  }
432  else if (doConvertFields)
433  {
434  Info<< "Field conversion disabled with the '-no-fields' option" << nl;
435  }
436 
437  // ------------------------------------------------------------------------
438 
439  #include "createTime.H"
440 
442 
443  // Handle -allRegions, -regions, -region
444  #include "getAllRegionOptions.H"
445 
446  // ------------------------------------------------------------------------
447  // Directory management
448 
449  // Define sub-directory name to use for EnSight data.
450  // The path to the ensight directory is at case level only
451  // - For parallel cases, data only written from master
452 
453  // Sub-directory for output
454  const word ensDirName = args.getOrDefault<word>("name", "EnSight");
455 
456  fileName outputDir(args.globalPath()/ensDirName);
457 
458  if (!outputDir.isAbsolute())
459  {
460  outputDir = args.globalPath()/outputDir;
461  }
462 
463 
464  // ------------------------------------------------------------------------
465  cpuTime timer;
466  memInfo mem;
467  Info<< "Initial memory " << mem.update().size() << " kB" << endl;
468 
469  #include "createNamedMeshes.H"
470  #include "createMeshAccounting.H"
471 
472  if (Pstream::master())
473  {
474  Info<< "Converting " << timeDirs.size() << " time steps" << nl;
475  // ensCase.printInfo(Info) << endl;
476  }
477 
478  // Check mesh motion
479  #include "checkMeshMoving.H"
480  if (hasMovingMesh && !doGeometry)
481  {
482  Info<< "has moving mesh: ignoring '-no-mesh' option" << endl;
483  doGeometry = true;
484  }
485 
486  // Check lagrangian
487  #include "findCloudFields.H"
488 
489  // Check field availability
490  #include "checkFieldAvailability.H"
491 
492  // test the pre-check variable if there is a moving mesh
493  // time-set for geometries
494  // TODO: split off into separate time-set,
495  // but need to verify ensight spec
496 
497  Info<< "Startup in "
498  << timer.cpuTimeIncrement() << " s, "
499  << mem.update().size() << " kB" << nl << endl;
500 
501 
502  forAll(timeDirs, timei)
503  {
504  runTime.setTime(timeDirs[timei], timei);
505 
506  // Index for the Ensight case(s). Continues if not possible
507  #include "getTimeIndex.H"
508 
509  Info<< "Time [" << timeIndex << "] = " << runTime.timeName() << nl;
510 
511  forAll(regionNames, regioni)
512  {
513  const word& regionName = regionNames[regioni];
515 
516  if (regionNames.size() > 1)
517  {
518  Info<< "region=" << regionName << nl;
519  }
520 
521  auto& mesh = meshes[regioni];
522 
524  const bool moving = (meshState != polyMesh::UNCHANGED);
525 
526  // Ensight
527  auto& ensCase = ensightCases[regioni];
528  auto& ensMesh = ensightMeshes[regioni];
529 
530  // Finite-area (can be missing)
531  auto* ensFaCasePtr = ensightCasesFa.get(regioni);
532  auto* ensFaMeshPtr = ensightMeshesFa.get(regioni);
533 
534  ensCase.setTime(timeDirs[timei], timeIndex);
535  if (ensFaCasePtr)
536  {
537  ensFaCasePtr->setTime(timeDirs[timei], timeIndex);
538  }
539 
540  if (moving)
541  {
542  ensMesh.expire();
543  ensMesh.correct();
544 
545  if (ensFaMeshPtr)
546  {
547  ensFaMeshPtr->expire();
548  ensFaMeshPtr->correct();
549  }
550  }
551 
552  if ((timei == 0 || moving) && doGeometry)
553  {
554  // finite-volume
555  {
557  ensCase.newGeometry(hasMovingMesh);
558  ensMesh.write(os);
559  }
560 
561  // finite-area
562  if (ensFaCasePtr && ensFaMeshPtr)
563  {
565  ensFaCasePtr->newGeometry(hasMovingMesh);
566  ensFaMeshPtr->write(os);
567  }
568  }
569 
570  // Objects at this time
571  IOobjectList objects(mesh, runTime.timeName());
572 
573  objects.filterObjects
574  (
576  );
577 
578  // Volume, internal, point fields
579  #include "convertVolumeFields.H"
580 
581  // The finiteArea fields
582  #include "convertAreaFields.H"
583 
584  // Lagrangian fields
585  #include "convertLagrangian.H"
586  }
587 
588  Info<< "Wrote in "
589  << timer.cpuTimeIncrement() << " s, "
590  << mem.update().size() << " kB" << nl << nl;
591  }
592 
593  // Write cases
594  forAll(ensightCases, regioni)
595  {
596  ensightCases[regioni].write();
597  }
598 
599  forAll(ensightCasesFa, regioni)
600  {
601  if (ensightCasesFa.set(regioni))
602  {
603  ensightCasesFa[regioni].write();
604  }
605  }
606 
607  Info<< "\nEnd: "
608  << timer.elapsedCpuTime() << " s, "
609  << mem.update().peak() << " kB (peak)" << nl << endl;
610 
611  return 0;
612 }
613 
614 
615 // ************************************************************************* //
const wordRes & cellZoneSelection() const noexcept
Selection of faceZones. Empty if unspecified.
Definition: ensightMesh.H:410
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:453
virtual Ostream & write(const char c)
Write character.
Definition: OBJstream.C:71
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
int peak() const
Peak memory (VmPeak in /proc/PID/status) at last update()
Definition: memInfo.H:119
A class for handling file names.
Definition: fileName.H:71
static void setAdvanced(const word &optName, bool advanced=true)
Set an existing option as being &#39;advanced&#39; or normal.
Definition: argList.C:395
List of IOobjects with searching and retrieving facilities. Implemented as a HashTable, so the various sorted methods should be used if traversing in parallel.
Definition: IOobjectList.H:55
const word & regionName() const
The mesh region name or word::null if polyMesh::defaultRegion.
Definition: polyMesh.C:841
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
const memInfo & update()
Update according to /proc/PID/status and /proc/memory contents.
Definition: memInfo.C:57
Implements a timeout mechanism via sigalarm.
Definition: timer.H:82
"ascii" (normal default)
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
List< T > getList(const label index) const
Get a List of values from the argument at index.
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
Definition: argList.C:365
static void addOptionCompat(const word &optName, std::pair< const char *, int > compat)
Specify an alias for the option name.
Definition: argList.C:409
wordList regionNames
A collection of functions for writing volField content in ensight format.
T getOrDefault(const word &optName, const T &deflt) const
Get a value from the named option if present, or return default.
Definition: argListI.H:300
A collection of functions for writing clouds as ensight file content.
PtrList< ensightCase > ensightCases(regionNames.size())
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
Configuration options for the ensightCase.
Definition: ensightCase.H:510
Foam::word regionName(Foam::polyMesh::defaultRegion)
dynamicFvMesh & mesh
virtual readUpdateState readUpdate()
Update the mesh based on the mesh files saved in time.
Definition: fvMesh.C:668
PtrList< ensightFaMesh > ensightMeshesFa(regionNames.size())
Header files for all the primitive types that Fields are instantiated for.
List< wordHashSet > availableRegionObjectNames(meshes.size())
A class for handling words, derived from Foam::string.
Definition: word.H:63
const wordRes & patchSelection() const noexcept
Selection of patches. Empty if unspecified.
Definition: ensightMesh.H:386
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
static void addVerboseOption(const string &usage, bool advanced=false)
Enable a &#39;verbose&#39; bool option, with usage information.
Definition: argList.C:505
PtrList< ensightMesh > ensightMeshes(regionNames.size())
PtrList< ensightCase > ensightCasesFa(regionNames.size())
bool useCellZones() const noexcept
Using cellZones?
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:47
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Add an option to validOptions with usage information.
Definition: argList.C:376
virtual void setTime(const Time &t)
Reset the time and time-index to those of the given time.
Definition: Time.C:977
static void ignoreOptionCompat(std::pair< const char *, int > compat, bool expectArg)
Specify an option to be ignored.
Definition: argList.C:423
bool hasMovingMesh(false)
bool useBoundaryMesh() const noexcept
Using boundary?
A wordRe is a Foam::word, but can contain a regular expression for matching words or strings...
Definition: wordRe.H:78
Istream and Ostream manipulators taking arguments.
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:760
const wordRes & faceZoneSelection() const noexcept
Selection of faceZones. Empty if unspecified.
Definition: ensightMesh.H:402
OBJstream os(runTime.globalPath()/outputName)
bool readListIfPresent(const word &optName, List< T > &list) const
If named option is present, get a List of values treating a single entry like a list of size 1...
Definition: argListI.H:387
Memory usage information for the current process, and the system memory that is free.
Definition: memInfo.H:58
static instantList select0(Time &runTime, const argList &args)
Return the set of times selected based on the argList options and also set the runTime to the first i...
Definition: timeSelector.C:234
word format(conversionProperties.get< word >("format"))
bool useInternalMesh() const noexcept
Using internal?
const word & regionDir
static bool master(const label communicator=worldComm)
Am I the master rank.
Definition: UPstream.H:672
const wordRes & patchExclude() const noexcept
Selection of black listed patches. Empty if unspecified.
Definition: ensightMesh.H:394
streamFormat
Data format (ascii | binary)
messageStream Info
Information stream (stdout output on master, null elsewhere)
Configuration options for the ensightMesh.
Definition: ensightMesh.H:299
void print(Ostream &os) const
Report values.
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
label filterObjects(const UnaryPredicate &pred, const bool pruning=false)
Filter to retain or prune given object names.
A collection of functions for writing areaField content in ensight format.
bool readIfPresent(const word &optName, T &val) const
Read a value from the named option if present.
Definition: argListI.H:316
readUpdateState
Enumeration defining the state of the mesh after a read update.
Definition: polyMesh.H:89
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
Definition: autoPtr.H:178
Foam::argList args(argc, argv)
int verbose() const noexcept
Return the verbose flag.
Definition: argListI.H:121
int size() const
Memory size (VmSize in /proc/PID/status) at last update()
Definition: memInfo.H:127
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:171
static void addOptions(const bool constant=true, const bool withZero=false)
Add timeSelector options to argList::validOptions.
Definition: timeSelector.C:101
Namespace for OpenFOAM.
fileName globalPath() const
Return the full path to the global case.
Definition: argListI.H:80
label timeIndex
Definition: getTimeIndex.H:24
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
Starts timing CPU usage and return elapsed time from start.
Definition: cpuTimePosix.H:52
Required Variables.