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 -------------------------------------------------------------------------------
10 License
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 
30 Foam::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 
45 template<class Type>
46 Foam::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 int maskWidth = 8;
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"
122  / ensightCase::padded(maskWidth, geomIndex)
124  );
125 
126 
127  // Location for data (and possibly the geometry as well)
128  const fileName dataDir
129  (
130  baseDir/"data"/ensightCase::padded(maskWidth, timeIndex)
131  );
132 
133  // As per mkdir -p "data/00000000"
134  mkDir(dataDir);
135 
136 
137  const fileName geomFile(baseDir/geometryName);
138 
139  if (!exists(geomFile))
140  {
141  if (verbose_)
142  {
143  Info<< "Writing geometry to " << geomFile.name() << endl;
144  }
145 
146  // Two-argument form for path-name to avoid validating base-dir
147  ensightGeoFile osGeom
148  (
149  geomFile.path(),
150  geomFile.name(),
151  writeFormat_
152  );
153 
154  writeGeometry(osGeom, elemOutput);
155  }
156 
157 
158  // Write field
159  ensightFile osField
160  (
161  dataDir,
162  varName,
163  writeFormat_
164  );
165 
166  if (verbose_)
167  {
168  Info<< "Writing field file to " << osField.name() << endl;
169  }
170 
171 
172  // Write field (serial only)
173  writeTrackField<Type>(osField, fieldPtrs);
174 
175 
176  // Update case file
177  if (stateChanged)
178  {
179  OFstream osCase(outputFile, IOstreamOption::ASCII);
180 
181  // Format options
182  osCase.setf(ios_base::left);
183  osCase.setf(ios_base::scientific, ios_base::floatfield);
184  osCase.precision(5);
185 
186  if (verbose_)
187  {
188  Info<< "Writing case file to " << osCase.name() << endl;
189  }
190 
191 
192  // The geometry can be any of the following:
193  // 0: constant/static
194  // 1: moving, with the same frequency as the data
195  // 2: moving, with different frequency as the data
196 
197  const label tsGeom = caching_.geometryTimeset();
198 
199  osCase
200  << "FORMAT" << nl
201  << "type: ensight gold" << nl
202  << nl
203  << "GEOMETRY" << nl;
204 
205  if (tsGeom)
206  {
207  // moving
208  osCase
209  << "model: " << tsGeom << " " // time-set (1|2)
210  << mask << geometryName.name() << nl;
211  }
212  else
213  {
214  // steady
215  osCase
216  << "model: "
217  << geometryName.c_str() << nl;
218  }
219 
220  osCase
221  << nl
222  << "VARIABLE" << nl;
223 
224 
225  for (const entry& dEntry : caching_.fieldsDict())
226  {
227  const dictionary& subDict = dEntry.dict();
228 
229  const word varType(subDict.get<word>("type"));
230  const word varName
231  (
232  subDict.getOrDefault<word>
233  (
234  "name",
235  dEntry.keyword() // fieldName as fallback
236  )
237  );
238 
239  osCase
240  << varType
241  <<
242  (
243  true // this->isPointData()
244  ? " per node: 1 " // time-set 1
245  : " per element: 1 " // time-set 1
246  )
247  << setw(15) << varName << ' '
248  << mask << ensight::FileName(varName).c_str() << nl;
249  }
250 
251  osCase
252  << nl
253  << "TIME" << nl;
254 
255  ensightCase::printTimeset(osCase, 1, caching_.times());
256  if (tsGeom == 2)
257  {
259  (
260  osCase,
261  tsGeom,
262  caching_.times(),
263  caching_.geometries()
264  );
265  }
266 
267  osCase << "# end" << nl;
268  }
269 
270  // Timestamp in the directory for future reference
271  {
272  OFstream timeStamp(dataDir/"time");
273  timeStamp
274  << "# timestep time" << nl
275  << dataDir.name() << ' ' << timeValue << nl;
276  }
277  }
278 
279  wroteGeom_ = true;
280  return outputFile;
281 }
282 
283 
284 // ************************************************************************* //
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:53
A class for handling file names.
Definition: fileName.H:71
writer writeGeometry()
static word padded(const int nwidth, const label value)
Stringified zero-padded integer value.
Definition: ensightCase.C:38
bool wroteGeom_
Track if geometry has been written since the last open.
Specification of a valid Ensight file-name.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
"ascii" (normal default)
static const fileName null
An empty fileName.
Definition: fileName.H:110
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:169
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:813
word timeName
Definition: getTimeIndex.H:3
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:567
Generic templated field type.
Definition: Field.H:61
A class for handling words, derived from Foam::string.
Definition: word.H:63
static const char * geometryName
The name for geometry files: "geometry".
Definition: ensightCase.H:81
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: POSIX.C:788
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition: HashTable.H:100
const char *const typeName
Specification of a valid Ensight variable-name.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
IOstream & scientific(IOstream &io)
Definition: IOstream.H:566
label timeIndex
Definition: getTimeIndex.H:24