Merge branch 'master' of ssh://git.code.sf.net/p/foam-extend/foam-extend-3.2
[foam-extend-3.2.git] / applications / utilities / postProcessing / dataConversion / foamToEnsight / foamToEnsight.C
blobf5803a83b83186824df78c237efd42bf5db55384
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | foam-extend: Open Source CFD
4    \\    /   O peration     | Version:     3.2
5     \\  /    A nd           | Web:         http://www.foam-extend.org
6      \\/     M anipulation  | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9     This file is part of foam-extend.
11     foam-extend is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation, either version 3 of the License, or (at your
14     option) any later version.
16     foam-extend is distributed in the hope that it will be useful, but
17     WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19     General Public License for more details.
21     You should have received a copy of the GNU General Public License
22     along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.
24 Description
25     Translates FOAM data to EnSight format.
27     An Ensight part is created for the internalMesh and for each patch.
29 Usage
30     - foamToEnsight [OPTION] \n
31     Translates FOAM data to Ensight format
33     @param -ascii \n
34     Write Ensight data in ASCII format instead of "C Binary"
36     @param -patches patchList \n
37     Specify particular patches to write.
38     Specifying an empty list suppresses writing the internalMesh.
40     @param -noPatches \n
41     Suppress writing any patches.
43 Note
44     Parallel support for cloud data is not supported
45     - writes to @a EnSight directory to avoid collisions with foamToEnsightParts
47 \*---------------------------------------------------------------------------*/
49 #include "argList.H"
50 #include "timeSelector.H"
51 #include "IOobjectList.H"
52 #include "IOmanip.H"
53 #include "OFstream.H"
55 #include "volFields.H"
57 #include "labelIOField.H"
58 #include "scalarIOField.H"
59 #include "tensorIOField.H"
61 #include "ensightMesh.H"
62 #include "ensightField.H"
64 #include "ensightParticlePositions.H"
65 #include "ensightCloudField.H"
67 #include "fvc.H"
69 using namespace Foam;
71 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
73 bool inFileNameList
75     const fileNameList& nameList,
76     const word& name
79     forAll(nameList, i)
80     {
81         if (nameList[i] == name)
82         {
83             return true;
84         }
85     }
87     return false;
91 // Main program:
93 int main(int argc, char *argv[])
95     argList::validOptions.insert("ascii", "" );
96     argList::validOptions.insert("patches", "patchList");
97     argList::validOptions.insert("noPatches", "");
99 #   include "addTimeOptions.H"
100 #   include "setRootCase.H"
102     // Check options
103     bool binary = !args.optionFound("ascii");
105 #   include "createTime.H"
107     // get the available time-steps
108     instantList Times = runTime.times();
110 #   include "checkTimeOptions.H"
112     runTime.setTime(Times[startTime], startTime);
114 #   include "createNamedMesh.H"
116     // Mesh instance (region0 gets filtered out)
117     fileName regionPrefix = "";
119     if (regionName != polyMesh::defaultRegion)
120     {
121         regionPrefix = regionName;
122     }
124     const label nVolFieldTypes = 5;
125     const word volFieldTypes[] =
126     {
127         volScalarField::typeName,
128         volVectorField::typeName,
129         volSphericalTensorField::typeName,
130         volSymmTensorField::typeName,
131         volTensorField::typeName
132     };
134     // Path to EnSight folder at case level only
135     // - For parallel cases, data only written from master
136     fileName ensightDir = args.rootPath()/args.globalCaseName()/"EnSight";
138     if (Pstream::master())
139     {
140         if (isDir(ensightDir))
141         {
142             rmDir(ensightDir);
143         }
145         mkDir(ensightDir);
146     }
148     // Start of case file header output
149     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
151     const word prepend = args.globalCaseName() + '.';
153     OFstream *ensightCaseFilePtr = NULL;
154     if (Pstream::master())
155     {
156         fileName caseFileName = prepend + "case";
157         Info<< nl << "write case: " << caseFileName.c_str() << endl;
159         // the case file is always ASCII
160         ensightCaseFilePtr = new OFstream
161         (
162             ensightDir/caseFileName,
163             ios_base::out|ios_base::trunc,
164             IOstream::ASCII
165         );
167         *ensightCaseFilePtr
168             << "FORMAT" << nl
169             << "type: ensight gold" << nl << nl;
170     }
172     OFstream& ensightCaseFile = *ensightCaseFilePtr;
174     // Construct the EnSight mesh
175     ensightMesh eMesh(mesh, args, binary);
177     // Set Time to the last time before looking for the lagrangian objects
178     runTime.setTime(Times[Times.size()-1], Times.size()-1);
180     IOobjectList objects(mesh, runTime.timeName());
182 #   include "checkMeshMoving.H"
184     wordHashSet allCloudNames;
185     if (Pstream::master())
186     {
187         word geomFileName = prepend + "000";
189         // test pre check variable if there is a moving mesh
190         if (meshMoving)
191         {
192             geomFileName = prepend + "***";
193         }
195         ensightCaseFile
196             << "GEOMETRY" << nl
197             << "model:        1     "
198             << (geomFileName + ".mesh").c_str() << nl;
199     }
201     // Identify if lagrangian data exists at each time, and add clouds
202     // to the 'allCloudNames' hash set
203     for (label n=startTime; n<endTime; n++)
204     {
205         runTime.setTime(Times[n], n);
207         fileNameList cloudDirs = readDir
208         (
209             runTime.timePath()/regionPrefix/cloud::prefix,
210             fileName::DIRECTORY
211         );
213         forAll(cloudDirs, cloudI)
214         {
215             IOobjectList cloudObjs
216             (
217                 mesh,
218                 runTime.timeName(),
219                 cloud::prefix/cloudDirs[cloudI]
220             );
222             IOobject* positionsPtr = cloudObjs.lookup("positions");
224             if (positionsPtr)
225             {
226                 allCloudNames.insert(cloudDirs[cloudI]);
227             }
228         }
229     }
231     HashTable<HashTable<word> > allCloudFields;
232     forAllConstIter(wordHashSet, allCloudNames, cloudIter)
233     {
234         // Add the name of the cloud(s) to the case file header
235         if (Pstream::master())
236         {
237             ensightCaseFile
238             <<  (
239                     "measured:     1     "
240                   + prepend
241                   + "***."
242                   + cloudIter.key()
243                 ).c_str()
244             << nl;
245         }
247         // Create a new hash table for each cloud
248         allCloudFields.insert(cloudIter.key(), HashTable<word>());
250         // Identify the new cloud in the hash table
251         HashTable<HashTable<word> >::iterator newCloudIter =
252             allCloudFields.find(cloudIter.key());
254         // Loop over all times to build list of fields and field types
255         // for each cloud
256         for (label n=startTime; n<endTime; n++)
257         {
258             runTime.setTime(Times[n], n);
260             IOobjectList cloudObjs
261             (
262                 mesh,
263                 runTime.timeName(),
264                 cloud::prefix/cloudIter.key()
265             );
267             forAllConstIter(IOobjectList, cloudObjs, fieldIter)
268             {
269                 const IOobject obj = *fieldIter();
271                 if (obj.name() != "positions")
272                 {
273                     // Add field and field type
274                     newCloudIter().insert
275                     (
276                         obj.name(),
277                         obj.headerClassName()
278                     );
279                 }
280             }
281         }
282     }
284     label nTimeSteps = 0;
285     for (label n=startTime; n<endTime; n++)
286     {
287         nTimeSteps++;
288         runTime.setTime(Times[n], n);
289         label timeIndex = n - startTime;
291         word timeName = itoa(timeIndex);
292         word timeFile = prepend + timeName;
294         Info<< "Translating time = " << runTime.timeName() << nl;
296 #       include "moveMesh.H"
298         if (timeIndex == 0 || mesh.moving())
299         {
300             eMesh.write
301             (
302                 ensightDir,
303                 prepend,
304                 timeIndex,
305                 ensightCaseFile
306             );
307         }
310         // Start of field data output
311         // ~~~~~~~~~~~~~~~~~~~~~~~~~~
313         if (timeIndex == 0 && Pstream::master())
314         {
315             ensightCaseFile<< nl << "VARIABLE" << nl;
316         }
319         // Cell field data output
320         // ~~~~~~~~~~~~~~~~~~~~~~
322         for (label i=0; i<nVolFieldTypes; i++)
323         {
324             wordList fieldNames = objects.names(volFieldTypes[i]);
326             for (label j=0; j<fieldNames.size(); j++)
327             {
328                 word fieldName = fieldNames[j];
330 #               include "checkData.H"
332                 if (!variableGood)
333                 {
334                     continue;
335                 }
337                 IOobject fieldObject
338                 (
339                     fieldName,
340                     mesh.time().timeName(),
341                     mesh,
342                     IOobject::MUST_READ,
343                     IOobject::NO_WRITE
344                 );
346                 if (volFieldTypes[i] == volScalarField::typeName)
347                 {
348                     ensightField<scalar>
349                     (
350                         fieldObject,
351                         eMesh,
352                         ensightDir,
353                         prepend,
354                         timeIndex,
355                         binary,
356                         ensightCaseFile
357                     );
358                 }
359                 else if (volFieldTypes[i] == volVectorField::typeName)
360                 {
361                     ensightField<vector>
362                     (
363                         fieldObject,
364                         eMesh,
365                         ensightDir,
366                         prepend,
367                         timeIndex,
368                         binary,
369                         ensightCaseFile
370                     );
371                 }
372                 else if (volFieldTypes[i] == volSphericalTensorField::typeName)
373                 {
374                     ensightField<sphericalTensor>
375                     (
376                         fieldObject,
377                         eMesh,
378                         ensightDir,
379                         prepend,
380                         timeIndex,
381                         binary,
382                         ensightCaseFile
383                     );
384                 }
385                 else if (volFieldTypes[i] == volSymmTensorField::typeName)
386                 {
387                     ensightField<symmTensor>
388                     (
389                         fieldObject,
390                         eMesh,
391                         ensightDir,
392                         prepend,
393                         timeIndex,
394                         binary,
395                         ensightCaseFile
396                     );
397                 }
398                 else if (volFieldTypes[i] == volTensorField::typeName)
399                 {
400                     ensightField<tensor>
401                     (
402                         fieldObject,
403                         eMesh,
404                         ensightDir,
405                         prepend,
406                         timeIndex,
407                         binary,
408                         ensightCaseFile
409                     );
410                 }
411             }
412         }
415         // Cloud field data output
416         // ~~~~~~~~~~~~~~~~~~~~~~~
418         forAllConstIter(HashTable<HashTable<word> >, allCloudFields, cloudIter)
419         {
420             const word& cloudName = cloudIter.key();
422             fileNameList currentCloudDirs = readDir
423             (
424                 runTime.timePath()/regionPrefix/cloud::prefix,
425                 fileName::DIRECTORY
426             );
428             bool cloudExists = inFileNameList(currentCloudDirs, cloudName);
429             ensightParticlePositions
430             (
431                 mesh,
432                 ensightDir,
433                 timeFile,
434                 cloudName,
435                 cloudExists
436             );
438             forAllConstIter(HashTable<word>, cloudIter(), fieldIter)
439             {
440                 const word& fieldName = fieldIter.key();
441                 const word& fieldType = fieldIter();
443                 IOobject fieldObject
444                 (
445                     fieldName,
446                     mesh.time().timeName(),
447                     cloud::prefix/cloudName,
448                     mesh,
449                     IOobject::MUST_READ
450                 );
452                 bool fieldExists = fieldObject.headerOk();
453                 if (fieldType == scalarIOField::typeName)
454                 {
455                     ensightCloudField<scalar>
456                     (
457                         fieldObject,
458                         ensightDir,
459                         prepend,
460                         timeIndex,
461                         cloudName,
462                         ensightCaseFile,
463                         fieldExists
464                     );
465                 }
466                 else if (fieldType == vectorIOField::typeName)
467                 {
468                     ensightCloudField<vector>
469                     (
470                         fieldObject,
471                         ensightDir,
472                         prepend,
473                         timeIndex,
474                         cloudName,
475                         ensightCaseFile,
476                         fieldExists
477                     );
478                 }
479                 else
480                 {
481                     Info<< "Unable to convert field type " << fieldType
482                         << " for field " << fieldName << endl;
483                 }
484             }
485         }
486     }
488 #   include "ensightCaseTail.H"
490     if (Pstream::master())
491     {
492         delete ensightCaseFilePtr;
493     }
495     Info<< "End\n" << endl;
497     return 0;
501 // ************************************************************************* //