Loading...
Searching...
No Matches
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-2025 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 "PtrDynList.H"
128#include "regionProperties.H"
129
130#include "fvc.H"
131#include "fvMesh.H"
132#include "fieldTypes.H"
133#include "volFields.H"
134#include "scalarIOField.H"
135#include "vectorIOField.H"
136
137// file-format/conversion
138#include "ensightCase.H"
139#include "ensightGeoFile.H"
140#include "ensightFaMesh.H"
141#include "ensightMesh.H"
142#include "ensightOutputCloud.H"
145
146// local files
147#include "readFields.H"
148#include "writeVolFields.H"
149#include "writeDimFields.H"
150#include "writePointFields.H"
151#include "writeAreaFields.H"
152
153#include "memInfo.H"
154
155#undef foamToEnsight_useTimeIndex
156
157using namespace Foam;
158
159// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
160
161int main(int argc, char *argv[])
162{
164 (
165 "Translate OpenFOAM data to Ensight format with individual parts"
166 " for cellZones, unzoned cells and patches"
167 );
169
170 // Less frequently used - reduce some clutter
171 argList::setAdvanced("decomposeParDict");
172
174
175 #include "addAllRegionOptions.H"
176 #include "addAllFaRegionOptions.H"
177
179 (
180 "ascii",
181 "Write in ASCII format instead of 'C Binary'"
182 );
184 (
185 "index",
186 "start",
187 "Starting index for consecutive number of Ensight data/ files."
188 " Ignore the time index contained in the uniform/time file."
189 , true // mark as an advanced option
190 );
192 (
193 "name",
194 "subdir",
195 "Sub-directory name for Ensight output (default: 'EnSight')"
196 );
198 (
199 "no-overwrite",
200 "Suppress removal of existing EnSight output directory"
201 );
203 (
204 "width",
205 "n",
206 "Width of Ensight data subdir"
207 );
209 (
210 "nearCellValue",
211 "Use zero-gradient cell values on patches"
212 , true // mark as an advanced option
213 );
215 (
216 "nodeValues",
217 "Force interpolation of values to nodes"
218 , true // mark as an advanced option
219 );
221 (
222 "no-boundary", // noPatches
223 "Suppress writing any patches"
224 );
225 argList::addOptionCompat("no-boundary", {"noPatches", 1806});
226
228 (
229 "no-internal",
230 "Suppress writing the internal mesh"
231 );
233 (
234 "no-cellZones",
235 "Suppress writing any cellZones"
236 );
238 (
239 "no-lagrangian", // noLagrangian
240 "Suppress writing lagrangian positions and fields"
241 );
242 argList::addOptionCompat("no-lagrangian", {"noLagrangian", 1806});
243
245 (
246 "no-point-data",
247 "Suppress conversion of pointFields, disable -nodeValues"
248 );
250 (
251 "no-mesh", // noMesh
252 "Suppress writing the geometry."
253 " Can be useful for converting partial results for a static geometry"
254 , true // mark as an advanced option
255 );
256
257 // Future?
258 // argList::addBoolOption
259 // (
260 // "one-boundary", // allPatches
261 // "Combine all patches into a single part"
262 // );
264 (
265 "no-finite-area",
266 "Suppress output of finite-area mesh/fields",
267 true // mark as an advanced option
268 );
270 (
271 {"finite-area", 2112}, // use -no-finite-area to disable
272 false // bool option, no argument
273 );
274
276 (
277 "patches",
278 "wordRes",
279 "Specify single patch or multiple patches to write\n"
280 "Eg, 'inlet' or '(outlet \"inlet.*\")'"
281 );
283 (
284 "exclude-patches",
285 "wordRes",
286 "Exclude single or multiple patches from writing\n"
287 "Eg, 'outlet' or '( inlet \".*Wall\" )'"
288 , true // mark as an advanced option
289 );
290 argList::addOptionCompat("exclude-patches", {"excludePatches", 2112});
291
293 (
294 "faceZones",
295 "wordRes",
296 "Specify single or multiple faceZones to write\n"
297 "Eg, 'cells' or '( slice \"mfp-.*\" )'."
298 );
300 (
301 "fields",
302 "wordRes",
303 "Specify single or multiple fields to write (all by default)\n"
304 "Eg, 'T' or '( \"U.*\" )'"
305 );
307 (
308 "exclude-fields",
309 "wordRes",
310 "Exclude single or multiple fields",
311 true // mark as an advanced option
312 );
314 (
315 "no-fields",
316 "Suppress conversion of fields"
317 );
318
320 (
321 "cellZones",
322 "wordRes",
323 "Specify single or multiple cellZones to write\n"
324 "Eg, 'cells' or '( slice \"mfp-.*\" )'."
325 );
326 argList::addOptionCompat("cellZones", {"cellZone", 1912});
327
328 // Prevent volume BCs from triggering finite-area
330
331 #include "setRootCase.H"
332
333 // ------------------------------------------------------------------------
334 // Configuration
335
336 // Default to binary output, unless otherwise specified
338 (
339 args.found("ascii")
342 );
343
344 const int optVerbose = args.verbose();
345 const bool doBoundary = !args.found("no-boundary");
346 const bool doInternal = !args.found("no-internal");
347 const bool doCellZones = !args.found("no-cellZones");
348 const bool doLagrangian = !args.found("no-lagrangian");
349 const bool doFiniteArea = !args.found("no-finite-area");
350 const bool doPointValues = !args.found("no-point-data");
351 const bool nearCellValue = args.found("nearCellValue") && doBoundary;
352
353 // Control for numbering iterations
354 label indexingNumber(0);
355 const bool doConsecutive = args.readIfPresent("index", indexingNumber);
356
357 // Write the geometry, unless otherwise specified
358 bool doGeometry = !args.found("no-mesh");
359
360 if (nearCellValue)
361 {
362 Info<< "Using neighbouring cell value instead of patch value"
363 << nl << endl;
364 }
365 if (!doPointValues)
366 {
367 Info<< "Point fields and interpolated point data"
368 << " disabled with the '-no-point-data' option"
369 << nl;
370 }
371
372 //
373 // General (case) output options
374 //
376
377 // Forced point interpolation?
378 caseOpts.nodeValues(doPointValues && args.found("nodeValues"));
379 caseOpts.width(args.getOrDefault<label>("width", 8));
380 caseOpts.overwrite(!args.found("no-overwrite")); // Remove existing?
381
382 // Can also have separate directory for lagrangian
383 // caseOpts.separateCloud(true);
384
385 ensightMesh::options writeOpts;
386 writeOpts.useBoundaryMesh(doBoundary);
387 writeOpts.useInternalMesh(doInternal);
388 writeOpts.useCellZones(doCellZones);
389
390 // Patch selection/deselection
391 if (args.found("patches"))
392 {
393 writeOpts.patchSelection(args.getList<wordRe>("patches"));
394 }
395 if (args.found("exclude-patches"))
396 {
397 writeOpts.patchExclude(args.getList<wordRe>("exclude-patches"));
398 }
399
400 if (args.found("faceZones"))
401 {
402 writeOpts.faceZoneSelection(args.getList<wordRe>("faceZones"));
403 }
404 if (args.found("cellZones"))
405 {
406 writeOpts.cellZoneSelection(args.getList<wordRe>("cellZones"));
407 }
408
409 // Report the setup
410 writeOpts.print(Info);
411
412 // Field selection/deselection
413 wordRes includedFields, excludedFields;
414 const bool doConvertFields = !args.found("no-fields");
415 if (doConvertFields)
416 {
417 if (args.readListIfPresent<wordRe>("fields", includedFields))
418 {
419 Info<< "Including fields "
420 << flatOutput(includedFields) << nl << endl;
421 }
422 if (args.readListIfPresent<wordRe>("exclude-fields", excludedFields))
423 {
424 Info<< "Excluding fields "
425 << flatOutput(excludedFields) << nl << endl;
426 }
427 }
428 else
429 {
430 Info<< "Field conversion disabled with the '-no-fields' option" << nl;
431 }
432
433 const wordRes::filter fieldSelector(includedFields, excludedFields);
434
435 // ------------------------------------------------------------------------
436
437 #include "createTime.H"
438
440
441 // Handle volume region selections
442 #include "getAllRegionOptions.H"
443
444 // Handle area region selections
445 #include "getAllFaRegionOptions.H"
446
447 if (!doFiniteArea)
448 {
449 areaRegionNames.clear(); // For consistency
450 }
451
452 // ------------------------------------------------------------------------
453 // Directory management
454
455 // Define sub-directory name to use for EnSight data.
456 // The path to the ensight directory is at case level only
457 // - For parallel cases, data only written from master
458
459 // Sub-directory for output
460 const word ensDirName = args.getOrDefault<word>("name", "EnSight");
461
462 fileName outputDir(args.globalPath()/ensDirName);
463
464 if (!outputDir.isAbsolute())
465 {
466 outputDir = args.globalPath()/outputDir;
467 }
468
469
470 // ------------------------------------------------------------------------
472 Info<< "Initial memory " << Foam::memInfo{}.size() << " kB" << endl;
473
474 #include "createNamedMeshes.H"
475 #include "createMeshAccounting.H"
476
477 if (UPstream::master())
478 {
479 Info<< "Converting " << timeDirs.size() << " time steps" << nl;
480 // ensCase.printInfo(Info) << endl;
481 }
482
483 // Check mesh motion
484 #include "checkMeshMoving.H"
485 if (hasMovingMesh && !doGeometry)
486 {
487 Info<< "has moving mesh: ignoring '-no-mesh' option" << endl;
488 doGeometry = true;
489 }
490
491 // Check lagrangian
492 #include "findCloudFields.H"
493
494 // Check field availability
495 #include "checkFieldAvailability.H"
496
497 // test the pre-check variable if there is a moving mesh
498 // time-set for geometries
499 // TODO: split off into separate time-set,
500 // but need to verify ensight spec
501
502 Info<< "Startup in "
503 << timer.cpuTimeIncrement() << " s, "
504 << Foam::memInfo{}.size() << " kB" << nl << endl;
505
506
507 forAll(timeDirs, timei)
508 {
509 runTime.setTime(timeDirs[timei], timei);
510
511 // Index for the Ensight case(s). Continues if not possible
512 #include "getTimeIndex.H"
513
514 Info<< "Time [" << timeIndex << "] = " << runTime.timeName() << nl;
515
516 forAll(regionNames, regioni)
517 {
518 const word& regionName = regionNames[regioni];
520
521 if (regionNames.size() > 1)
522 {
523 Info<< "region=" << regionName << nl;
524 }
525
526 auto& mesh = meshes[regioni];
527
529 const bool moving = (meshState != polyMesh::UNCHANGED);
530
531 // Ensight (fvMesh)
532 auto& ensCase = ensightCases[regioni];
533 auto& ensMesh = ensightMeshes[regioni];
534
535 ensCase.setTime(timeDirs[timei], timeIndex);
536
537 // Finite-area (optional)
538 // Accounting exists for each volume region but may be empty
539 auto& ensFaCases = ensightCasesFa[regioni];
540 auto& ensFaMeshes = ensightMeshesFa[regioni];
541
542 for (auto& ensFaCase : ensFaCases)
543 {
544 ensFaCase.setTime(timeDirs[timei], timeIndex);
545 }
546
547 // Movement
548 if (moving)
549 {
550 ensMesh.expire();
551 ensMesh.correct();
552
553 for (auto& ensFaMesh : ensFaMeshes)
554 {
555 ensFaMesh.expire();
556 ensFaMesh.correct();
557 }
558 }
559
560 if ((timei == 0 || moving) && doGeometry)
561 {
562 // finite-volume
563 {
565 ensCase.newGeometry(hasMovingMesh);
566
567 ensMesh.write(os.ref());
568 }
569
570 // finite-area
571 forAll(ensFaMeshes, areai)
572 {
573 const auto& ensFaCase = ensFaCases[areai];
574 const auto& ensFaMesh = ensFaMeshes[areai];
575
577 ensFaCase.newGeometry(hasMovingMesh);
578
579 ensFaMesh.write(os.ref());
580 }
581 }
582
583
584 // Objects at this time
585 IOobjectList objects(mesh, runTime.timeName());
586
587 objects.filterObjects
588 (
590 );
591
592 // Volume, internal, point fields
593 #include "convertVolumeFields.H"
594
595 // finite-area
596 forAll(ensFaMeshes, areai)
597 {
598 auto* ensFaCasePtr = ensFaCases.get(areai);
599 auto* ensFaMeshPtr = ensFaMeshes.get(areai);
600
601 // The finite-area region objects at this time
602 IOobjectList faObjects;
603
604 if (ensFaMeshPtr) // Cannot really fail
605 {
606 const auto& areaMesh = ensFaMeshPtr->mesh();
607 const word& areaName = areaMesh.name();
608
609 faObjects = IOobjectList
610 (
611 areaMesh,
612 runTime.timeName(),
614 );
615
616 faObjects.filterObjects
617 (
618 availableFaRegionObjectNames[regioni](areaName)
619 );
620 }
621
622 // The finiteArea fields
623 #include "convertAreaFields.H"
624 }
625
626 // Lagrangian fields
627 #include "convertLagrangian.H"
628 }
629
630 Info<< "Wrote in "
631 << timer.cpuTimeIncrement() << " s, "
632 << Foam::memInfo{}.size() << " kB" << nl << nl;
633 }
634
635 // Write cases
636 forAll(ensightCases, regioni)
637 {
638 // finite-volume
639 ensightCases[regioni].write();
640
641 // Finite-area (if any)
642 for (const auto& ensFaCase : ensightCasesFa[regioni])
643 {
644 ensFaCase.write();
645 }
646 }
647
648 Info<< "\nEnd: "
649 << timer.elapsedCpuTime() << " s, "
650 << Foam::memInfo{}.peak() << " kB (peak)" << nl << endl;
651
652 return 0;
653}
654
655
656// ************************************************************************* //
Istream and Ostream manipulators taking arguments.
Required Classes.
Required Classes.
Helper routines for reading a field or fields, for foamToEnsight.
List< HashTable< wordHashSet > > availableFaRegionObjectNames(meshes.size())
List< wordHashSet > availableRegionObjectNames(meshes.size())
bool hasMovingMesh(false)
List of IOobjects with searching and retrieving facilities. Implemented as a HashTable,...
label filterObjects(const UnaryPredicate &pred, const bool pruning=false)
Filter to retain or prune given object names.
@ NO_REGISTER
Do not request registration (bool: false).
streamFormat
Data format (ascii | binary | coherent).
@ ASCII
"ascii" (normal default)
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
Mesh data needed to do the Finite Area discretisation.
Definition areaFaMesh.H:50
static void addVerboseOption(const string &usage="", bool advanced=false)
Enable a 'verbose' bool option, with usage information.
Definition argList.C:535
static void setAdvanced(const word &optName, bool advanced=true)
Set an existing option as being 'advanced' or normal.
Definition argList.C:419
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
Definition argList.C:389
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:400
static void addNote(const string &note)
Add extra notes for the usage information.
Definition argList.C:477
static void ignoreOptionCompat(std::pair< const char *, int > compat, bool expectArg)
Specify an option to be ignored.
Definition argList.C:447
static void addOptionCompat(const word &optName, std::pair< const char *, int > compat)
Specify an alias for the option name.
Definition argList.C:433
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
Configuration options for the ensightCase.
Configuration options for the ensightMesh.
bool useBoundaryMesh() const noexcept
Using boundary?
const wordRes & faceZoneSelection() const noexcept
Selection of face zones. Empty if unspecified.
bool useInternalMesh() const noexcept
Using internal?
void print(Ostream &os) const
Report values.
const wordRes & patchSelection() const noexcept
Selection of patches. Empty if unspecified.
const wordRes & patchExclude() const noexcept
Excluded patches. Empty if unspecified.
bool useCellZones() const noexcept
Using cellZones?
const wordRes & cellZoneSelection() const noexcept
Selection of cell zones. Empty if unspecified.
A class for handling file names.
Definition fileName.H:75
Memory usage information for the current process, and the system memory that is free.
Definition memInfo.H:59
int64_t peak() const noexcept
Peak memory at last update - (VmPeak in /proc/PID/status).
Definition memInfo.H:119
int64_t size() const noexcept
Memory size at last update - (VmSize in /proc/PID/status).
Definition memInfo.H:124
Database for mesh data, solution data, solver performance and other reduced data.
Definition meshState.H:56
static const word & regionName(const word &region)
The mesh region name or word::null if polyMesh::defaultRegion.
Definition polyMesh.C:796
readUpdateState
Enumeration defining the state of the mesh after a read update.
Definition polyMesh.H:92
static void addOptions(const bool constant=true, const bool withZero=false)
Add timeSelector options to argList::validOptions.
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...
Implements a timeout mechanism via sigalarm.
Definition timer.H:83
A wordRe is a Foam::word, but can contain a regular expression for matching words or strings.
Definition wordRe.H:81
A List of wordRe with additional matching capabilities.
Definition wordRes.H:56
A class for handling words, derived from Foam::string.
Definition word.H:66
dynamicFvMesh & mesh
engineTime & runTime
Foam::word regionName(args.getOrDefault< word >("region", 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)
const word & regionDir
List< PtrDynList< ensightFaMesh > > ensightMeshesFa(regionNames.size())
PtrList< ensightCase > ensightCases(regionNames.size())
PtrList< ensightMesh > ensightMeshes(regionNames.size())
List< PtrDynList< ensightCase > > ensightCasesFa(regionNames.size())
wordList areaRegionNames
wordList regionNames
bool allowFaModels() noexcept
The enable/disable state for regionFaModel (default: true).
Namespace for OpenFOAM.
messageStream Info
Information stream (stdout output on master, null elsewhere).
List< instant > instantList
List of instants.
Definition instantList.H:41
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition FlatOutput.H:217
cpuTimePosix cpuTime
Selection of preferred clock mechanism for the elapsed cpu time.
Definition cpuTimeFwd.H:38
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
label timeIndex
word format(conversionProperties.get< word >("format"))
Foam::argList args(argc, argv)
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
Functor wrapper of allow/deny lists of wordRe for filtering.
Definition wordRes.H:275