convertVolumeFields.H
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) 2018-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
26Description
27 Code chunk for converting volume and dimensioned fields
28 included by foamToVTK.
29
30\*---------------------------------------------------------------------------*/
31
32// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
33
34{
35 using reportFields = foamToVtkReportFields;
36
37 const label nVolFields =
38 (
39 (doInternal || doBoundary)
40 ? objects.count(stringListOps::foundOp<word>(fieldTypes::volume))
41 : 0
42 );
43
44 const label nDimFields =
45 (
46 (doInternal || doBoundary)
47 ? objects.count(stringListOps::foundOp<word>(fieldTypes::internal))
48 : 0
49 );
50
52 (
53 doPointValues
54 ? objects.count(stringListOps::foundOp<word>(fieldTypes::point))
55 : 0
56 );
57
58
59 reportFields::volume(Info, objects);
60 reportFields::internal(Info, objects);
61
62
63 // Setup for the vtm writer.
64 // For legacy format, the information added is simply ignored.
65
67 (
68 outputDir/regionDir/vtkName + timeDesc
69 );
70
71 // Combined internal + boundary in a vtm file
72 vtk::vtmWriter vtmWriter;
73
74 // Collect individual boundaries into a vtm file
75 vtk::vtmWriter vtmBoundaries;
76
77 // Setup the internal writer
78 autoPtr<vtk::internalWriter> internalWriter;
79
80 // Interpolator for volume and dimensioned fields
81 autoPtr<volPointInterpolation> pInterp;
82
83 if (doInternal)
84 {
85 if (vtuMeshCells.empty())
86 {
87 // Use the appropriate mesh (baseMesh or subMesh)
88 vtuMeshCells.reset(meshProxy.mesh());
89
90 if (doPointValues && vtuMeshCells.manifold())
91 {
92 doPointValues = false;
93 nPointFields = 0;
94 Warning
95 << nl
96 << "Manifold cells detected (eg, AMI) - disabling PointData"
97 << nl
98 << endl;
99 }
100 }
101
102 internalWriter = autoPtr<vtk::internalWriter>::New
103 (
104 meshProxy.mesh(),
105 vtuMeshCells,
106 writeOpts,
107 // The output base name for internal
108 (
109 writeOpts.legacy()
111 : (vtmOutputBase / "internal")
112 ),
113 Pstream::parRun()
114 );
115
116 // No sub-block for internal
117 vtmWriter.append_vtu
118 (
119 "internal",
120 vtmOutputBase.name()/"internal"
121 );
122
123 Info<< " Internal : "
124 << args.relativePath(internalWriter->output()) << nl;
125
126 internalWriter->writeTimeValue(mesh.time().value());
127 internalWriter->writeGeometry();
128
129 if (doPointValues)
130 {
131 pInterp.reset(new volPointInterpolation(mesh));
132 }
133 }
134
135
136 // Setup the patch writers
137
138 const polyBoundaryMesh& patches = mesh.boundaryMesh();
139
140 PtrList<vtk::patchWriter> patchWriters;
141 PtrList<PrimitivePatchInterpolation<primitivePatch>> patchInterps;
142
143 labelList patchIds;
144 if (doBoundary)
145 {
146 patchIds = getSelectedPatches(patches, patchSelector);
147 }
148
149 if (oneBoundary && patchIds.size())
150 {
151 auto writer = autoPtr<vtk::patchWriter>::New
152 (
153 meshProxy.mesh(),
154 patchIds,
155 writeOpts,
156 nearCellValue,
157 // Output one patch: "boundary"
158 (
159 writeOpts.legacy()
160 ?
161 (
162 outputDir/regionDir/"boundary"
163 / (meshProxy.useSubMesh() ? meshProxy.name() : "boundary")
164 + timeDesc
165 )
166 : (vtmOutputBase / "boundary")
167 ),
168 Pstream::parRun()
169 );
170
171 // No sub-block for one-patch
172 vtmWriter.append_vtp
173 (
174 "boundary",
175 vtmOutputBase.name()/"boundary"
176 );
177
178 Info<< " Boundaries: "
179 << args.relativePath(writer->output()) << nl;
180
181 writer->writeTimeValue(timeValue);
182 writer->writeGeometry();
183
184 // Transfer writer to list for later use
185 patchWriters.resize(1);
186 patchWriters.set(0, writer);
187
188 // Avoid patchInterpolation for each sub-patch
189 patchInterps.resize(1); // == nullptr
190 }
191 else if (patchIds.size())
192 {
193 patchWriters.resize(patchIds.size());
194 if (doPointValues)
195 {
196 patchInterps.resize(patchIds.size());
197 }
198
199 label nPatchWriters = 0;
200 label nPatchInterps = 0;
201
202 for (const label patchId : patchIds)
203 {
204 const polyPatch& pp = patches[patchId];
205
206 auto writer = autoPtr<vtk::patchWriter>::New
207 (
208 meshProxy.mesh(),
209 labelList(one{}, pp.index()),
210 writeOpts,
211 nearCellValue,
212 // Output patch: "boundary"/name
213 (
214 writeOpts.legacy()
215 ?
216 (
217 outputDir/regionDir/pp.name()
218 / (meshProxy.useSubMesh() ? meshProxy.name() : pp.name())
219 + timeDesc
220 )
221 : (vtmOutputBase / "boundary" / pp.name())
222 ),
223 Pstream::parRun()
224 );
225
226 if (!nPatchWriters)
227 {
228 vtmWriter.beginBlock("boundary");
229 vtmBoundaries.beginBlock("boundary");
230 }
231
232 vtmWriter.append_vtp
233 (
234 pp.name(),
235 vtmOutputBase.name()/"boundary"/pp.name()
236 );
237
238 vtmBoundaries.append_vtp
239 (
240 pp.name(),
241 "boundary"/pp.name()
242 );
243
244 Info<< " Boundary : "
245 << args.relativePath(writer->output()) << nl;
246
247 writer->writeTimeValue(timeValue);
248 writer->writeGeometry();
249
250 // Transfer writer to list for later use
252
253 if (patchInterps.size())
254 {
255 patchInterps.set
256 (
257 nPatchInterps++,
258 new PrimitivePatchInterpolation<primitivePatch>(pp)
259 );
260 }
261 }
262
263 if (nPatchWriters)
264 {
265 vtmWriter.endBlock("boundary");
266 }
267
269 patchInterps.resize(nPatchInterps);
270 }
271
272
273 // CellData
274 {
275 // Begin CellData
276 if (internalWriter)
277 {
278 // Optionally with (cellID, procID) fields
279 internalWriter->beginCellData
280 (
281 (withMeshIds ? 1 + (internalWriter->parallel() ? 1 : 0) : 0)
283 );
284
285 if (withMeshIds)
286 {
287 internalWriter->writeCellIDs();
288 internalWriter->writeProcIDs(); // parallel only
289 }
290 }
291
292 if (nVolFields || withMeshIds)
293 {
294 for (vtk::patchWriter& writer : patchWriters)
295 {
296 // Optionally with (patchID, procID) fields
297 writer.beginCellData
298 (
299 (withMeshIds ? 2 : 0)
300 + nVolFields
301 );
302
303 if (withMeshIds)
304 {
305 writer.writePatchIDs();
306 writer.writeProcIDs();
307 }
308 }
309 }
310
312 (
315 meshProxy,
316 objects,
317 true // syncPar
318 );
319
321 (
323 meshProxy,
324 objects,
325 true // syncPar
326 );
327
328 // End CellData is implicit
329 }
330
331
332 // PointData
333 // - only construct pointMesh on request since it constructs
334 // edge addressing
335 if (doPointValues)
336 {
337 // Begin PointData
338 if (internalWriter)
339 {
340 internalWriter->beginPointData
341 (
343 + (withPointIds ? 1 : 0)
344 );
345
346 if (withPointIds)
347 {
348 internalWriter->writePointIDs();
349 }
350 }
351
352 forAll(patchWriters, writeri)
353 {
354 const label nPatchFields =
355 (
356 (
357 writeri < patchInterps.size() && patchInterps.set(writeri)
358 ? nVolFields
359 : 0
360 )
362 );
363
364 if (nPatchFields)
365 {
366 patchWriters[writeri].beginPointData(nPatchFields);
367 }
368 }
369
370 writeAllVolFields
371 (
374 meshProxy,
375 objects,
376 true // syncPar
377 );
378
380 (
382 meshProxy,
383 objects,
384 true // syncPar
385 );
386
387 writeAllPointFields
388 (
391 meshProxy,
392 objects,
393 true // syncPar
394 );
395
396 // End PointData is implicit
397 }
398
399
400 // Finish writers
402 {
403 internalWriter->close();
404 }
405
406 for (vtk::patchWriter& writer : patchWriters)
407 {
408 writer.close();
409 }
410
411 pInterp.clear();
412 patchWriters.clear();
413 patchInterps.clear();
414
415
416 // Collective output
417
418 if (Pstream::master())
419 {
420 // Naming for vtm, file series etc.
421 fileName outputName(vtmOutputBase);
422
423 if (writeOpts.legacy())
424 {
425 if (doInternal)
426 {
427 // Add to file-series and emit as JSON
428
429 outputName.ext(vtk::legacy::fileExtension);
430
431 fileName seriesName(vtk::seriesWriter::base(outputName));
432
433 vtk::seriesWriter& series = vtkSeries(seriesName);
434
435 // First time?
436 // Load from file, verify against filesystem,
437 // prune time >= currentTime
438 if (series.empty())
439 {
440 series.load(seriesName, true, timeValue);
441 }
442
443 series.append(timeValue, timeDesc);
444 series.write(seriesName);
445 }
446 }
447 else
448 {
449 if (vtmWriter.size())
450 {
451 // Emit ".vtm"
452
453 outputName.ext(vtmWriter.ext());
454
455 fileName seriesName(vtk::seriesWriter::base(outputName));
456
457 vtmWriter.setTime(timeValue);
458 vtmWriter.write(outputName);
459
460 // Add to file-series and emit as JSON
461
462 vtk::seriesWriter& series = vtkSeries(seriesName);
463
464 // First time?
465 // Load from file, verify against filesystem,
466 // prune time >= currentTime
467 if (series.empty())
468 {
469 series.load(seriesName, true, timeValue);
470 }
471
472 series.append(timeValue, outputName);
473 series.write(seriesName);
474
475 // Add to multi-region vtm
476 vtmMultiRegion.add(regionName, regionDir, vtmWriter);
477 }
478
479 if (vtmBoundaries.size())
480 {
481 // Emit "boundary.vtm" with collection of boundaries
482
483 // Naming for vtm
484 fileName outputName(vtmOutputBase / "boundary");
485 outputName.ext(vtmBoundaries.ext());
486
487 vtmBoundaries.setTime(timeValue);
489 }
490 }
491 }
492}
493
494
495// ************************************************************************* //
vtk::internalMeshWriter writer(topoMesh, topoCells, vtk::formatType::INLINE_ASCII, runTime.path()/"blockTopology")
fileName relativePath(const fileName &input, const bool caseTag=false) const
Definition: argListI.H:94
label nPatchWriters
dynamicFvMesh & mesh
Foam::word regionName(Foam::polyMesh::defaultRegion)
word outputName("finiteArea-edges.obj")
const word & regionDir
labelList patchIds
PtrList< PrimitivePatchInterpolation< primitivePatch > > patchInterps
vtk::vtmWriter vtmWriter
const label nVolFields
const label nDimFields
fileName vtmOutputBase(outputDir/regionDir/vtkName+timeDesc)
writeAllDimFields(internalWriter, meshProxy, objects, true)
autoPtr< vtk::internalWriter > internalWriter
autoPtr< volPointInterpolation > pInterp
PtrList< vtk::patchWriter > patchWriters
const polyBoundaryMesh & patches
label nPointFields
vtk::vtmWriter vtmBoundaries
label patchId(-1)
label writeAllVolFields(ensightCase &ensCase, const ensightMesh &ensMesh, const IOobjectList &objects, const bool nearCellValue=false)
Foam::argList args(argc, argv)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333