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/>.
28 Translates foam data to Ensight format.
29 An Ensight part is created for each cellZone and patch.
32 - foamToEnsightParts [OPTION] \n
33 Translates foam 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::validOptions.insert("ascii", "");
82 argList::validOptions.insert("index", "start");
83 argList::validOptions.insert("noMesh", "");
85 // the volume field types that we handle
86 wordHashSet volFieldTypes;
87 volFieldTypes.insert(volScalarField::typeName);
88 volFieldTypes.insert(volVectorField::typeName);
89 volFieldTypes.insert(volSphericalTensorField::typeName);
90 volFieldTypes.insert(volSymmTensorField::typeName);
91 volFieldTypes.insert(volTensorField::typeName);
93 // the lagrangian field types that we handle
94 wordHashSet cloudFieldTypes;
95 cloudFieldTypes.insert(scalarIOField::typeName);
96 cloudFieldTypes.insert(vectorIOField::typeName);
97 cloudFieldTypes.insert(tensorIOField::typeName);
99 const char* geometryName = "geometry";
101 # include "setRootCase.H"
102 # include "createTime.H"
105 instantList timeDirs = timeSelector::select0(runTime, args);
107 // default to binary output, unless otherwise specified
108 IOstream::streamFormat format = IOstream::BINARY;
109 if (args.optionFound("ascii"))
111 format = IOstream::ASCII;
114 // control for renumbering iterations
115 bool optIndex = false;
116 label indexingNumber = 0;
117 if (args.optionFound("index"))
120 indexingNumber = args.optionRead<label>("index");
123 // always write the geometry, unless the -noMesh option is specified
124 bool optNoMesh = args.optionFound("noMesh");
126 fileName ensightDir = args.rootPath()/args.globalCaseName()/"Ensight";
127 fileName dataDir = ensightDir/"data";
128 fileName caseFileName = "Ensight.case";
129 fileName dataMask = fileName("data")/ensightFile::mask();
131 // Ensight and Ensight/data directories must exist
132 // do not remove old data - we might wish to convert new results
133 // or a particular time interval
134 if (isDir(ensightDir))
136 Info<<"Warning: reusing existing directory" << nl
137 << " " << ensightDir << endl;
142 # include "createNamedMesh.H"
144 // Mesh instance (region0 gets filtered out)
145 fileName regionPrefix;
147 if (regionName != polyMesh::defaultRegion)
149 regionPrefix = regionName;
152 // Construct the list of ensight parts for the entire mesh
153 ensightParts partsList(mesh);
155 // write summary information
157 OFstream partsInfoFile(ensightDir/"partsInfo");
160 << "// summary of ensight parts" << nl << nl;
161 partsList.writeSummary(partsInfoFile);
164 # include "checkHasMovingMesh.H"
165 # include "findFields.H"
167 if (hasMovingMesh && optNoMesh)
169 Info<< "mesh is moving: ignoring '-noMesh' option" << endl;
175 Map<scalar> timeIndices;
177 // Track the time indices used by the volume fields
178 DynamicList<label> fieldTimesUsed;
180 // Track the time indices used by each cloud
181 HashTable<DynamicList<label> > cloudTimesUsed;
183 // Create a new DynamicList for each cloud
184 forAllConstIter(HashTable<HashTable<word> >, cloudFields, cloudIter)
186 cloudTimesUsed.insert(cloudIter.key(), DynamicList<label>());
190 forAll(timeDirs, timeI)
192 runTime.setTime(timeDirs[timeI], timeI);
194 # include "getTimeIndex.H"
196 // remember the time index
197 fieldTimesUsed.append(timeIndex);
199 // the data/ITER subdirectory must exist
200 fileName subDir = ensightFile::subDir(timeIndex);
201 mkDir(dataDir/subDir);
203 // place a timestamp in the directory for future reference
205 OFstream timeStamp(dataDir/subDir/"time");
207 << "# timestep time" << nl
208 << subDir.c_str() << " " << runTime.timeName() << nl;
211 # include "moveMesh.H"
213 if (timeI == 0 || mesh.moving())
217 partsList.recalculate(mesh);
225 geomDir = dataDir/subDir;
228 ensightGeoFile geoFile(ensightDir/geomDir/geometryName, format);
229 partsList.writeGeometry(geoFile);
234 Info<< "write volume field (" << flush;
236 forAllConstIter(HashTable<word>, volumeFields, fieldIter)
238 const word& fieldName = fieldIter.key();
239 const word& fieldType = fieldIter();
244 mesh.time().timeName(),
250 if (fieldType == volScalarField::typeName)
252 ensightVolField<scalar>
263 else if (fieldType == volVectorField::typeName)
265 ensightVolField<vector>
276 else if (fieldType == volSphericalTensorField::typeName)
278 ensightVolField<sphericalTensor>
289 else if (fieldType == volSymmTensorField::typeName)
291 ensightVolField<symmTensor>
301 else if (fieldType == volTensorField::typeName)
303 ensightVolField<tensor>
317 forAllConstIter(HashTable<HashTable<word> >, cloudFields, cloudIter)
319 const word& cloudName = cloudIter.key();
325 runTime.timePath()/regionPrefix/
326 cloud::prefix/cloudName
333 IOobjectList cloudObjs
337 cloud::prefix/cloudName
340 // check that the positions field is present for this time
341 if (cloudObjs.lookup("positions"))
343 ensightParticlePositions
357 Info<< "write " << cloudName << " (" << flush;
359 forAllConstIter(HashTable<word>, cloudIter(), fieldIter)
361 const word& fieldName = fieldIter.key();
362 const word& fieldType = fieldIter();
364 IOobject *fieldObject = cloudObjs.lookup(fieldName);
369 << runTime.timeName()/cloud::prefix/cloudName
375 if (fieldType == scalarIOField::typeName)
377 ensightLagrangianField<scalar>
387 else if (fieldType == vectorIOField::typeName)
389 ensightLagrangianField<vector>
399 else if (fieldType == tensorIOField::typeName)
401 ensightLagrangianField<tensor>
415 // remember the time index
416 cloudTimesUsed[cloudName].append(timeIndex);
420 # include "ensightOutputCase.H"
422 Info<< "\nEnd\n"<< endl;
428 // ************************************************************************* //