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 / foamToEnsightParts / foamToEnsightParts.C
blob3c815f287c2cc0d300f55a6234fc63ef3e4b516f
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 Application
25     foamToEnsightParts
27 Description
28     Translates foam data to Ensight format.
29     An Ensight part is created for each cellZone and patch.
31 Usage
32     - foamToEnsightParts [OPTION] \n
33     Translates foam data to Ensight format
35     @param -ascii \n
36     Write Ensight data in ASCII format instead of "C Binary"
38     @param -noZero \n
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.
45     @param -noMesh \n
46     Suppress writing the geometry. Can be useful for converting partial
47     results for a static geometry.
49 Note
50     - no parallel data.
51     - writes to @a Ensight directory to avoid collisions with foamToEnsight.
53 \*---------------------------------------------------------------------------*/
55 #include "argList.H"
56 #include "timeSelector.H"
58 #include "volFields.H"
59 #include "OFstream.H"
60 #include "IOmanip.H"
61 #include "IOobjectList.H"
62 #include "scalarIOField.H"
63 #include "tensorIOField.H"
65 #include "ensightParts.H"
66 #include "ensightOutputFunctions.H"
68 using namespace Foam;
70 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
72 // Main program:
74 int main(int argc, char *argv[])
76     // enable -constant
77     // probably don't need -zeroTime though, since the fields are vetted
78     // afterwards anyhow
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"
104     // get times list
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"))
110     {
111         format = IOstream::ASCII;
112     }
114     // control for renumbering iterations
115     bool optIndex = false;
116     label indexingNumber = 0;
117     if (args.optionFound("index"))
118     {
119         optIndex = true;
120         indexingNumber = args.optionRead<label>("index");
121     }
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))
135     {
136         Info<<"Warning: reusing existing directory" << nl
137             << "    " << ensightDir << endl;
138     }
139     mkDir(ensightDir);
140     mkDir(dataDir);
142 #   include "createNamedMesh.H"
144     // Mesh instance (region0 gets filtered out)
145     fileName regionPrefix;
147     if (regionName != polyMesh::defaultRegion)
148     {
149         regionPrefix = regionName;
150     }
152     // Construct the list of ensight parts for the entire mesh
153     ensightParts partsList(mesh);
155     // write summary information
156     {
157         OFstream partsInfoFile(ensightDir/"partsInfo");
159         partsInfoFile
160             << "// summary of ensight parts" << nl << nl;
161         partsList.writeSummary(partsInfoFile);
162     }
164 #   include "checkHasMovingMesh.H"
165 #   include "findFields.H"
167     if (hasMovingMesh && optNoMesh)
168     {
169         Info<< "mesh is moving: ignoring '-noMesh' option" << endl;
170         optNoMesh = false;
171     }
174     // map times used
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)
185     {
186         cloudTimesUsed.insert(cloudIter.key(), DynamicList<label>());
187     }
190     forAll(timeDirs, timeI)
191     {
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
204         {
205             OFstream timeStamp(dataDir/subDir/"time");
206             timeStamp
207                 << "#   timestep time" << nl
208                 << subDir.c_str() << " " << runTime.timeName() << nl;
209         }
211 #       include "moveMesh.H"
213         if (timeI == 0 || mesh.moving())
214         {
215             if (mesh.moving())
216             {
217                 partsList.recalculate(mesh);
218             }
220             if (!optNoMesh)
221             {
222                 fileName geomDir;
223                 if (hasMovingMesh)
224                 {
225                     geomDir = dataDir/subDir;
226                 }
228                 ensightGeoFile geoFile(ensightDir/geomDir/geometryName, format);
229                 partsList.writeGeometry(geoFile);
230                 Info<< nl;
231             }
232         }
234         Info<< "write volume field (" << flush;
236         forAllConstIter(HashTable<word>, volumeFields, fieldIter)
237         {
238             const word& fieldName = fieldIter.key();
239             const word& fieldType = fieldIter();
241             IOobject fieldObject
242             (
243                 fieldName,
244                 mesh.time().timeName(),
245                 mesh,
246                 IOobject::MUST_READ,
247                 IOobject::NO_WRITE
248             );
250             if (fieldType == volScalarField::typeName)
251             {
252                 ensightVolField<scalar>
253                 (
254                     partsList,
255                     fieldObject,
256                     mesh,
257                     dataDir,
258                     subDir,
259                     format
260                 );
262             }
263             else if (fieldType == volVectorField::typeName)
264             {
265                 ensightVolField<vector>
266                 (
267                     partsList,
268                     fieldObject,
269                     mesh,
270                     dataDir,
271                     subDir,
272                     format
273                 );
275             }
276             else if (fieldType == volSphericalTensorField::typeName)
277             {
278                 ensightVolField<sphericalTensor>
279                 (
280                     partsList,
281                     fieldObject,
282                     mesh,
283                     dataDir,
284                     subDir,
285                     format
286                 );
288             }
289             else if (fieldType == volSymmTensorField::typeName)
290             {
291                 ensightVolField<symmTensor>
292                 (
293                     partsList,
294                     fieldObject,
295                     mesh,
296                     dataDir,
297                     subDir,
298                     format
299                 );
300             }
301             else if (fieldType == volTensorField::typeName)
302             {
303                 ensightVolField<tensor>
304                 (
305                     partsList,
306                     fieldObject,
307                     mesh,
308                     dataDir,
309                     subDir,
310                     format
311                 );
312             }
313         }
314         Info<< " )" << endl;
316         // check for clouds
317         forAllConstIter(HashTable<HashTable<word> >, cloudFields, cloudIter)
318         {
319             const word& cloudName = cloudIter.key();
321             if
322             (
323                 !isDir
324                 (
325                     runTime.timePath()/regionPrefix/
326                     cloud::prefix/cloudName
327                 )
328             )
329             {
330                 continue;
331             }
333             IOobjectList cloudObjs
334             (
335                 mesh,
336                 runTime.timeName(),
337                 cloud::prefix/cloudName
338             );
340             // check that the positions field is present for this time
341             if (cloudObjs.lookup("positions"))
342             {
343                 ensightParticlePositions
344                 (
345                     mesh,
346                     dataDir,
347                     subDir,
348                     cloudName,
349                     format
350                 );
351             }
352             else
353             {
354                 continue;
355             }
357             Info<< "write " << cloudName << " (" << flush;
359             forAllConstIter(HashTable<word>, cloudIter(), fieldIter)
360             {
361                 const word& fieldName = fieldIter.key();
362                 const word& fieldType = fieldIter();
364                 IOobject *fieldObject = cloudObjs.lookup(fieldName);
366                 if (!fieldObject)
367                 {
368                     Info<< "missing "
369                         << runTime.timeName()/cloud::prefix/cloudName
370                         / fieldName
371                         << endl;
372                     continue;
373                 }
375                 if (fieldType == scalarIOField::typeName)
376                 {
377                     ensightLagrangianField<scalar>
378                     (
379                         *fieldObject,
380                         dataDir,
381                         subDir,
382                         cloudName,
383                         format
384                     );
386                 }
387                 else if (fieldType == vectorIOField::typeName)
388                 {
389                     ensightLagrangianField<vector>
390                     (
391                         *fieldObject,
392                         dataDir,
393                         subDir,
394                         cloudName,
395                         format
396                     );
398                 }
399                 else if (fieldType == tensorIOField::typeName)
400                 {
401                     ensightLagrangianField<tensor>
402                     (
403                         *fieldObject,
404                         dataDir,
405                         subDir,
406                         cloudName,
407                         format
408                     );
410                 }
411             }
413             Info<< " )" << endl;
415             // remember the time index
416             cloudTimesUsed[cloudName].append(timeIndex);
417         }
418     }
420 #   include "ensightOutputCase.H"
422     Info<< "\nEnd\n"<< endl;
424     return 0;
428 // ************************************************************************* //