1 /*---------------------------------------------------------------------------*\
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 -------------------------------------------------------------------------------
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/>.
25 Translates FOAM data to EnSight format.
27 An Ensight part is created for the internalMesh and for each patch.
30 - foamToEnsight [OPTION] \n
31 Translates FOAM data to Ensight format
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.
41 Suppress writing any patches.
44 Parallel support for cloud data is not supported
45 - writes to @a EnSight directory to avoid collisions with foamToEnsightParts
47 \*---------------------------------------------------------------------------*/
50 #include "timeSelector.H"
51 #include "IOobjectList.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"
71 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
75 const fileNameList& nameList,
81 if (nameList[i] == name)
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"
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)
121 regionPrefix = regionName;
124 const label nVolFieldTypes = 5;
125 const word volFieldTypes[] =
127 volScalarField::typeName,
128 volVectorField::typeName,
129 volSphericalTensorField::typeName,
130 volSymmTensorField::typeName,
131 volTensorField::typeName
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())
140 if (isDir(ensightDir))
148 // Start of case file header output
149 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
151 const word prepend = args.globalCaseName() + '.';
153 OFstream *ensightCaseFilePtr = NULL;
154 if (Pstream::master())
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
162 ensightDir/caseFileName,
163 ios_base::out|ios_base::trunc,
169 << "type: ensight gold" << nl << nl;
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())
187 word geomFileName = prepend + "000";
189 // test pre check variable if there is a moving mesh
192 geomFileName = prepend + "***";
198 << (geomFileName + ".mesh").c_str() << nl;
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++)
205 runTime.setTime(Times[n], n);
207 fileNameList cloudDirs = readDir
209 runTime.timePath()/regionPrefix/cloud::prefix,
213 forAll(cloudDirs, cloudI)
215 IOobjectList cloudObjs
219 cloud::prefix/cloudDirs[cloudI]
222 IOobject* positionsPtr = cloudObjs.lookup("positions");
226 allCloudNames.insert(cloudDirs[cloudI]);
231 HashTable<HashTable<word> > allCloudFields;
232 forAllConstIter(wordHashSet, allCloudNames, cloudIter)
234 // Add the name of the cloud(s) to the case file header
235 if (Pstream::master())
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
256 for (label n=startTime; n<endTime; n++)
258 runTime.setTime(Times[n], n);
260 IOobjectList cloudObjs
264 cloud::prefix/cloudIter.key()
267 forAllConstIter(IOobjectList, cloudObjs, fieldIter)
269 const IOobject obj = *fieldIter();
271 if (obj.name() != "positions")
273 // Add field and field type
274 newCloudIter().insert
277 obj.headerClassName()
284 label nTimeSteps = 0;
285 for (label n=startTime; n<endTime; n++)
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())
310 // Start of field data output
311 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
313 if (timeIndex == 0 && Pstream::master())
315 ensightCaseFile<< nl << "VARIABLE" << nl;
319 // Cell field data output
320 // ~~~~~~~~~~~~~~~~~~~~~~
322 for (label i=0; i<nVolFieldTypes; i++)
324 wordList fieldNames = objects.names(volFieldTypes[i]);
326 for (label j=0; j<fieldNames.size(); j++)
328 word fieldName = fieldNames[j];
330 # include "checkData.H"
340 mesh.time().timeName(),
346 if (volFieldTypes[i] == volScalarField::typeName)
359 else if (volFieldTypes[i] == volVectorField::typeName)
372 else if (volFieldTypes[i] == volSphericalTensorField::typeName)
374 ensightField<sphericalTensor>
385 else if (volFieldTypes[i] == volSymmTensorField::typeName)
387 ensightField<symmTensor>
398 else if (volFieldTypes[i] == volTensorField::typeName)
415 // Cloud field data output
416 // ~~~~~~~~~~~~~~~~~~~~~~~
418 forAllConstIter(HashTable<HashTable<word> >, allCloudFields, cloudIter)
420 const word& cloudName = cloudIter.key();
422 fileNameList currentCloudDirs = readDir
424 runTime.timePath()/regionPrefix/cloud::prefix,
428 bool cloudExists = inFileNameList(currentCloudDirs, cloudName);
429 ensightParticlePositions
438 forAllConstIter(HashTable<word>, cloudIter(), fieldIter)
440 const word& fieldName = fieldIter.key();
441 const word& fieldType = fieldIter();
446 mesh.time().timeName(),
447 cloud::prefix/cloudName,
452 bool fieldExists = fieldObject.headerOk();
453 if (fieldType == scalarIOField::typeName)
455 ensightCloudField<scalar>
466 else if (fieldType == vectorIOField::typeName)
468 ensightCloudField<vector>
481 Info<< "Unable to convert field type " << fieldType
482 << " for field " << fieldName << endl;
488 # include "ensightCaseTail.H"
490 if (Pstream::master())
492 delete ensightCaseFilePtr;
495 Info<< "End\n" << endl;
501 // ************************************************************************* //