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 | Copyright (C) 2011-2016 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Application
25  foamToEnsight
26 
27 Description
28  Translates OpenFOAM data to EnSight format.
29 
30  An Ensight part is created for the internalMesh and for each patch.
31 
32 Usage
33  \b foamToEnsight [OPTION]
34 
35  Options:
36  - \par -ascii
37  Write Ensight data in ASCII format instead of "C Binary"
38 
39  - \par -patches patchList
40  Specify particular patches to write.
41  Specifying an empty list suppresses writing the internalMesh.
42 
43  - \par -noPatches
44  Suppress writing any patches.
45 
46  - \par -faceZones zoneList
47  Specify faceZones to write, with wildcards
48 
49  - \par -cellZone zoneName
50  Specify single cellZone to write (not lagrangian)
51 
52 Note
53  Parallel support for cloud data is not supported
54  - writes to \a EnSight directory to avoid collisions with foamToEnsightParts
55 
56 \*---------------------------------------------------------------------------*/
57 
58 #include "argList.H"
59 #include "timeSelector.H"
60 #include "IOobjectList.H"
61 #include "IOmanip.H"
62 #include "OFstream.H"
63 
64 #include "volFields.H"
65 
66 #include "labelIOField.H"
67 #include "scalarIOField.H"
68 #include "tensorIOField.H"
69 
70 #include "ensightMesh.H"
71 #include "ensightField.H"
72 
74 #include "ensightCloudField.H"
75 
76 #include "fvc.H"
77 
78 #include "cellSet.H"
79 #include "fvMeshSubset.H"
80 
81 using namespace Foam;
82 
83 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
84 
85 bool inFileNameList
86 (
87  const fileNameList& nameList,
88  const word& name
89 )
90 {
91  forAll(nameList, i)
92  {
93  if (nameList[i] == name)
94  {
95  return true;
96  }
97  }
98 
99  return false;
100 }
101 
102 
103 
104 int main(int argc, char *argv[])
105 {
107  #include "addRegionOption.H"
108 
110  (
111  "ascii",
112  "write in ASCII format instead of 'C Binary'"
113  );
115  (
116  "nodeValues",
117  "write values in nodes"
118  );
120  (
121  "noPatches",
122  "suppress writing any patches"
123  );
125  (
126  "patches",
127  "wordReList",
128  "specify particular patches to write - eg '(outlet \"inlet.*\")'. "
129  "An empty list suppresses writing the internalMesh."
130  );
132  (
133  "faceZones",
134  "wordReList",
135  "specify faceZones to write - eg '( slice \"mfp-.*\" )'."
136  );
138  (
139  "fields",
140  "wordReList",
141  "specify fields to export (all by default) - eg '( \"U.*\" )'."
142  );
144  (
145  "cellZone",
146  "word",
147  "specify cellZone to write"
148  );
149 
150  #include "setRootCase.H"
151 
152  // Check options
153  const bool binary = !args.optionFound("ascii");
154  const bool nodeValues = args.optionFound("nodeValues");
155 
156  #include "createTime.H"
157 
158  instantList Times = timeSelector::select0(runTime, args);
159 
160  #include "createNamedMesh.H"
161 
162  // Mesh instance (region0 gets filtered out)
163  fileName regionPrefix = "";
164 
166  {
167  regionPrefix = regionName;
168  }
169 
170  const label nVolFieldTypes = 5;
171  const word volFieldTypes[] =
172  {
177  volTensorField::typeName
178  };
179 
180  // Path to EnSight directory at case level only
181  // - For parallel cases, data only written from master
182  fileName ensightDir = args.rootPath()/args.globalCaseName()/"EnSight";
183 
184  if (Pstream::master())
185  {
186  if (isDir(ensightDir))
187  {
188  rmDir(ensightDir);
189  }
190 
191  mkDir(ensightDir);
192  }
193 
194  // Start of case file header output
195  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
196 
197  const word prepend = args.globalCaseName() + '.';
198 
199  OFstream *ensightCaseFilePtr = NULL;
200  if (Pstream::master())
201  {
202  fileName caseFileName = prepend + "case";
203  Info<< nl << "write case: " << caseFileName.c_str() << endl;
204 
205  // the case file is always ASCII
206  ensightCaseFilePtr = new OFstream
207  (
208  ensightDir/caseFileName,
210  );
211 
212  *ensightCaseFilePtr
213  << "FORMAT" << nl
214  << "type: ensight gold" << nl << nl;
215  }
216 
217  OFstream& ensightCaseFile = *ensightCaseFilePtr;
218 
219  // Construct the EnSight mesh
220  const bool selectedPatches = args.optionFound("patches");
221  wordReList patchPatterns;
222  if (selectedPatches)
223  {
224  patchPatterns = wordReList(args.optionLookup("patches")());
225  }
226  const bool selectedZones = args.optionFound("faceZones");
227  wordReList zonePatterns;
228  if (selectedZones)
229  {
230  zonePatterns = wordReList(args.optionLookup("faceZones")());
231  }
232 
233  const bool selectedFields = args.optionFound("fields");
234  wordReList fieldPatterns;
235  if (selectedFields)
236  {
237  fieldPatterns = wordReList(args.optionLookup("fields")());
238  }
239 
240  word cellZoneName;
241  const bool doCellZone = args.optionReadIfPresent("cellZone", cellZoneName);
242 
243  fvMeshSubset meshSubsetter(mesh);
244  if (doCellZone)
245  {
246  Info<< "Converting cellZone " << cellZoneName
247  << " only (puts outside faces into patch "
248  << mesh.boundaryMesh()[0].name()
249  << ")" << endl;
250  const cellZone& cz = mesh.cellZones()[cellZoneName];
251  cellSet c0(mesh, "c0", labelHashSet(cz));
252  meshSubsetter.setLargeCellSubset(c0, 0);
253  }
254 
255  ensightMesh eMesh
256  (
257  (
258  meshSubsetter.hasSubMesh()
259  ? meshSubsetter.subMesh()
260  : meshSubsetter.baseMesh()
261  ),
262  args.optionFound("noPatches"),
263  selectedPatches,
264  patchPatterns,
265  selectedZones,
266  zonePatterns,
267  binary
268  );
269 
270  // Set Time to the last time before looking for the lagrangian objects
271  runTime.setTime(Times.last(), Times.size()-1);
272 
273  IOobjectList objects(mesh, runTime.timeName());
274 
275  #include "checkMeshMoving.H"
276 
277  if (meshMoving)
278  {
279  Info<< "Detected a moving mesh (multiple polyMesh/points files)."
280  << " Writing meshes for every timestep." << endl;
281  }
282 
283 
284  wordHashSet allCloudNames;
285  if (Pstream::master())
286  {
287  word geomFileName = prepend + "0000";
288 
289  // test pre check variable if there is a moving mesh
290  if (meshMoving)
291  {
292  geomFileName = prepend + "****";
293  }
294 
295  ensightCaseFile
296  << "GEOMETRY" << nl
297  << "model: 1 "
298  << (geomFileName + ".mesh").c_str() << nl;
299  }
300 
301  // Identify if lagrangian data exists at each time, and add clouds
302  // to the 'allCloudNames' hash set
303  forAll(Times, timeI)
304  {
305  runTime.setTime(Times[timeI], timeI);
306 
307  fileNameList cloudDirs = readDir
308  (
309  runTime.timePath()/regionPrefix/cloud::prefix,
311  );
312 
313  forAll(cloudDirs, cloudI)
314  {
315  IOobjectList cloudObjs
316  (
317  mesh,
318  runTime.timeName(),
319  cloud::prefix/cloudDirs[cloudI]
320  );
321 
322  IOobject* positionsPtr = cloudObjs.lookup(word("positions"));
323 
324  if (positionsPtr)
325  {
326  allCloudNames.insert(cloudDirs[cloudI]);
327  }
328  }
329  }
330 
331  HashTable<HashTable<word>> allCloudFields;
332  forAllConstIter(wordHashSet, allCloudNames, cloudIter)
333  {
334  // Add the name of the cloud(s) to the case file header
335  if (Pstream::master())
336  {
337  ensightCaseFile
338  << (
339  "measured: 1 "
340  + prepend
341  + "****."
342  + cloudIter.key()
343  ).c_str()
344  << nl;
345  }
346 
347  // Create a new hash table for each cloud
348  allCloudFields.insert(cloudIter.key(), HashTable<word>());
349 
350  // Identify the new cloud in the hash table
351  HashTable<HashTable<word>>::iterator newCloudIter =
352  allCloudFields.find(cloudIter.key());
353 
354  // Loop over all times to build list of fields and field types
355  // for each cloud
356  forAll(Times, timeI)
357  {
358  runTime.setTime(Times[timeI], timeI);
359 
360  IOobjectList cloudObjs
361  (
362  mesh,
363  runTime.timeName(),
364  cloud::prefix/cloudIter.key()
365  );
366 
367  forAllConstIter(IOobjectList, cloudObjs, fieldIter)
368  {
369  const IOobject obj = *fieldIter();
370 
371  if (obj.name() != "positions")
372  {
373  // Add field and field type
374  newCloudIter().insert
375  (
376  obj.name(),
377  obj.headerClassName()
378  );
379  }
380  }
381  }
382  }
383 
384  label nTimeSteps = 0;
385  forAll(Times, timeIndex)
386  {
387  nTimeSteps++;
388  runTime.setTime(Times[timeIndex], timeIndex);
389 
390  word timeName = itoa(timeIndex);
391  word timeFile = prepend + timeName;
392 
393  Info<< "Translating time = " << runTime.timeName() << nl;
394 
395  polyMesh::readUpdateState meshState = mesh.readUpdate();
396  if (timeIndex != 0 && meshSubsetter.hasSubMesh())
397  {
398  Info<< "Converting cellZone " << cellZoneName
399  << " only (puts outside faces into patch "
400  << mesh.boundaryMesh()[0].name()
401  << ")" << endl;
402  const cellZone& cz = mesh.cellZones()[cellZoneName];
403  cellSet c0(mesh, "c0", labelHashSet(cz));
404  meshSubsetter.setLargeCellSubset(c0, 0);
405  }
406 
407 
408  if (meshState != polyMesh::UNCHANGED)
409  {
410  eMesh.correct();
411  }
412 
413  if (timeIndex == 0 || meshMoving)
414  {
415  eMesh.write
416  (
417  ensightDir,
418  prepend,
419  timeIndex,
420  meshMoving,
421  ensightCaseFile
422  );
423  }
424 
425 
426  // Start of field data output
427  // ~~~~~~~~~~~~~~~~~~~~~~~~~~
428 
429  if (timeIndex == 0 && Pstream::master())
430  {
431  ensightCaseFile<< nl << "VARIABLE" << nl;
432  }
433 
434 
435  // Cell field data output
436  // ~~~~~~~~~~~~~~~~~~~~~~
437 
438  for (label i=0; i<nVolFieldTypes; i++)
439  {
440  wordList fieldNames = objects.names(volFieldTypes[i]);
441 
442  forAll(fieldNames, j)
443  {
444  const word& fieldName = fieldNames[j];
445 
446  // Check if the field has to be exported
447  if (selectedFields)
448  {
449  if (!findStrings(fieldPatterns, fieldName))
450  {
451  continue;
452  }
453  }
454 
455  #include "checkData.H"
456 
457  if (!variableGood)
458  {
459  continue;
460  }
461 
463  (
464  fieldName,
465  mesh.time().timeName(),
466  mesh,
469  );
470 
471  if (volFieldTypes[i] == volScalarField::typeName)
472  {
473  volScalarField vf(fieldObject, mesh);
474  ensightField<scalar>
475  (
476  volField(meshSubsetter, vf),
477  eMesh,
478  ensightDir,
479  prepend,
480  timeIndex,
481  binary,
482  nodeValues,
483  ensightCaseFile
484  );
485  }
486  else if (volFieldTypes[i] == volVectorField::typeName)
487  {
488  volVectorField vf(fieldObject, mesh);
489  ensightField<vector>
490  (
491  volField(meshSubsetter, vf),
492  eMesh,
493  ensightDir,
494  prepend,
495  timeIndex,
496  binary,
497  nodeValues,
498  ensightCaseFile
499  );
500  }
501  else if (volFieldTypes[i] == volSphericalTensorField::typeName)
502  {
504  ensightField<sphericalTensor>
505  (
506  volField(meshSubsetter, vf),
507  eMesh,
508  ensightDir,
509  prepend,
510  timeIndex,
511  binary,
512  nodeValues,
513  ensightCaseFile
514  );
515  }
516  else if (volFieldTypes[i] == volSymmTensorField::typeName)
517  {
519  ensightField<symmTensor>
520  (
521  volField(meshSubsetter, vf),
522  eMesh,
523  ensightDir,
524  prepend,
525  timeIndex,
526  binary,
527  nodeValues,
528  ensightCaseFile
529  );
530  }
531  else if (volFieldTypes[i] == volTensorField::typeName)
532  {
533  volTensorField vf(fieldObject, mesh);
534  ensightField<tensor>
535  (
536  volField(meshSubsetter, vf),
537  eMesh,
538  ensightDir,
539  prepend,
540  timeIndex,
541  binary,
542  nodeValues,
543  ensightCaseFile
544  );
545  }
546  }
547  }
548 
549 
550  // Cloud field data output
551  // ~~~~~~~~~~~~~~~~~~~~~~~
552 
553  forAllConstIter(HashTable<HashTable<word>>, allCloudFields, cloudIter)
554  {
555  const word& cloudName = cloudIter.key();
556 
557  fileNameList currentCloudDirs = readDir
558  (
559  runTime.timePath()/regionPrefix/cloud::prefix,
561  );
562 
563  bool cloudExists = inFileNameList(currentCloudDirs, cloudName);
565  (
566  mesh,
567  ensightDir,
568  timeFile,
569  cloudName,
570  cloudExists
571  );
572 
573  forAllConstIter(HashTable<word>, cloudIter(), fieldIter)
574  {
575  const word& fieldName = fieldIter.key();
576  const word& fieldType = fieldIter();
577 
579  (
580  fieldName,
581  mesh.time().timeName(),
583  mesh,
585  );
586 
587  bool fieldExists = fieldObject.headerOk();
588  if (fieldType == scalarIOField::typeName)
589  {
590  ensightCloudField<scalar>
591  (
592  fieldObject,
593  ensightDir,
594  prepend,
595  timeIndex,
596  cloudName,
597  ensightCaseFile,
598  fieldExists
599  );
600  }
601  else if (fieldType == vectorIOField::typeName)
602  {
603  ensightCloudField<vector>
604  (
605  fieldObject,
606  ensightDir,
607  prepend,
608  timeIndex,
609  cloudName,
610  ensightCaseFile,
611  fieldExists
612  );
613  }
614  else
615  {
616  Info<< "Unable to convert field type " << fieldType
617  << " for field " << fieldName << endl;
618  }
619  }
620  }
621  }
622 
623  #include "ensightCaseTail.H"
624 
625  if (Pstream::master())
626  {
627  delete ensightCaseFilePtr;
628  }
629 
630  Info<< "End\n" << endl;
631 
632  return 0;
633 }
634 
635 
636 // ************************************************************************* //
A HashTable with keys but without contents.
Definition: HashSet.H:59
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
A class for handling file names.
Definition: fileName.H:69
List of IOobjects with searching and retrieving facilities.
Definition: IOobjectList.H:50
static const char *const typeName
Definition: Field.H:94
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
word itoa(const label n)
Foam::word regionName
Output to file stream.
Definition: OFstream.H:81
Foam::tmp< Foam::GeometricField< Type, Foam::fvPatchField, Foam::volMesh > > volField(const Foam::fvMeshSubset &, const Foam::GeometricField< Type, Foam::fvPatchField, Foam::volMesh > &vf)
Wrapper to get hold of the field or the subsetted field.
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
bool optionReadIfPresent(const word &opt, T &) const
Read a value from the named option if present.
Definition: argListI.H:198
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:306
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:411
void ensightParticlePositions(const polyMesh &mesh, const fileName &dataDir, const fileName &subDir, const word &cloudName, IOstream::streamFormat format)
const word cloudName(propsDict.lookup("cloudName"))
bool isDir(const fileName &)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:486
IOobject fieldObject(fieldNames[var2field[nVar]], runTime.timeName(), mesh, IOobject::MUST_READ, IOobject::NO_WRITE)
const fileName & rootPath() const
Return root path.
Definition: argListI.H:36
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:116
const word & headerClassName() const
Return name of the class name read from header.
Definition: IOobject.H:266
bool findStrings(const wordReListMatcher &matcher, const std::string &str)
Return true if string matches one of the regular expressions.
Definition: stringListOps.H:52
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
Definition: HashTable.C:138
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
Definition: HashSet.H:210
dynamicFvMesh & mesh
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:108
A class for handling words, derived from string.
Definition: word.H:59
static void addOption(const word &opt, const string &param="", const string &usage="")
Add to an option to validOptions with usage information.
Definition: argList.C:93
word timeName
Definition: getTimeIndex.H:3
const fileName & globalCaseName() const
Return case name.
Definition: argListI.H:48
An STL-conforming hash table.
Definition: HashTable.H:61
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
bool rmDir(const fileName &)
Remove a dirctory and its contents.
Definition: POSIX.C:839
Istream and Ostream manipulators taking arguments.
static const char nl
Definition: Ostream.H:262
static const word prefix
The prefix to local: lagrangian.
Definition: cloud.H:71
Post-processing mesh subset tool. Given the original mesh and the list of selected cells...
Definition: fvMeshSubset.H:73
static instantList select0(Time &runTime, const argList &args)
Return the set of times selected based on the argList options.
Definition: timeSelector.C:253
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:295
A subset of mesh cells.
Definition: cellZone.H:61
A collection of cell labels.
Definition: cellSet.H:48
label timeIndex
Definition: getTimeIndex.H:4
IStringStream optionLookup(const word &opt) const
Return an IStringStream from the named option.
Definition: argListI.H:114
messageStream Info
bool headerOk()
Read and check header info.
Definition: IOobject.C:400
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Definition: argList.C:83
List< wordRe > wordReList
A List of wordRe (word or regular expression)
Definition: wordReList.H:50
readUpdateState
Enumeration defining the state of the mesh after a read update.
Definition: polyMesh.H:88
T & last()
Return the last element of the list.
Definition: UListI.H:128
Foam::argList args(argc, argv)
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:91
bool variableGood
Definition: checkData.H:3
fileNameList readDir(const fileName &, const fileName::Type=fileName::FILE, const bool filtergz=true)
Read a directory and return the entries as a string list.
Definition: POSIX.C:527
const word & name() const
Return name.
Definition: IOobject.H:260
static void addOptions(const bool constant=true, const bool withZero=false)
Add the options handled by timeSelector to argList::validOptions.
Definition: timeSelector.C:114
Namespace for OpenFOAM.
bool meshMoving