1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
28 Translates OpenFOAM data to Ensight format.
29 An Ensight part is created for each cellZone and patch.
32 - foamToEnsightParts [OPTION] \n
33 Translates OpenFOAM data to Ensight format
36 Write Ensight data in ASCII format instead of "C Binary"
39 Exclude the often incomplete initial conditions.
41 \param -index \<start\>\n
42 Ignore the time index contained in the time file and use a
43 simple indexing when creating the \c Ensight/data/######## files.
46 Suppress writing the geometry. Can be useful for converting partial
47 results for a static geometry.
51 - writes to \a Ensight directory to avoid collisions with foamToEnsight.
53 \*---------------------------------------------------------------------------*/
56 #include "timeSelector.H"
58 #include "volFields.H"
61 #include "IOobjectList.H"
62 #include "scalarIOField.H"
63 #include "tensorIOField.H"
65 #include "ensightParts.H"
66 #include "ensightOutputFunctions.H"
70 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
74 int main(int argc, char *argv[])
77 // probably don't need -zeroTime though, since the fields are vetted
79 timeSelector::addOptions(true, false);
80 argList::noParallel();
81 argList::addBoolOption
84 "write in ASCII format instead of 'C Binary'"
90 "ignore the time index contained in the uniform/time file "
91 "and use simple indexing when creating the files"
93 argList::addBoolOption
96 "suppress writing the geometry. "
97 "Can be useful for converting partial results for a static geometry"
100 // the volume field types that we handle
101 wordHashSet volFieldTypes;
102 volFieldTypes.insert(volScalarField::typeName);
103 volFieldTypes.insert(volVectorField::typeName);
104 volFieldTypes.insert(volSphericalTensorField::typeName);
105 volFieldTypes.insert(volSymmTensorField::typeName);
106 volFieldTypes.insert(volTensorField::typeName);
108 // the lagrangian field types that we handle
109 wordHashSet cloudFieldTypes;
110 cloudFieldTypes.insert(scalarIOField::typeName);
111 cloudFieldTypes.insert(vectorIOField::typeName);
112 cloudFieldTypes.insert(tensorIOField::typeName);
114 const char* geometryName = "geometry";
116 # include "setRootCase.H"
117 # include "createTime.H"
120 instantList timeDirs = timeSelector::select0(runTime, args);
122 // default to binary output, unless otherwise specified
123 IOstream::streamFormat format = IOstream::BINARY;
124 if (args.optionFound("ascii"))
126 format = IOstream::ASCII;
129 // control for renumbering iterations
130 label indexingNumber = 0;
131 bool optIndex = args.optionReadIfPresent("index", indexingNumber);
133 // always write the geometry, unless the -noMesh option is specified
134 bool optNoMesh = args.optionFound("noMesh");
136 fileName ensightDir = args.rootPath()/args.globalCaseName()/"Ensight";
137 fileName dataDir = ensightDir/"data";
138 fileName caseFileName = "Ensight.case";
139 fileName dataMask = fileName("data")/ensightFile::mask();
141 // Ensight and Ensight/data directories must exist
142 // do not remove old data - we might wish to convert new results
143 // or a particular time interval
144 if (isDir(ensightDir))
146 Info<<"Warning: re-using existing directory" << nl
147 << " " << ensightDir << endl;
152 # include "createNamedMesh.H"
154 // Mesh instance (region0 gets filtered out)
155 fileName regionPrefix;
157 if (regionName != polyMesh::defaultRegion)
159 regionPrefix = regionName;
162 // Construct the list of ensight parts for the entire mesh
163 ensightParts partsList(mesh);
165 // write summary information
167 OFstream partsInfoFile(ensightDir/"partsInfo");
170 << "// summary of ensight parts" << nl << nl;
171 partsList.writeSummary(partsInfoFile);
174 # include "checkHasMovingMesh.H"
175 # include "findFields.H"
177 if (hasMovingMesh && optNoMesh)
179 Info<< "mesh is moving: ignoring '-noMesh' option" << endl;
185 Map<scalar> timeIndices;
187 // Track the time indices used by the volume fields
188 DynamicList<label> fieldTimesUsed;
190 // Track the time indices used by each cloud
191 HashTable<DynamicList<label> > cloudTimesUsed;
193 // Create a new DynamicList for each cloud
194 forAllConstIter(HashTable<HashTable<word> >, cloudFields, cloudIter)
196 cloudTimesUsed.insert(cloudIter.key(), DynamicList<label>());
200 forAll(timeDirs, timeI)
202 runTime.setTime(timeDirs[timeI], timeI);
204 # include "getTimeIndex.H"
206 // remember the time index
207 fieldTimesUsed.append(timeIndex);
209 // the data/ITER subdirectory must exist
210 fileName subDir = ensightFile::subDir(timeIndex);
211 mkDir(dataDir/subDir);
213 // place a timestamp in the directory for future reference
215 OFstream timeStamp(dataDir/subDir/"time");
217 << "# timestep time" << nl
218 << subDir.c_str() << " " << runTime.timeName() << nl;
221 # include "moveMesh.H"
223 if (timeI == 0 || mesh.moving())
227 partsList.recalculate(mesh);
235 geomDir = dataDir/subDir;
238 ensightGeoFile geoFile(ensightDir/geomDir/geometryName, format);
239 partsList.writeGeometry(geoFile);
244 Info<< "write volume field (" << flush;
246 forAllConstIter(HashTable<word>, volumeFields, fieldIter)
248 const word& fieldName = fieldIter.key();
249 const word& fieldType = fieldIter();
254 mesh.time().timeName(),
260 if (fieldType == volScalarField::typeName)
262 ensightVolField<scalar>
273 else if (fieldType == volVectorField::typeName)
275 ensightVolField<vector>
286 else if (fieldType == volSphericalTensorField::typeName)
288 ensightVolField<sphericalTensor>
299 else if (fieldType == volSymmTensorField::typeName)
301 ensightVolField<symmTensor>
311 else if (fieldType == volTensorField::typeName)
313 ensightVolField<tensor>
327 forAllConstIter(HashTable<HashTable<word> >, cloudFields, cloudIter)
329 const word& cloudName = cloudIter.key();
335 runTime.timePath()/regionPrefix/
336 cloud::prefix/cloudName
343 IOobjectList cloudObjs
347 cloud::prefix/cloudName
350 // check that the positions field is present for this time
351 if (cloudObjs.lookup("positions"))
353 ensightParticlePositions
367 Info<< "write " << cloudName << " (" << flush;
369 forAllConstIter(HashTable<word>, cloudIter(), fieldIter)
371 const word& fieldName = fieldIter.key();
372 const word& fieldType = fieldIter();
374 IOobject *fieldObject = cloudObjs.lookup(fieldName);
379 << runTime.timeName()/cloud::prefix/cloudName
385 if (fieldType == scalarIOField::typeName)
387 ensightLagrangianField<scalar>
397 else if (fieldType == vectorIOField::typeName)
399 ensightLagrangianField<vector>
409 else if (fieldType == tensorIOField::typeName)
411 ensightLagrangianField<tensor>
425 // remember the time index
426 cloudTimesUsed[cloudName].append(timeIndex);
430 # include "ensightOutputCase.H"
432 Info<< "\nEnd\n"<< endl;
438 // ************************************************************************* //