vtkWrite.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) 2017-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 #include "vtkWrite.H"
29 #include "dictionary.H"
30 #include "Time.H"
31 #include "areaFields.H"
32 #include "stringListOps.H"
33 #include "foamVtkInternalWriter.H"
34 #include "foamVtkPatchWriter.H"
35 #include "foamVtkSeriesWriter.H"
36 #include "foamVtmWriter.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43 namespace functionObjects
44 {
45  defineTypeNameAndDebug(vtkWrite, 0);
46  addToRunTimeSelectionTable(functionObject, vtkWrite, dictionary);
47 }
48 }
49 
50 
51 // Implementation
52 #include "vtkWriteImpl.C"
53 
54 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
55 
56 Foam::label Foam::functionObjects::vtkWrite::writeAllVolFields
57 (
58  autoPtr<vtk::internalWriter>& internalWriter,
59  UPtrList<vtk::patchWriter>& patchWriters,
60  const fvMeshSubset& proxy,
61  const wordHashSet& candidateNames
62 ) const
63 {
64  label count = 0;
65 
66  {
67  #undef doLocalCode
68  #define doLocalCode(FieldType) \
69  count += writeVolFieldsImpl<FieldType> \
70  ( \
71  internalWriter, \
72  patchWriters, \
73  proxy, \
74  candidateNames \
75  );
76 
82 
83  #undef doLocalCode
84  }
85 
86  return count;
87 }
88 
89 
90 Foam::label Foam::functionObjects::vtkWrite::writeAllVolFields
91 (
92  autoPtr<vtk::internalWriter>& internalWriter,
93  const autoPtr<volPointInterpolation>& pInterp,
94 
95  UPtrList<vtk::patchWriter>& patchWriters,
96  const UPtrList<PrimitivePatchInterpolation<primitivePatch>>& patchInterps,
97  const fvMeshSubset& proxy,
98  const wordHashSet& candidateNames
99 ) const
100 {
101  label count = 0;
102 
103  {
104  #undef doLocalCode
105  #define doLocalCode(FieldType) \
106  count += writeVolFieldsImpl<FieldType> \
107  ( \
108  internalWriter, pInterp, \
109  patchWriters, patchInterps, \
110  proxy, \
111  candidateNames \
112  );
113 
119 
120  #undef doLocalCode
121  }
122 
123  return count;
124 }
125 
126 
127 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
128 
129 Foam::functionObjects::vtkWrite::vtkWrite
130 (
131  const word& name,
132  const Time& runTime,
133  const dictionary& dict
134 )
135 :
137  outputDir_(),
138  printf_(),
139  writeOpts_(vtk::formatType::INLINE_BASE64),
140  verbose_(true),
141  doInternal_(true),
142  doBoundary_(true),
143  oneBoundary_(false),
144  interpolate_(false),
145  decompose_(false),
146  writeIds_(false),
147  meshState_(polyMesh::TOPO_CHANGE),
148  selectRegions_(),
149  selectPatches_(),
150  blockPatches_(),
151  selectFields_(),
152  blockFields_(),
153  selection_(),
154  meshes_(),
155  meshSubsets_(),
156  vtuMappings_(),
157  series_()
158 {
159  // May still want this? (OCT-2018)
160  // if (postProcess)
161  // {
162  // // Disable for post-process mode.
163  // // Emit as FatalError for the try/catch in the caller.
164  // FatalError
165  // << type() << " disabled in post-process mode"
166  // << exit(FatalError);
167  // }
169  read(dict);
170 }
171 
172 
173 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
174 
176 {
178 
179  readSelection(dict);
180 
181  // We probably cannot trust old information after a reread
182  series_.clear();
183 
184  // verbose_ = dict.getOrDefault("verbose", true);
185  doInternal_ = dict.getOrDefault("internal", true);
186  doBoundary_ = dict.getOrDefault("boundary", true);
187  oneBoundary_ = dict.getOrDefault("single", false);
188  interpolate_ = dict.getOrDefault("interpolate", false);
189 
190  //
191  // Writer options - default is xml base64
192  //
193  writeOpts_ = vtk::formatType::INLINE_BASE64;
194 
195  writeOpts_.ascii
196  (
199  );
200 
201  writeOpts_.legacy(dict.getOrDefault("legacy", false));
202 
203  writeOpts_.precision
204  (
205  dict.getOrDefault("precision", IOstream::defaultPrecision())
206  );
207 
208  // Info<< type() << " " << name() << " output-format: "
209  // << writeOpts_.description() << nl;
210 
211  const int padWidth = dict.getOrDefault<int>("width", 8);
212 
213  // Appropriate printf format - Enforce min/max sanity limits
214  if (padWidth < 1 || padWidth > 31)
215  {
216  printf_.clear();
217  }
218  else
219  {
220  printf_ = "%0" + std::to_string(padWidth) + "d";
221  }
222 
223  //
224  // Other options
225  //
226 
227  decompose_ = dict.getOrDefault("decompose", false);
228  writeIds_ = dict.getOrDefault("writeIds", false);
229 
230 
231  // Output directory
232 
233  outputDir_.clear();
234  dict.readIfPresent("directory", outputDir_);
235 
236  if (outputDir_.size())
237  {
238  // User-defined output directory
239  outputDir_.expand();
240  if (!outputDir_.isAbsolute())
241  {
242  outputDir_ = time_.globalPath()/outputDir_;
243  }
244  }
245  else
246  {
247  // Standard postProcessing/ naming
248  outputDir_ = time_.globalPath()/functionObject::outputPrefix/name();
249  }
250  outputDir_.clean(); // Remove unneeded ".."
251 
252  return true;
253 }
254 
257 {
258  return true;
259 }
260 
261 
263 {
264  // const word timeDesc =
265  // useTimeName ? time_.timeName() : Foam::name(time_.timeIndex());
266 
267  const word timeDesc = "_" +
268  (
269  printf_.empty()
270  ? Foam::name(time_.timeIndex())
271  : word::printf(printf_, time_.timeIndex())
272  );
273 
274  const scalar timeValue = time_.value();
275 
276  update();
277 
278  if (meshes_.empty() || (!doInternal_ && !doBoundary_))
279  {
280  // Skip
281  return true;
282  }
283 
284 
285  fileName vtkName = time_.globalCaseName();
286 
287  vtk::vtmWriter vtmMultiRegion;
288 
289  Info<< name() << " output Time: " << time_.timeName() << nl;
290 
291  label regioni = 0;
292  for (const fvMesh& mesh : meshes_)
293  {
294  const word& regionName = mesh.name();
296 
297  auto& meshProxy = meshSubsets_[regioni];
298  auto& vtuMeshCells = vtuMappings_[regioni];
299  ++regioni;
300 
301  const fvMesh& baseMesh = meshProxy.baseMesh();
302 
303 
304  // Output fields MUST be specified to avoid accidentally
305  // writing everything. Can still use ".*" for everything
306 
307  wordHashSet candidateNames(0);
308 
309  if (!selectFields_.empty())
310  {
311  if (!blockFields_.empty())
312  {
313  // With 'allow' and 'deny' filters
314  wordRes::filter filter(selectFields_, blockFields_);
315 
316  candidateNames = baseMesh.names<void>(filter);
317  }
318  else
319  {
320  // With 'allow' filter only
321  candidateNames = baseMesh.names<void>(selectFields_);
322  }
323  }
324 
325  // Prune restart fields
326  candidateNames.filterKeys
327  (
328  [](const word& k){ return k.ends_with("_0"); },
329  true // prune
330  );
331 
332  const label nVolFields =
333  (
334  (doInternal_ || doBoundary_)
335  ? baseMesh.count
336  (
337  stringListOps::foundOp<word>(fieldTypes::volume),
338  candidateNames
339  )
340  : 0
341  );
342 
343  // Undecided if we want to automatically support DimensionedFields
344  // or only on demand:
345  const label nDimFields = 0;
346  // (
347  // (doInternal_ || doBoundary_)
348  // ? baseMesh.count
349  // (
350  // stringListOps::foundOp<word>(fieldTypes::internal),
351  // candidateNames
352  // )
353  // : 0
354  // );
355 
356 
357  // Setup for the vtm writer.
358  // For legacy format, the information added is simply ignored.
359 
360  fileName vtmOutputBase
361  (
362  outputDir_/regionDir/vtkName + timeDesc
363  );
364 
365  // Combined internal + boundary in a vtm file
367 
368  // Collect individual boundaries into a vtm file
370 
371  // Setup the internal writer
372  autoPtr<vtk::internalWriter> internalWriter;
373 
374  // Interpolator for volume and dimensioned fields
375  autoPtr<volPointInterpolation> pInterp;
376 
377  if (doInternal_)
378  {
379  if (vtuMeshCells.empty())
380  {
381  // Use the appropriate mesh (baseMesh or subMesh)
382  vtuMeshCells.reset(meshProxy.mesh());
383 
384  if (interpolate_ && vtuMeshCells.manifold())
385  {
386  interpolate_ = false;
388  << "Manifold cells detected - disabling PointData"
389  << endl;
390  }
391  }
392 
394  (
395  meshProxy.mesh(),
396  vtuMeshCells,
397  writeOpts_,
398  // Output name for internal
399  (
400  writeOpts_.legacy()
401  ? vtmOutputBase
402  : (vtmOutputBase / "internal")
403  ),
405  );
406 
407  Info<< " Internal : "
408  << time_.relativePath(internalWriter->output())
409  << endl;
410 
411  // No sub-block for internal
412  vtmWriter.append_vtu
413  (
414  "internal",
415  vtmOutputBase.name()/"internal"
416  );
417 
418  internalWriter->writeTimeValue(timeValue);
419  internalWriter->writeGeometry();
420 
421  if (interpolate_)
422  {
423  pInterp.reset(new volPointInterpolation(meshProxy.mesh()));
424  }
425  }
426 
427 
428  // Setup the patch writers
429 
430  const polyBoundaryMesh& patches = meshProxy.mesh().boundaryMesh();
431 
432  PtrList<vtk::patchWriter> patchWriters;
433  PtrList<PrimitivePatchInterpolation<primitivePatch>> patchInterps;
434 
436  if (doBoundary_)
437  {
438  patchIds = getSelectedPatches(patches);
439  }
440 
441  if (oneBoundary_ && patchIds.size())
442  {
444  (
445  meshProxy.mesh(),
446  patchIds,
447  writeOpts_,
448  // Output name for one patch: "boundary"
449  (
450  writeOpts_.legacy()
451  ? (outputDir_/regionDir/"boundary"/"boundary" + timeDesc)
452  : (vtmOutputBase / "boundary")
453  ),
455  );
456 
457  // No sub-block for one-patch
458  vtmWriter.append_vtp
459  (
460  "boundary",
461  vtmOutputBase.name()/"boundary"
462  );
463 
464  Info<< " Boundaries: "
465  << time_.relativePath(writer->output()) << nl;
466 
467 
468  writer->writeTimeValue(timeValue);
469  writer->writeGeometry();
470 
471  // Transfer writer to list for later use
472  patchWriters.resize(1);
473  patchWriters.set(0, writer);
474 
475  // Avoid patchInterpolation for each sub-patch
476  patchInterps.resize(1); // == nullptr
477  }
478  else if (patchIds.size())
479  {
480  patchWriters.resize(patchIds.size());
481  if (interpolate_)
482  {
483  patchInterps.resize(patchIds.size());
484  }
485 
486  label nPatchWriters = 0;
487  label nPatchInterps = 0;
488 
489  for (const label patchId : patchIds)
490  {
491  const polyPatch& pp = patches[patchId];
492 
494  (
495  meshProxy.mesh(),
496  labelList(one{}, pp.index()),
497  writeOpts_,
498  // Output name for patch: "boundary"/name
499  (
500  writeOpts_.legacy()
501  ?
502  (
503  outputDir_/regionDir/pp.name()
504  / (pp.name()) + timeDesc
505  )
506  : (vtmOutputBase / "boundary" / pp.name())
507  ),
509  );
510 
511  if (!nPatchWriters)
512  {
513  vtmWriter.beginBlock("boundary");
514  vtmBoundaries.beginBlock("boundary");
515  }
516 
517  vtmWriter.append_vtp
518  (
519  pp.name(),
520  vtmOutputBase.name()/"boundary"/pp.name()
521  );
522 
523  vtmBoundaries.append_vtp
524  (
525  pp.name(),
526  "boundary"/pp.name()
527  );
528 
529  Info<< " Boundary : "
530  << time_.relativePath(writer->output()) << nl;
531 
532  writer->writeTimeValue(timeValue);
533  writer->writeGeometry();
534 
535  // Transfer writer to list for later use
537 
538  if (patchInterps.size())
539  {
540  patchInterps.set
541  (
542  nPatchInterps++,
543  new PrimitivePatchInterpolation<primitivePatch>(pp)
544  );
545  }
546  }
547 
548  if (nPatchWriters)
549  {
550  vtmWriter.endBlock("boundary");
551  vtmBoundaries.endBlock("boundary");
552  }
553 
554  patchWriters.resize(nPatchWriters);
555  patchInterps.resize(nPatchInterps);
556  }
557 
558  // CellData
559  {
560  if (internalWriter)
561  {
562  // Optionally with cellID and procID fields
563  internalWriter->beginCellData
564  (
565  (writeIds_ ? 1 + (internalWriter->parallel() ? 1 : 0) : 0)
567  );
568 
569  if (writeIds_)
570  {
571  internalWriter->writeCellIDs();
572  internalWriter->writeProcIDs(); // parallel only
573  }
574  }
575 
576  if (nVolFields)
577  {
578  for (vtk::patchWriter& writer : patchWriters)
579  {
580  // Optionally with patchID field
581  writer.beginCellData
582  (
583  (writeIds_ ? 1 : 0)
584  + nVolFields
585  );
586 
587  if (writeIds_)
588  {
589  writer.writePatchIDs();
590  }
591  }
592  }
593 
595  (
597  patchWriters,
598  meshProxy,
599  candidateNames
600  );
601 
602  // writeAllDimFields
603  // (
604  // internalWriter,
605  // meshProxy,
606  // candidateNames
607  // );
608 
609  // End CellData is implicit
610  }
611 
612 
613  // PointData
614  // - only construct pointMesh on request since it constructs
615  // edge addressing
616  if (interpolate_)
617  {
618  // Begin PointData
619  if (internalWriter)
620  {
621  internalWriter->beginPointData
622  (
624  );
625  }
626 
627  forAll(patchWriters, writeri)
628  {
629  const label nPatchFields =
630  (
631  patchInterps.test(writeri) ? nVolFields : 0
632  );
633 
634  if (nPatchFields)
635  {
636  patchWriters[writeri].beginPointData(nPatchFields);
637  }
638  }
639 
641  (
644  meshProxy,
645  candidateNames
646  );
647 
648  // writeAllDimFields
649  // (
650  // internalWriter, pInterp,
651  // meshProxy,
652  // candidateNames
653  // );
654 
655  // writeAllPointFields
656  // (
657  // internalWriter,
658  // patchWriters,
659  // meshProxy,
660  // candidateNames
661  // );
662 
663  // End PointData is implicit
664  }
665 
666 
667  // Finish writers
668  if (internalWriter)
669  {
670  internalWriter->close();
671  }
672 
673  for (vtk::patchWriter& writer : patchWriters)
674  {
675  writer.close();
676  }
677 
678  pInterp.clear();
679  patchWriters.clear();
680  patchInterps.clear();
681 
682 
683  // Collective output
684 
685  if (Pstream::master())
686  {
687  // Naming for vtm, file series etc.
688  fileName outputName(vtmOutputBase);
689 
690  if (writeOpts_.legacy())
691  {
692  if (doInternal_)
693  {
694  // Add to file-series and emit as JSON
695 
697 
698  fileName seriesName(vtk::seriesWriter::base(outputName));
699 
700  vtk::seriesWriter& series = series_(seriesName);
701 
702  // First time?
703  // Load from file, verify against filesystem,
704  // prune time >= currentTime
705  if (series.empty())
706  {
707  series.load(seriesName, true, timeValue);
708  }
709 
710  series.append(timeValue, timeDesc);
711  series.write(seriesName);
712  }
713  }
714  else
715  {
716  if (vtmWriter.size())
717  {
718  // Emit ".vtm"
719 
720  outputName.ext(vtmWriter.ext());
721 
722  vtmWriter.setTime(timeValue);
723  vtmWriter.write(outputName);
724 
725  fileName seriesName(vtk::seriesWriter::base(outputName));
726 
727  vtk::seriesWriter& series = series_(seriesName);
728 
729  // First time?
730  // Load from file, verify against filesystem,
731  // prune time >= currentTime
732  if (series.empty())
733  {
734  series.load(seriesName, true, timeValue);
735  }
736 
737  series.append(timeValue, outputName);
738  series.write(seriesName);
739 
740  // Add to multi-region vtm
741  vtmMultiRegion.add(regionName, regionDir, vtmWriter);
742  }
743 
744  if (vtmBoundaries.size())
745  {
746  // Emit "boundary.vtm" with collection of boundaries
747 
748  // Naming for vtm
749  fileName outputName(vtmOutputBase / "boundary");
750  outputName.ext(vtmBoundaries.ext());
751 
752  vtmBoundaries.setTime(timeValue);
753  vtmBoundaries.write(outputName);
754  }
755  }
756  }
757  }
758 
759 
760  // Emit multi-region vtm
761  if (Pstream::master() && meshes_.size() > 1)
762  {
763  fileName outputName
764  (
765  outputDir_/vtkName + "-regions" + timeDesc + ".vtm"
766  );
767 
768  vtmMultiRegion.setTime(timeValue);
769  vtmMultiRegion.write(outputName);
770 
771  fileName seriesName(vtk::seriesWriter::base(outputName));
772 
773  vtk::seriesWriter& series = series_(seriesName);
774 
775  // First time?
776  // Load from file, verify against filesystem,
777  // prune time >= currentTime
778  if (series.empty())
779  {
780  series.load(seriesName, true, timeValue);
781  }
782 
783  series.append(timeValue, outputName);
784  series.write(seriesName);
785  }
786 
787  return true;
788 }
789 
790 
792 {
793  meshSubsets_.clear();
794  vtuMappings_.clear();
795  meshes_.clear();
796 
797  return true;
798 }
799 
800 
801 // ************************************************************************* //
label patchId(-1)
Provides a means of accumulating file entries for generating a vtkMultiBlockDataSet (...
Definition: foamVtmWriter.H:87
GeometricField< symmTensor, fvPatchField, volMesh > volSymmTensorField
Definition: volFieldsFwd.H:85
labelList patchIds
dictionary dict
defineTypeNameAndDebug(ObukhovLength, 0)
A class for handling file names.
Definition: fileName.H:72
static fileName base(const fileName &outputName, char sep='_')
Extract the base name for a file series.
virtual bool write()
Write fields.
Definition: vtkWrite.C:255
vtk::lineWriter writer(edgeCentres, edgeList::null(), fileName(aMesh.time().globalPath()/"finiteArea-edgesCentres"))
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
const word & regionName() const
The mesh region name or word::null if polyMesh::defaultRegion.
Definition: polyMesh.C:847
const word fileExtension
Legacy file extension ("vtk")
GeometricField< tensor, fvPatchField, volMesh > volTensorField
Definition: volFieldsFwd.H:86
label writeAllVolFields(ensightCase &ensCase, const ensightMesh &ensMesh, const IOobjectList &objects, const bool nearCellValue=false)
label write(const fileName &file)
Open file for writing (creates parent directory) and write the blocks and TimeValue.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
"ascii" (normal default)
wordList names() const
The unsorted names of all objects.
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1049
static unsigned int defaultPrecision() noexcept
Return the default precision.
Definition: IOstream.H:423
fileName vtmOutputBase(outputDir/regionDir/vtkName+timeDesc)
const label nDimFields
Operations on lists of strings.
label k
Boltzmann constant.
GeometricField< vector, fvPatchField, volMesh > volVectorField
Definition: volFieldsFwd.H:82
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
GeometricField< sphericalTensor, fvPatchField, volMesh > volSphericalTensorField
Definition: volFieldsFwd.H:84
Macros for easy insertion into run-time selection tables.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:81
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
word outputName("finiteArea-edges.obj")
dynamicFvMesh & mesh
label count(const char *clsName) const
The number of objects of the given class name.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
A class for handling words, derived from Foam::string.
Definition: word.H:63
Functor wrapper of allow/deny lists of wordRe for filtering.
Definition: wordRes.H:216
void setTime(scalar timeValue)
Define "TimeValue" for FieldData (name as per Catalyst output)
formatType
The output format type for file contents.
Definition: foamVtkCore.H:66
label nPatchWriters
const label nVolFields
autoPtr< vtk::internalWriter > internalWriter
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition: HashSet.H:73
static word printf(const char *fmt, const PrimitiveType &val)
Use a printf-style formatter for a primitive.
const wordList volume
Standard volume field types (scalar, vector, tensor, etc)
mesh update()
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary)
PtrList< PrimitivePatchInterpolation< primitivePatch > > patchInterps
#define WarningInFunction
Report a warning using Foam::Warning.
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
vtk::vtmWriter vtmBoundaries
const word & regionDir
virtual bool read(const dictionary &dict)
Read and set the function object if its data have changed.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
static streamFormat formatEnum(const word &fmtName, const streamFormat deflt=streamFormat::ASCII)
Lookup streamFormat enum corresponding to the string (ascii | binary).
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
const polyBoundaryMesh & patches
vtk::vtmWriter vtmWriter
static word outputPrefix
Directory prefix.
messageStream Info
Information stream (stdout output on master, null elsewhere)
virtual bool execute()
Execute - does nothing.
Definition: vtkWrite.C:249
XML inline base64, base64Formatter.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
List< label > labelList
A List of labels.
Definition: List.H:62
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
Definition: autoPtr.H:178
virtual bool read(const dictionary &dict)
Read the vtkWrite specification.
Definition: vtkWrite.C:168
virtual bool end()
On end - cleanup internal allocations.
Definition: vtkWrite.C:784
void add(const word &blockName, const vtmWriter &other)
Add in content from another vtm and place under the given block name.
PtrList< vtk::patchWriter > patchWriters
Virtual base class for function objects with a reference to Time.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
autoPtr< volPointInterpolation > pInterp
#define doLocalCode(FieldType)