ensightCoordSetWriterCollated.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2022 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
29
30Foam::fileName Foam::coordSetWriters::ensightWriter::writeCollated
31(
32 const bool writeTracks
33)
34{
35 // Collated?
36 // ========
37 // CaseFile: rootdir/NAME/NAME.case
38 // Geometry: rootdir/NAME/NAME.mesh
39
40 wroteGeom_ = true;
41 return fileName::null;
42}
43
44
45template<class Type>
46Foam::fileName Foam::coordSetWriters::ensightWriter::writeCollated
47(
48 const word& fieldName,
49 const UPtrList<const Field<Type>>& fieldPtrs,
50 elemOutputType elemOutput
51)
52{
53 // Geometry changed since last output? Capture now
54 const bool geomChanged = (!upToDate_);
55
56 checkOpen();
57
58 const ensight::FileName baseName(outputPath_.name());
59 const ensight::VarName varName(fieldName);
60
61
62 // Collated
63 // ========
64 // CaseFile: rootdir/NAME/NAME.case
65 // Geometry: rootdir/NAME/data/<index>/geometry
66 // Field: rootdir/NAME/data/<index>/field
67
68 // Use geometry name as sub-directory for results. Eg,
69 // - NAME1/NAME1.case
70 // - NAME1/data/00000000/geometry
71 // - NAME1/data/00000000/VAR1
72 // - NAME1/data/00000000/VAR2
73
74 // Names "data" and "geometry" as per ensightCase:
75 const char* fmt = "%08d";
76 const char* mask = "data/********/";
77
78 // Ignore the useTimeDir setting - manage ourselves
79 const fileName baseDir = outputPath_;
80
81 const word timeDir = timeName();
82 const scalar timeValue = currTime_.value();
83
84 const fileName outputFile = baseDir / baseName + ".case";
85
86 if (verbose_)
87 {
88 Info<< "Writing case file to " << outputFile << endl;
89 }
90
91 // Update geometry
92 merge();
93
94 {
95 if (!isDir(outputFile.path()))
96 {
97 mkDir(outputFile.path());
98 }
99
100 const bool stateChanged =
101 caching_.update
102 (
103 baseDir,
104 timeValue,
105 geomChanged,
106 fieldName,
108 varName
109 );
110
111
112 // The most current time and geometry indices
113 const label timeIndex = caching_.latestTimeIndex();
114 const label geomIndex = caching_.latestGeomIndex();
115
116
117 // This will be used for the name of a static geometry,
118 // or just the masking part for moving geometries.
119 const fileName geometryName
120 (
121 "data"/word::printf(fmt, geomIndex)/ensightCase::geometryName
122 );
123
124
125 // Do case file
126 if (stateChanged)
127 {
128 OFstream osCase(outputFile, IOstream::ASCII);
129
130 // Format options
131 osCase.setf(ios_base::left);
132 osCase.setf(ios_base::scientific, ios_base::floatfield);
133 osCase.precision(5);
134
135 if (verbose_)
136 {
137 Info<< "Writing case file to " << osCase.name() << endl;
138 }
139
140
141 // The geometry can be any of the following:
142 // 0: constant/static
143 // 1: moving, with the same frequency as the data
144 // 2: moving, with different frequency as the data
145
146 const label tsGeom = caching_.geometryTimeset();
147
148 osCase
149 << "FORMAT" << nl
150 << "type: ensight gold" << nl
151 << nl
152 << "GEOMETRY" << nl;
153
154 if (tsGeom)
155 {
156 // moving
157 osCase
158 << "model: " << tsGeom << " " // time-set (1|2)
159 << mask << geometryName.name() << nl;
160 }
161 else
162 {
163 // steady
164 osCase
165 << "model: "
166 << geometryName.c_str() << nl;
167 }
168
169 osCase
170 << nl
171 << "VARIABLE" << nl;
172
173
174 for (const entry& dEntry : caching_.fieldsDict())
175 {
176 const dictionary& subDict = dEntry.dict();
177
178 const word varType(subDict.get<word>("type"));
179 const word varName
180 (
181 subDict.getOrDefault<word>
182 (
183 "name",
184 dEntry.keyword() // fieldName as fallback
185 )
186 );
187
188 osCase
189 << varType
190 <<
191 (
192 true // this->isPointData()
193 ? " per node: 1 " // time-set 1
194 : " per element: 1 " // time-set 1
195 )
196 << setw(15) << varName << ' '
197 << mask << varName << nl;
198 }
199
200 osCase
201 << nl
202 << "TIME" << nl;
203
204 ensightCase::printTimeset(osCase, 1, caching_.times());
205 if (tsGeom == 2)
206 {
208 (
209 osCase,
210 tsGeom,
211 caching_.times(),
212 caching_.geometries()
213 );
214 }
215
216 osCase << "# end" << nl;
217 }
218
219
220 // Location for data (and possibly the geometry as well)
221 fileName dataDir = baseDir/"data"/word::printf(fmt, timeIndex);
222
223 // As per mkdir -p "data/00000000"
224 mkDir(dataDir);
225
226
227 const fileName geomFile(baseDir/geometryName);
228
229 if (!exists(geomFile))
230 {
231 if (verbose_)
232 {
233 Info<< "Writing geometry to " << geomFile.name() << endl;
234 }
235
236 // Two-argument form for path-name to avoid validating base-dir
237 ensightGeoFile osGeom
238 (
239 geomFile.path(),
240 geomFile.name(),
241 writeFormat_
242 );
243
244 writeGeometry(osGeom, elemOutput);
245 }
246
247
248 // Write field
249 ensightFile osField
250 (
251 dataDir,
252 varName,
253 writeFormat_
254 );
255
256 if (verbose_)
257 {
258 Info<< "Writing field file to " << osField.name() << endl;
259 }
260
261
262 // Write field (serial only)
263 writeTrackField<Type>(osField, fieldPtrs);
264
265
266 // Timestamp in the directory for future reference
267 {
268 OFstream timeStamp(dataDir/"time");
269 timeStamp
270 << "# timestep time" << nl
271 << dataDir.name() << ' ' << timeValue << nl;
272 }
273 }
274
275 wroteGeom_ = true;
276 return outputFile;
277}
278
279
280// ************************************************************************* //
writer writeGeometry()
Generic templated field type.
Definition: Field.H:82
ios_base::fmtflags setf(const ios_base::fmtflags f)
Set flags of stream.
Definition: IOstream.H:378
Output to file stream, using an OSstream.
Definition: OFstream.H:57
virtual const fileName & name() const
Read/write access to the name of the stream.
Definition: OSstream.H:107
virtual int precision() const
Get precision of output field.
Definition: OSstream.C:326
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition: UPtrList.H:71
bool wroteGeom_
Track if geometry has been written since the last open.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
static const char * geometryName
The name for geometry files: "geometry".
Definition: ensightCase.H:81
static void printTimeset(OSstream &os, const label ts, const scalar timeValue)
Print time-set for ensight case file with a single time.
Definition: ensightCase.C:44
Ensight output with specialized write() for strings, integers and floats. Correctly handles binary wr...
Definition: ensightFile.H:55
Specialized Ensight output with extra geometry file header.
Specification of a valid Ensight file-name.
Specification of a valid Ensight variable-name.
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:70
A class for handling file names.
Definition: fileName.H:76
static const fileName null
An empty fileName.
Definition: fileName.H:102
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:176
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Definition: fileNameI.H:199
A class for handling words, derived from Foam::string.
Definition: word.H:68
static word printf(const char *fmt, const PrimitiveType &val)
Use a printf-style formatter for a primitive.
word timeName
Definition: getTimeIndex.H:3
bool exists(const fileName &name, const bool checkGzip=true, const bool followLink=true)
Does the name exist (as DIRECTORY or FILE) in the file system?
Definition: MSwindows.C:633
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:515
messageStream Info
Information stream (stdout output on master, null elsewhere)
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: MSwindows.C:651
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
label timeIndex
Definition: getTimeIndex.H:30
Ensight names and component order for base types.