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 
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  Info<< "Initial memory " << Foam::memInfo{}.size() << " kB" << endl;
467 
468  #include "createNamedMeshes.H"
469  #include "createMeshAccounting.H"
470 
471  if (Pstream::master())
472  {
473  Info<< "Converting " << timeDirs.size() << " time steps" << nl;
474  // ensCase.printInfo(Info) << endl;
475  }
476 
477  // Check mesh motion
478  #include "checkMeshMoving.H"
479  if (hasMovingMesh && !doGeometry)
480  {
481  Info<< "has moving mesh: ignoring '-no-mesh' option" << endl;
482  doGeometry = true;
483  }
484 
485  // Check lagrangian
486  #include "findCloudFields.H"
487 
488  // Check field availability
489  #include "checkFieldAvailability.H"
490 
491  // test the pre-check variable if there is a moving mesh
492  // time-set for geometries
493  // TODO: split off into separate time-set,
494  // but need to verify ensight spec
495 
496  Info<< "Startup in "
497  << timer.cpuTimeIncrement() << " s, "
498  << Foam::memInfo{}.size() << " kB" << nl << endl;
499 
500 
501  forAll(timeDirs, timei)
502  {
503  runTime.setTime(timeDirs[timei], timei);
504 
505  // Index for the Ensight case(s). Continues if not possible
506  #include "getTimeIndex.H"
507 
508  Info<< "Time [" << timeIndex << "] = " << runTime.timeName() << nl;
509 
510  forAll(regionNames, regioni)
511  {
512  const word& regionName = regionNames[regioni];
514 
515  if (regionNames.size() > 1)
516  {
517  Info<< "region=" << regionName << nl;
518  }
519 
520  auto& mesh = meshes[regioni];
521 
523  const bool moving = (meshState != polyMesh::UNCHANGED);
524 
525  // Ensight
526  auto& ensCase = ensightCases[regioni];
527  auto& ensMesh = ensightMeshes[regioni];
528 
529  // Finite-area (can be missing)
530  auto* ensFaCasePtr = ensightCasesFa.get(regioni);
531  auto* ensFaMeshPtr = ensightMeshesFa.get(regioni);
532 
533  ensCase.setTime(timeDirs[timei], timeIndex);
534  if (ensFaCasePtr)
535  {
536  ensFaCasePtr->setTime(timeDirs[timei], timeIndex);
537  }
538 
539  if (moving)
540  {
541  ensMesh.expire();
542  ensMesh.correct();
543 
544  if (ensFaMeshPtr)
545  {
546  ensFaMeshPtr->expire();
547  ensFaMeshPtr->correct();
548  }
549  }
550 
551  if ((timei == 0 || moving) && doGeometry)
552  {
553  // finite-volume
554  {
556  ensCase.newGeometry(hasMovingMesh);
557  ensMesh.write(os);
558  }
559 
560  // finite-area
561  if (ensFaCasePtr && ensFaMeshPtr)
562  {
564  ensFaCasePtr->newGeometry(hasMovingMesh);
565  ensFaMeshPtr->write(os);
566  }
567  }
568 
569  // Objects at this time
570  IOobjectList objects(mesh, runTime.timeName());
571 
572  objects.filterObjects
573  (
575  );
576 
577  // Volume, internal, point fields
578  #include "convertVolumeFields.H"
579 
580  // The finiteArea fields
581  #include "convertAreaFields.H"
582 
583  // Lagrangian fields
584  #include "convertLagrangian.H"
585  }
586 
587  Info<< "Wrote in "
588  << timer.cpuTimeIncrement() << " s, "
589  << Foam::memInfo{}.size() << " kB" << nl << nl;
590  }
591 
592  // Write cases
593  forAll(ensightCases, regioni)
594  {
595  ensightCases[regioni].write();
596  }
597 
598  forAll(ensightCasesFa, regioni)
599  {
600  if (ensightCasesFa.set(regioni))
601  {
602  ensightCasesFa[regioni].write();
603  }
604  }
605 
606  Info<< "\nEnd: "
607  << timer.elapsedCpuTime() << " s, "
608  << Foam::memInfo{}.peak() << " kB (peak)" << nl << endl;
609 
610  return 0;
611 }
612 
613 
614 // ************************************************************************* //
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:462
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
A class for handling file names.
Definition: fileName.H:72
static void setAdvanced(const word &optName, bool advanced=true)
Set an existing option as being &#39;advanced&#39; or normal.
Definition: argList.C:404
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
virtual Ostream & write(const char c) override
Write character.
Definition: OBJstream.C:69
const word & regionName() const
The mesh region name or word::null if polyMesh::defaultRegion.
Definition: polyMesh.C:847
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Implements a timeout mechanism via sigalarm.
Definition: timer.H:82
"ascii" (normal default)
engineTime & runTime
Database for mesh data, solution data, solver performance and other reduced data. ...
Definition: meshState.H:53
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
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:374
static void addOptionCompat(const word &optName, std::pair< const char *, int > compat)
Specify an alias for the option name.
Definition: argList.C:418
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:421
Configuration options for the ensightCase.
Definition: ensightCase.H:530
dynamicFvMesh & mesh
virtual readUpdateState readUpdate()
Update the mesh based on the mesh files saved in time.
Definition: fvMesh.C:704
PtrList< ensightFaMesh > ensightMeshesFa(regionNames.size())
List< wordHashSet > availableRegionObjectNames(meshes.size())
A class for handling words, derived from Foam::string.
Definition: word.H:63
int64_t peak() const noexcept
Peak memory at last update - (VmPeak in /proc/PID/status)
Definition: memInfo.H:113
const wordRes & patchSelection() const noexcept
Selection of patches. Empty if unspecified.
Definition: ensightMesh.H:386
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
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:53
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:385
virtual void setTime(const Time &t)
Reset the time and time-index to those of the given time.
Definition: Time.C:935
static void ignoreOptionCompat(std::pair< const char *, int > compat, bool expectArg)
Specify an option to be ignored.
Definition: argList.C:432
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
static void addVerboseOption(const string &usage="", bool advanced=false)
Enable a &#39;verbose&#39; bool option, with usage information.
Definition: argList.C:520
Istream and Ostream manipulators taking arguments.
static word timeName(const scalar t, const int precision=precision_)
Return a time name for the given scalar time value formatted with the given precision.
Definition: Time.C:714
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"))
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
bool useInternalMesh() const noexcept
Using internal?
const word & regionDir
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
Required Classes.
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:90
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
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
int64_t size() const noexcept
Memory size at last update - (VmSize in /proc/PID/status)
Definition: memInfo.H:118
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.