1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
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
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 Translates OpenFOAM data to Ensight format.
30 An Ensight part is created for each cellZone and patch.
33 - foamToEnsightParts [OPTION] \n
34 Translates OpenFOAM data to Ensight format
37 Write Ensight data in ASCII format instead of "C Binary"
40 Exclude the often incomplete initial conditions.
42 @param -index \<start\>\n
43 Ignore the time index contained in the time file and use a
44 simple indexing when creating the @c Ensight/data/######## files.
47 Suppress writing the geometry. Can be useful for converting partial
48 results for a static geometry.
52 - writes to @a Ensight directory to avoid collisions with foamToEnsight.
54 \*---------------------------------------------------------------------------*/
57 #include "timeSelector.H"
59 #include "volFields.H"
62 #include "IOobjectList.H"
63 #include "scalarIOField.H"
64 #include "tensorIOField.H"
66 #include "ensightParts.H"
67 #include "ensightOutputFunctions.H"
71 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
75 int main(int argc, char *argv[])
78 // probably don't need -zeroTime though, since the fields are vetted
80 timeSelector::addOptions(true, false);
81 argList::noParallel();
82 argList::validOptions.insert("ascii", "");
83 argList::validOptions.insert("index", "start");
84 argList::validOptions.insert("noMesh", "");
86 // the volume field types that we handle
87 wordHashSet volFieldTypes;
88 volFieldTypes.insert(volScalarField::typeName);
89 volFieldTypes.insert(volVectorField::typeName);
90 volFieldTypes.insert(volSphericalTensorField::typeName);
91 volFieldTypes.insert(volSymmTensorField::typeName);
92 volFieldTypes.insert(volTensorField::typeName);
94 // the lagrangian field types that we handle
95 wordHashSet cloudFieldTypes;
96 cloudFieldTypes.insert(scalarIOField::typeName);
97 cloudFieldTypes.insert(vectorIOField::typeName);
98 cloudFieldTypes.insert(tensorIOField::typeName);
100 const char* geometryName = "geometry";
102 # include "setRootCase.H"
103 # include "createTime.H"
106 instantList timeDirs = timeSelector::select0(runTime, args);
108 // default to binary output, unless otherwise specified
109 IOstream::streamFormat format = IOstream::BINARY;
110 if (args.optionFound("ascii"))
112 format = IOstream::ASCII;
115 // control for renumbering iterations
116 bool optIndex = false;
117 label indexingNumber = 0;
118 if (args.optionFound("index"))
121 indexingNumber = args.optionRead<label>("index");
124 // always write the geometry, unless the -noMesh option is specified
125 bool optNoMesh = args.optionFound("noMesh");
127 fileName ensightDir = args.rootPath()/args.globalCaseName()/"Ensight";
128 fileName dataDir = ensightDir/"data";
129 fileName caseFileName = "Ensight.case";
130 fileName dataMask = fileName("data")/ensightFile::mask();
132 // Ensight and Ensight/data directories must exist
133 // do not remove old data - we might wish to convert new results
134 // or a particular time interval
135 if (isDir(ensightDir))
137 Info<<"Warning: reusing existing directory" << nl
138 << " " << ensightDir << endl;
143 # include "createNamedMesh.H"
145 // Mesh instance (region0 gets filtered out)
146 fileName regionPrefix;
148 if (regionName != polyMesh::defaultRegion)
150 regionPrefix = regionName;
153 // Construct the list of ensight parts for the entire mesh
154 ensightParts partsList(mesh);
156 // write summary information
158 OFstream partsInfoFile(ensightDir/"partsInfo");
161 << "// summary of ensight parts" << nl << nl;
162 partsList.writeSummary(partsInfoFile);
165 # include "checkHasMovingMesh.H"
166 # include "findFields.H"
168 if (hasMovingMesh && optNoMesh)
170 Info<< "mesh is moving: ignoring '-noMesh' option" << endl;
176 Map<scalar> timeIndices;
178 // Track the time indices used by the volume fields
179 DynamicList<label> fieldTimesUsed;
181 // Track the time indices used by each cloud
182 HashTable<DynamicList<label> > cloudTimesUsed;
184 // Create a new DynamicList for each cloud
185 forAllConstIter(HashTable<HashTable<word> >, cloudFields, cloudIter)
187 cloudTimesUsed.insert(cloudIter.key(), DynamicList<label>());
191 forAll(timeDirs, timeI)
193 runTime.setTime(timeDirs[timeI], timeI);
195 # include "getTimeIndex.H"
197 // remember the time index
198 fieldTimesUsed.append(timeIndex);
200 // the data/ITER subdirectory must exist
201 fileName subDir = ensightFile::subDir(timeIndex);
202 mkDir(dataDir/subDir);
204 // place a timestamp in the directory for future reference
206 OFstream timeStamp(dataDir/subDir/"time");
208 << "# timestep time" << nl
209 << subDir.c_str() << " " << runTime.timeName() << nl;
212 # include "moveMesh.H"
214 if (timeI == 0 || mesh.moving())
218 partsList.recalculate(mesh);
226 geomDir = dataDir/subDir;
229 ensightGeoFile geoFile(ensightDir/geomDir/geometryName, format);
230 partsList.writeGeometry(geoFile);
235 Info<< "write volume field (" << flush;
237 forAllConstIter(HashTable<word>, volumeFields, fieldIter)
239 const word& fieldName = fieldIter.key();
240 const word& fieldType = fieldIter();
245 mesh.time().timeName(),
251 if (fieldType == volScalarField::typeName)
253 ensightVolField<scalar>
264 else if (fieldType == volVectorField::typeName)
266 ensightVolField<vector>
277 else if (fieldType == volSphericalTensorField::typeName)
279 ensightVolField<sphericalTensor>
290 else if (fieldType == volSymmTensorField::typeName)
292 ensightVolField<symmTensor>
302 else if (fieldType == volTensorField::typeName)
304 ensightVolField<tensor>
318 forAllConstIter(HashTable<HashTable<word> >, cloudFields, cloudIter)
320 const word& cloudName = cloudIter.key();
326 runTime.timePath()/regionPrefix/
327 cloud::prefix/cloudName
334 IOobjectList cloudObjs
338 cloud::prefix/cloudName
341 // check that the positions field is present for this time
342 if (cloudObjs.lookup("positions"))
344 ensightParticlePositions
358 Info<< "write " << cloudName << " (" << flush;
360 forAllConstIter(HashTable<word>, cloudIter(), fieldIter)
362 const word& fieldName = fieldIter.key();
363 const word& fieldType = fieldIter();
365 IOobject *fieldObject = cloudObjs.lookup(fieldName);
370 << runTime.timeName()/cloud::prefix/cloudName
376 if (fieldType == scalarIOField::typeName)
378 ensightLagrangianField<scalar>
388 else if (fieldType == vectorIOField::typeName)
390 ensightLagrangianField<vector>
400 else if (fieldType == tensorIOField::typeName)
402 ensightLagrangianField<tensor>
416 // remember the time index
417 cloudTimesUsed[cloudName].append(timeIndex);
421 # include "ensightOutputCase.H"
423 Info<< "\nEnd\n"<< endl;
429 // ************************************************************************* //