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-2021 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 Description
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 
51  const label nPointFields =
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 
66  fileName vtmOutputBase
67  (
68  outputDir/regionDir/vtkName + timeDesc
69  );
70 
71  // Combined internal + boundary in a vtm file
73 
74  // Collect individual boundaries into a vtm file
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 (doPointValues)
86  {
87  pInterp.reset(new volPointInterpolation(mesh));
88  }
89 
90  if (vtuMeshCells.empty())
91  {
92  // Use the appropriate mesh (baseMesh or subMesh)
93  vtuMeshCells.reset(meshProxy.mesh());
94  }
95 
97  (
98  meshProxy.mesh(),
99  vtuMeshCells,
100  writeOpts,
101  // The output base name for internal
102  (
103  writeOpts.legacy()
104  ? vtmOutputBase
105  : (vtmOutputBase / "internal")
106  ),
107  Pstream::parRun()
108  );
109 
110  // No sub-block for internal
111  vtmWriter.append_vtu
112  (
113  "internal",
114  vtmOutputBase.name()/"internal"
115  );
116 
117  Info<< " Internal : "
118  << args.relativePath(internalWriter->output()) << nl;
119 
120  internalWriter->writeTimeValue(mesh.time().value());
121  internalWriter->writeGeometry();
122  }
123 
124 
125  // Setup the patch writers
126 
127  const polyBoundaryMesh& patches = mesh.boundaryMesh();
128 
129  PtrList<vtk::patchWriter> patchWriters;
130  PtrList<PrimitivePatchInterpolation<primitivePatch>> patchInterps;
131 
133  if (doBoundary)
134  {
135  patchIds = getSelectedPatches(patches, includePatches, excludePatches);
136  }
137 
138  if (oneBoundary && patchIds.size())
139  {
141  (
142  meshProxy.mesh(),
143  patchIds,
144  writeOpts,
145  nearCellValue,
146  // Output one patch: "boundary"
147  (
148  writeOpts.legacy()
149  ?
150  (
151  outputDir/regionDir/"boundary"
152  / (meshProxy.useSubMesh() ? meshProxy.name() : "boundary")
153  + timeDesc
154  )
155  : (vtmOutputBase / "boundary")
156  ),
157  Pstream::parRun()
158  );
159 
160  // No sub-block for one-patch
161  vtmWriter.append_vtp
162  (
163  "boundary",
164  vtmOutputBase.name()/"boundary"
165  );
166 
167  Info<< " Boundaries: "
168  << args.relativePath(writer->output()) << nl;
169 
170  writer->writeTimeValue(timeValue);
171  writer->writeGeometry();
172 
173  // Transfer writer to list for later use
174  patchWriters.resize(1);
175  patchWriters.set(0, writer);
176 
177  // Avoid patchInterpolation for each sub-patch
178  patchInterps.resize(1); // == nullptr
179  }
180  else if (patchIds.size())
181  {
182  patchWriters.resize(patchIds.size());
183  if (doPointValues)
184  {
185  patchInterps.resize(patchIds.size());
186  }
187 
188  label nPatchWriters = 0;
189  label nPatchInterps = 0;
190 
191  for (const label patchId : patchIds)
192  {
193  const polyPatch& pp = patches[patchId];
194 
196  (
197  meshProxy.mesh(),
198  labelList(one{}, pp.index()),
199  writeOpts,
200  nearCellValue,
201  // Output patch: "boundary"/name
202  (
203  writeOpts.legacy()
204  ?
205  (
206  outputDir/regionDir/pp.name()
207  / (meshProxy.useSubMesh() ? meshProxy.name() : pp.name())
208  + timeDesc
209  )
210  : (vtmOutputBase / "boundary" / pp.name())
211  ),
212  Pstream::parRun()
213  );
214 
215  if (!nPatchWriters)
216  {
217  vtmWriter.beginBlock("boundary");
218  vtmBoundaries.beginBlock("boundary");
219  }
220 
221  vtmWriter.append_vtp
222  (
223  pp.name(),
224  vtmOutputBase.name()/"boundary"/pp.name()
225  );
226 
227  vtmBoundaries.append_vtp
228  (
229  pp.name(),
230  "boundary"/pp.name()
231  );
232 
233  Info<< " Boundary : "
234  << args.relativePath(writer->output()) << nl;
235 
236  writer->writeTimeValue(timeValue);
237  writer->writeGeometry();
238 
239  // Transfer writer to list for later use
241 
242  if (patchInterps.size())
243  {
244  patchInterps.set
245  (
246  nPatchInterps++,
247  new PrimitivePatchInterpolation<primitivePatch>(pp)
248  );
249  }
250  }
251 
252  if (nPatchWriters)
253  {
254  vtmWriter.endBlock("boundary");
255  }
256 
257  patchWriters.resize(nPatchWriters);
258  patchInterps.resize(nPatchInterps);
259  }
260 
261 
262  // CellData
263  {
264  // Begin CellData
265  if (internalWriter)
266  {
267  // Optionally with (cellID, procID) fields
268  internalWriter->beginCellData
269  (
270  (withMeshIds ? 1 + (internalWriter->parallel() ? 1 : 0) : 0)
272  );
273 
274  if (withMeshIds)
275  {
276  internalWriter->writeCellIDs();
277  internalWriter->writeProcIDs(); // parallel only
278  }
279  }
280 
281  if (nVolFields || withMeshIds)
282  {
283  for (vtk::patchWriter& writer : patchWriters)
284  {
285  // Optionally with (patchID, procID) fields
286  writer.beginCellData
287  (
288  (withMeshIds ? 2 : 0)
289  + nVolFields
290  );
291 
292  if (withMeshIds)
293  {
294  writer.writePatchIDs();
295  writer.writeProcIDs();
296  }
297  }
298  }
299 
301  (
303  patchWriters,
304  meshProxy,
305  objects,
306  true // syncPar
307  );
308 
310  (
312  meshProxy,
313  objects,
314  true // syncPar
315  );
316 
317  // End CellData is implicit
318  }
319 
320 
321  // PointData
322  // - only construct pointMesh on request since it constructs
323  // edge addressing
324  if (doPointValues)
325  {
326  // Begin PointData
327  if (internalWriter)
328  {
329  internalWriter->beginPointData
330  (
332  + (withPointIds ? 1 : 0)
333  );
334 
335  if (withPointIds)
336  {
337  internalWriter->writePointIDs();
338  }
339  }
340 
341  forAll(patchWriters, writeri)
342  {
343  const label nPatchFields =
344  (
345  (
346  writeri < patchInterps.size() && patchInterps.set(writeri)
347  ? nVolFields
348  : 0
349  )
350  + nPointFields
351  );
352 
353  if (nPatchFields)
354  {
355  patchWriters[writeri].beginPointData(nPatchFields);
356  }
357  }
358 
360  (
363  meshProxy,
364  objects,
365  true // syncPar
366  );
367 
369  (
371  meshProxy,
372  objects,
373  true // syncPar
374  );
375 
377  (
379  patchWriters,
380  meshProxy,
381  objects,
382  true // syncPar
383  );
384 
385  // End PointData is implicit
386  }
387 
388 
389  // Finish writers
391  {
392  internalWriter->close();
393  }
394 
395  for (vtk::patchWriter& writer : patchWriters)
396  {
397  writer.close();
398  }
399 
400  pInterp.clear();
401  patchWriters.clear();
402  patchInterps.clear();
403 
404 
405  // Collective output
406 
407  if (Pstream::master())
408  {
409  // Naming for vtm, file series etc.
410  fileName outputName(vtmOutputBase);
411 
412  if (writeOpts.legacy())
413  {
414  if (doInternal)
415  {
416  // Add to file-series and emit as JSON
417 
419 
420  fileName seriesName(vtk::seriesWriter::base(outputName));
421 
422  vtk::seriesWriter& series = vtkSeries(seriesName);
423 
424  // First time?
425  // Load from file, verify against filesystem,
426  // prune time >= currentTime
427  if (series.empty())
428  {
429  series.load(seriesName, true, timeValue);
430  }
431 
432  series.append(timeValue, timeDesc);
433  series.write(seriesName);
434  }
435  }
436  else
437  {
438  if (vtmWriter.size())
439  {
440  // Emit ".vtm"
441 
442  outputName.ext(vtmWriter.ext());
443 
444  fileName seriesName(vtk::seriesWriter::base(outputName));
445 
446  vtmWriter.setTime(timeValue);
447  vtmWriter.write(outputName);
448 
449  // Add to file-series and emit as JSON
450 
451  vtk::seriesWriter& series = vtkSeries(seriesName);
452 
453  // First time?
454  // Load from file, verify against filesystem,
455  // prune time >= currentTime
456  if (series.empty())
457  {
458  series.load(seriesName, true, timeValue);
459  }
460 
461  series.append(timeValue, outputName);
462  series.write(seriesName);
463 
464  // Add to multi-region vtm
465  vtmMultiRegion.add(regionName, regionDir, vtmWriter);
466  }
467 
468  if (vtmBoundaries.size())
469  {
470  // Emit "boundary.vtm" with collection of boundaries
471 
472  // Naming for vtm
473  fileName outputName(vtmOutputBase / "boundary");
474  outputName.ext(vtmBoundaries.ext());
475 
476  vtmBoundaries.setTime(timeValue);
477  vtmBoundaries.write(outputName);
478  }
479  }
480  }
481 }
482 
483 
484 // ************************************************************************* //
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
vtmWriter
vtk::vtmWriter vtmWriter
Definition: convertVolumeFields.H:72
Foam::vtk::fileExtension
const Foam::Enum< fileTag > fileExtension
File extension (without ".") for some vtk XML file content types.
patchIds
labelList patchIds
Definition: convertVolumeFields.H:132
vtmBoundaries
vtk::vtmWriter vtmBoundaries
Definition: convertVolumeFields.H:75
Foam::fieldTypes::volume
const wordList volume
Standard volume field types (scalar, vector, tensor, etc)
Foam::fieldTypes::internal
const wordList internal
Standard dimensioned field types (scalar, vector, tensor, etc)
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
outputName
word outputName("finiteArea-edges.obj")
regionName
Foam::word regionName
Definition: createNamedDynamicFvMesh.H:1
patches
const polyBoundaryMesh & patches
Definition: convertVolumeFields.H:127
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
vtmOutputBase
fileName vtmOutputBase(outputDir/regionDir/vtkName+timeDesc)
Foam::writeAllVolFields
label writeAllVolFields(ensightCase &ensCase, const ensightMesh &ensMesh, const IOobjectList &objects, const bool nearCellValue=false)
Definition: writeVolFields.H:126
writeAllDimFields
writeAllDimFields(internalWriter, meshProxy, objects, true)
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
internalWriter
autoPtr< vtk::internalWriter > internalWriter
Definition: convertVolumeFields.H:78
nDimFields
const label nDimFields
Definition: convertVolumeFields.H:44
nPointFields
const label nPointFields
Definition: convertVolumeFields.H:51
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
nPatchWriters
label nPatchWriters
Definition: convertProcessorPatches.H:85
Foam::nl
constexpr char nl
Definition: Ostream.H:404
patchWriters
PtrList< vtk::patchWriter > patchWriters
Definition: convertVolumeFields.H:129
patchId
label patchId(-1)
regionDir
const word & regionDir
Definition: findMeshDefinitionDict.H:34
Foam::point
vector point
Point is a vector.
Definition: point.H:43
args
Foam::argList args(argc, argv)
writer
vtk::internalMeshWriter writer(topoMesh, topoCells, vtk::formatType::INLINE_ASCII, runTime.path()/"blockTopology")
patchInterps
PtrList< PrimitivePatchInterpolation< primitivePatch > > patchInterps
Definition: convertVolumeFields.H:130
Foam::argList::relativePath
fileName relativePath(const fileName &input, const bool caseTag=false) const
Definition: argListI.H:94
pInterp
autoPtr< volPointInterpolation > pInterp
Definition: convertVolumeFields.H:81
Foam::writeAllPointFields
label writeAllPointFields(ensightCase &ensCase, const ensightMesh &ensMesh, const IOobjectList &objects)
Definition: writePointFields.H:107
nVolFields
const label nVolFields
Definition: convertVolumeFields.H:37