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-------------------------------------------------------------------------------
11License
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
27Application
28 foamToEnsight
29
30Group
31 grpPostProcessingUtilitie
32
33Description
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
41Usage
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"
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
156using namespace Foam;
157
158// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
159
160int main(int argc, char *argv[])
161{
162 argList::addNote
163 (
164 "Translate OpenFOAM data to Ensight format with individual parts"
165 " for cellZones, unzoned cells and patches"
166 );
167 timeSelector::addOptions();
168
169 // Less frequently used - reduce some clutter
170 argList::setAdvanced("decomposeParDict");
171 argList::setAdvanced("noFunctionObjects");
172
173 argList::addVerboseOption("Additional verbosity");
174
175 #include "addAllRegionOptions.H"
176
177 argList::addBoolOption
178 (
179 "ascii",
180 "Write in ASCII format instead of 'C Binary'"
181 );
182 argList::addOption
183 (
184 "index",
185 "start",
186 "Starting index for consecutive number of Ensight data/ files."
187 " Ignore the time index contained in the uniform/time file."
188 , true // mark as an advanced option
189 );
190 argList::addOption
191 (
192 "name",
193 "subdir",
194 "Sub-directory name for Ensight output (default: 'EnSight')"
195 );
196 argList::addBoolOption
197 (
198 "no-overwrite",
199 "Suppress removal of existing EnSight output directory"
200 );
201 argList::addOption
202 (
203 "width",
204 "n",
205 "Width of Ensight data subdir"
206 );
207 argList::addBoolOption
208 (
209 "nearCellValue",
210 "Use zero-gradient cell values on patches"
211 , true // mark as an advanced option
212 );
213 argList::addBoolOption
214 (
215 "nodeValues",
216 "Force interpolation of values to nodes"
217 , true // mark as an advanced option
218 );
219 argList::addBoolOption
220 (
221 "no-boundary", // noPatches
222 "Suppress writing any patches"
223 );
224 argList::addOptionCompat("no-boundary", {"noPatches", 1806});
225
226 argList::addBoolOption
227 (
228 "no-internal",
229 "Suppress writing the internal mesh"
230 );
231 argList::addBoolOption
232 (
233 "no-cellZones",
234 "Suppress writing any cellZones"
235 );
236 argList::addBoolOption
237 (
238 "no-lagrangian", // noLagrangian
239 "Suppress writing lagrangian positions and fields"
240 );
241 argList::addOptionCompat("no-lagrangian", {"noLagrangian", 1806});
242
243 argList::addBoolOption
244 (
245 "no-point-data",
246 "Suppress conversion of pointFields, disable -nodeValues"
247 );
248 argList::addBoolOption
249 (
250 "no-mesh", // noMesh
251 "Suppress writing the geometry."
252 " Can be useful for converting partial results for a static geometry"
253 , true // mark as an advanced option
254 );
255
256 // Future?
257 // argList::addBoolOption
258 // (
259 // "one-boundary", // allPatches
260 // "Combine all patches into a single part"
261 // );
262 argList::addBoolOption
263 (
264 "no-finite-area",
265 "Suppress output of finite-area mesh/fields",
266 true // mark as an advanced option
267 );
268 argList::ignoreOptionCompat
269 (
270 {"finite-area", 2112}, // use -no-finite-area to disable
271 false // bool option, no argument
272 );
273
274 argList::addOption
275 (
276 "patches",
277 "wordRes",
278 "Specify single patch or multiple patches to write\n"
279 "Eg, 'inlet' or '(outlet \"inlet.*\")'"
280 );
281 argList::addOption
282 (
283 "exclude-patches",
284 "wordRes",
285 "Exclude single or multiple patches from writing\n"
286 "Eg, 'outlet' or '( inlet \".*Wall\" )'"
287 , true // mark as an advanced option
288 );
289 argList::addOptionCompat("exclude-patches", {"excludePatches", 2112});
290
291 argList::addOption
292 (
293 "faceZones",
294 "wordRes",
295 "Specify single or multiple faceZones to write\n"
296 "Eg, 'cells' or '( slice \"mfp-.*\" )'."
297 );
298 argList::addOption
299 (
300 "fields",
301 "wordRes",
302 "Specify single or multiple fields to write (all by default)\n"
303 "Eg, 'T' or '( \"U.*\" )'"
304 );
305 argList::addOption
306 (
307 "exclude-fields",
308 "wordRes",
309 "Exclude single or multiple fields",
310 true // mark as an advanced option
311 );
312 argList::addBoolOption
313 (
314 "no-fields",
315 "Suppress conversion of fields"
316 );
317
318 argList::addOption
319 (
320 "cellZones",
321 "wordRes",
322 "Specify single or multiple cellZones to write\n"
323 "Eg, 'cells' or '( slice \"mfp-.*\" )'."
324 );
325 argList::addOptionCompat("cellZones", {"cellZone", 1912});
326
327 #include "setRootCase.H"
328
329 // ------------------------------------------------------------------------
330 // Configuration
331
332 // Default to binary output, unless otherwise specified
334 (
335 args.found("ascii")
336 ? IOstreamOption::ASCII
337 : IOstreamOption::BINARY
338 );
339
340 const int optVerbose = args.verbose();
341 const bool doBoundary = !args.found("no-boundary");
342 const bool doInternal = !args.found("no-internal");
343 const bool doCellZones = !args.found("no-cellZones");
344 const bool doLagrangian = !args.found("no-lagrangian");
345 const bool doFiniteArea = !args.found("no-finite-area");
346 const bool doPointValues = !args.found("no-point-data");
347 const bool nearCellValue = args.found("nearCellValue") && doBoundary;
348
349 // Control for numbering iterations
350 label indexingNumber(0);
351 const bool doConsecutive = args.readIfPresent("index", indexingNumber);
352
353 // Write the geometry, unless otherwise specified
354 bool doGeometry = !args.found("no-mesh");
355
356 if (nearCellValue)
357 {
358 Info<< "Using neighbouring cell value instead of patch value"
359 << nl << endl;
360 }
361 if (!doPointValues)
362 {
363 Info<< "Point fields and interpolated point data"
364 << " disabled with the '-no-point-data' option"
365 << nl;
366 }
367
368 //
369 // General (case) output options
370 //
372
373 // Forced point interpolation?
374 caseOpts.nodeValues(doPointValues && args.found("nodeValues"));
375 caseOpts.width(args.getOrDefault<label>("width", 8));
376 caseOpts.overwrite(!args.found("no-overwrite")); // Remove existing?
377
378 // Can also have separate directory for lagrangian
379 // caseOpts.separateCloud(true);
380
381 ensightMesh::options writeOpts;
382 writeOpts.useBoundaryMesh(doBoundary);
383 writeOpts.useInternalMesh(doInternal);
384 writeOpts.useCellZones(doCellZones);
385
386 // Patch selection/deselection
387 if (args.found("patches"))
388 {
389 writeOpts.patchSelection(args.getList<wordRe>("patches"));
390 }
391 if (args.found("exclude-patches"))
392 {
393 writeOpts.patchExclude(args.getList<wordRe>("exclude-patches"));
394 }
395
396 if (args.found("faceZones"))
397 {
398 writeOpts.faceZoneSelection(args.getList<wordRe>("faceZones"));
399 }
400 if (args.found("cellZones"))
401 {
402 writeOpts.cellZoneSelection(args.getList<wordRe>("cellZones"));
403 }
404
405 // Report the setup
406 writeOpts.print(Info);
407
408 // Field selection/deselection
409 wordRes includedFields, excludedFields;
410 autoPtr<wordRes::filter> fieldSelector(nullptr);
411 const bool doConvertFields = !args.found("no-fields");
412 if (doConvertFields)
413 {
414 bool resetFilter = false;
415 if (args.readListIfPresent<wordRe>("fields", includedFields))
416 {
417 resetFilter = true;
418 Info<< "Including fields "
419 << flatOutput(includedFields) << nl << endl;
420 }
421 if (args.readListIfPresent<wordRe>("exclude-fields", excludedFields))
422 {
423 resetFilter = true;
424 Info<< "Excluding fields "
425 << flatOutput(excludedFields) << nl << endl;
426 }
427 if (resetFilter)
428 {
429 fieldSelector =
430 autoPtr<wordRes::filter>::New(includedFields, excludedFields);
431 }
432 }
433 else if (doConvertFields)
434 {
435 Info<< "Field conversion disabled with the '-no-fields' option" << nl;
436 }
437
438 // ------------------------------------------------------------------------
439
440 #include "createTime.H"
441
442 instantList timeDirs = timeSelector::select0(runTime, args);
443
444 // Handle -allRegions, -regions, -region
445 #include "getAllRegionOptions.H"
446
447 // ------------------------------------------------------------------------
448 // Directory management
449
450 // Define sub-directory name to use for EnSight data.
451 // The path to the ensight directory is at case level only
452 // - For parallel cases, data only written from master
453
454 // Sub-directory for output
455 const word ensDirName = args.getOrDefault<word>("name", "EnSight");
456
457 fileName outputDir(args.globalPath()/ensDirName);
458
459 if (!outputDir.isAbsolute())
460 {
461 outputDir = args.globalPath()/outputDir;
462 }
463
464
465 // ------------------------------------------------------------------------
467 memInfo mem;
468 Info<< "Initial memory " << mem.update().size() << " kB" << endl;
469
470 #include "createNamedMeshes.H"
471 #include "createMeshAccounting.H"
472
473 if (Pstream::master())
474 {
475 Info<< "Converting " << timeDirs.size() << " time steps" << nl;
476 // ensCase.printInfo(Info) << endl;
477 }
478
479 // Check mesh motion
480 #include "checkMeshMoving.H"
481 if (hasMovingMesh && !doGeometry)
482 {
483 Info<< "has moving mesh: ignoring '-no-mesh' option" << endl;
484 doGeometry = true;
485 }
486
487 // Check lagrangian
488 #include "findCloudFields.H"
489
490 // Check field availability
491 #include "checkFieldAvailability.H"
492
493 // test the pre-check variable if there is a moving mesh
494 // time-set for geometries
495 // TODO: split off into separate time-set,
496 // but need to verify ensight spec
497
498 Info<< "Startup in "
499 << timer.cpuTimeIncrement() << " s, "
500 << mem.update().size() << " kB" << nl << endl;
501
502
503 forAll(timeDirs, timei)
504 {
505 runTime.setTime(timeDirs[timei], timei);
506
507 // Index for the Ensight case(s). Continues if not possible
508 #include "getTimeIndex.H"
509
510 Info<< "Time [" << timeIndex << "] = " << runTime.timeName() << nl;
511
512 forAll(regionNames, regioni)
513 {
514 const word& regionName = regionNames[regioni];
515 const word& regionDir = polyMesh::regionName(regionName);
516
517 if (regionNames.size() > 1)
518 {
519 Info<< "region=" << regionName << nl;
520 }
521
522 auto& mesh = meshes[regioni];
523
524 polyMesh::readUpdateState meshState = mesh.readUpdate();
525 const bool moving = (meshState != polyMesh::UNCHANGED);
526
527 // Ensight
528 auto& ensCase = ensightCases[regioni];
529 auto& ensMesh = ensightMeshes[regioni];
530
531 // Finite-area (can be missing)
532 auto* ensFaCasePtr = ensightCasesFa.get(regioni);
533 auto* ensFaMeshPtr = ensightMeshesFa.get(regioni);
534
535 ensCase.setTime(timeDirs[timei], timeIndex);
536 if (ensFaCasePtr)
537 {
538 ensFaCasePtr->setTime(timeDirs[timei], timeIndex);
539 }
540
541 if (moving)
542 {
543 ensMesh.expire();
544 ensMesh.correct();
545
546 if (ensFaMeshPtr)
547 {
548 ensFaMeshPtr->expire();
549 ensFaMeshPtr->correct();
550 }
551 }
552
553 if ((timei == 0 || moving) && doGeometry)
554 {
555 // finite-volume
556 {
558 ensCase.newGeometry(hasMovingMesh);
559 ensMesh.write(os);
560 }
561
562 // finite-area
563 if (ensFaCasePtr && ensFaMeshPtr)
564 {
566 ensFaCasePtr->newGeometry(hasMovingMesh);
567 ensFaMeshPtr->write(os);
568 }
569 }
570
571 // Objects at this time
572 IOobjectList objects(mesh, runTime.timeName());
573
574 objects.filterObjects
575 (
577 );
578
579 // Volume, internal, point fields
580 #include "convertVolumeFields.H"
581
582 // The finiteArea fields
583 #include "convertAreaFields.H"
584
585 // Lagrangian fields
586 #include "convertLagrangian.H"
587 }
588
589 Info<< "Wrote in "
590 << timer.cpuTimeIncrement() << " s, "
591 << mem.update().size() << " kB" << nl << nl;
592 }
593
594 // Write cases
595 forAll(ensightCases, regioni)
596 {
597 ensightCases[regioni].write();
598 }
599
600 forAll(ensightCasesFa, regioni)
601 {
602 if (ensightCasesFa.set(regioni))
603 {
604 ensightCasesFa[regioni].write();
605 }
606 }
607
608 Info<< "\nEnd: "
609 << timer.elapsedCpuTime() << " s, "
610 << mem.update().peak() << " kB (peak)" << nl << endl;
611
612 return 0;
613}
614
615
616// ************************************************************************* //
Istream and Ostream manipulators taking arguments.
List< wordHashSet > availableRegionObjectNames(meshes.size())
bool hasMovingMesh(false)
List of IOobjects with searching and retrieving facilities.
Definition: IOobjectList.H:59
streamFormat
Data format (ascii | binary)
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
int verbose() const noexcept
Return the verbose flag.
Definition: argListI.H:128
bool readListIfPresent(const word &optName, List< T > &list) const
Definition: argListI.H:394
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:178
bool readIfPresent(const word &optName, T &val) const
Read a value from the named option if present.
Definition: argListI.H:323
List< T > getList(const label index) const
Get a List of values from the argument at index.
T getOrDefault(const word &optName, const T &deflt) const
Get a value from the named option if present, or return default.
Definition: argListI.H:307
fileName globalPath() const
Return the full path to the global case.
Definition: argListI.H:87
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
Starts timing CPU usage and return elapsed time from start.
Definition: cpuTimeCxx.H:54
Configuration options for the ensightCase.
Definition: ensightCase.H:381
Configuration options for the ensightMesh.
Definition: ensightMesh.H:240
bool useBoundaryMesh() const noexcept
Using boundary?
const wordRes & faceZoneSelection() const noexcept
Selection of faceZones. Empty if unspecified.
Definition: ensightMesh.H:308
bool useInternalMesh() const noexcept
Using internal?
void print(Ostream &os) const
Report values.
const wordRes & patchSelection() const noexcept
Selection of patches. Empty if unspecified.
Definition: ensightMesh.H:296
const wordRes & patchExclude() const noexcept
Selection of black listed patches. Empty if unspecified.
Definition: ensightMesh.H:302
bool useCellZones() const noexcept
Using cellZones?
const wordRes & cellZoneSelection() const noexcept
Selection of faceZones. Empty if unspecified.
Definition: ensightMesh.H:314
A class for handling file names.
Definition: fileName.H:76
Memory usage information for the current process, and the system memory that is free.
Definition: memInfo.H:63
int peak() const
Peak memory (VmPeak in /proc/PID/status) at last update()
Definition: memInfo.H:103
const memInfo & update()
Update according to /proc/PID/status and /proc/memory contents.
Definition: memInfo.C:64
int size() const
Memory size (VmSize in /proc/PID/status) at last update()
Definition: memInfo.H:109
readUpdateState
Enumeration defining the state of the mesh after a read update.
Definition: polyMesh.H:91
Implements a timeout mechanism via sigalarm.
Definition: timer.H:84
A wordRe is a Foam::word, but can contain a regular expression for matching words or strings.
Definition: wordRe.H:83
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:54
A class for handling words, derived from Foam::string.
Definition: word.H:68
dynamicFvMesh & mesh
engineTime & runTime
Foam::word regionName(Foam::polyMesh::defaultRegion)
Required Variables.
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
A collection of functions for writing areaField content in ensight format.
A collection of functions for writing clouds as ensight file content.
A collection of functions for writing volField content in ensight format.
OBJstream os(runTime.globalPath()/outputName)
Header files for all the primitive types that Fields are instantiated for.
const word & regionDir
PtrList< ensightCase > ensightCases(regionNames.size())
PtrList< ensightMesh > ensightMeshes(regionNames.size())
PtrList< ensightFaMesh > ensightMeshesFa(regionNames.size())
PtrList< ensightCase > ensightCasesFa(regionNames.size())
wordList regionNames
Namespace for OpenFOAM.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:215
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
label timeIndex
Definition: getTimeIndex.H:30
word format(conversionProperties.get< word >("format"))
Foam::argList args(argc, argv)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333