vtkPVFoamUpdateInfo.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "vtkPVFoam.H"
27 
28 // OpenFOAM includes
29 #include "cellSet.H"
30 #include "faceSet.H"
31 #include "pointSet.H"
32 #include "IOobjectList.H"
33 #include "IOPtrList.H"
35 #include "entry.H"
36 #include "Cloud.H"
37 #include "vtkPVFoamReader.h"
38 
39 // local headers
42 
43 // VTK includes
44 #include "vtkDataArraySelection.h"
45 
46 
47 // * * * * * * * * * * * * * * * Private Classes * * * * * * * * * * * * * * //
48 
49 namespace Foam
50 {
51 
52 //- A class for reading zone information without requiring a mesh
53 class zonesEntries
54 :
55  public regIOobject,
56  public PtrList<entry>
57 {
58 
59 public:
60 
61  // Constructors
62 
63  explicit zonesEntries(const IOobject& io)
64  :
65  regIOobject(io),
66  PtrList<entry>(readStream(word("regIOobject")))
67  {
68  close();
69  }
70 
71  // Member functions
72 
73  bool writeData(Ostream&) const
74  {
76  return false;
77  }
78 };
79 
80 }
81 
82 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
83 
84 template<class ZoneType>
85 Foam::wordList Foam::vtkPVFoam::getZoneNames
86 (
87  const ZoneMesh<ZoneType, polyMesh>& zmesh
88 ) const
89 {
90  wordList names(zmesh.size());
91  label nZone = 0;
92 
93  forAll(zmesh, zoneI)
94  {
95  if (zmesh[zoneI].size())
96  {
97  names[nZone++] = zmesh[zoneI].name();
98  }
99  }
100  names.setSize(nZone);
101 
102  return names;
103 }
104 
105 
106 Foam::wordList Foam::vtkPVFoam::getZoneNames(const word& zoneType) const
107 {
108  wordList names;
109 
110  // mesh not loaded - read from file
111  IOobject ioObj
112  (
113  zoneType,
114  dbPtr_().findInstance
115  (
116  meshDir_,
117  zoneType,
119  ),
120  meshDir_,
121  dbPtr_(),
124  false
125  );
126 
127  if (ioObj.typeHeaderOk<cellZoneMesh>(false))
128  {
129  zonesEntries zones(ioObj);
130 
131  names.setSize(zones.size());
132  forAll(zones, zoneI)
133  {
134  names[zoneI] = zones[zoneI].keyword();
135  }
136  }
137 
138  return names;
139 }
140 
141 
142 void Foam::vtkPVFoam::updateInfoInternalMesh
143 (
144  vtkDataArraySelection* arraySelection
145 )
146 {
147  if (debug)
148  {
149  Info<< "<beg> Foam::vtkPVFoam::updateInfoInternalMesh" << endl;
150  }
151 
152  // Determine mesh parts (internalMesh, patches...)
153  //- Add internal mesh as first entry
154  arrayRangeVolume_.reset(arraySelection->GetNumberOfArrays());
155  arraySelection->AddArray
156  (
157  "internalMesh"
158  );
159  arrayRangeVolume_ += 1;
160 
161  if (debug)
162  {
163  // just for debug info
164  getSelectedArrayEntries(arraySelection);
165 
166  Info<< "<end> Foam::vtkPVFoam::updateInfoInternalMesh" << endl;
167  }
168 }
169 
170 
171 void Foam::vtkPVFoam::updateInfoLagrangian
172 (
173  vtkDataArraySelection* arraySelection
174 )
175 {
176  if (debug)
177  {
178  Info<< "<beg> Foam::vtkPVFoam::updateInfoLagrangian" << nl
179  << " " << dbPtr_->timePath()/cloud::prefix << endl;
180  }
181 
182 
183  // use the db directly since this might be called without a mesh,
184  // but the region must get added back in
185  fileName lagrangianPrefix(cloud::prefix);
186  if (meshRegion_ != polyMesh::defaultRegion)
187  {
188  lagrangianPrefix = meshRegion_/cloud::prefix;
189  }
190 
191  arrayRangeLagrangian_.reset(arraySelection->GetNumberOfArrays());
192 
193  // Generate a list of lagrangian clouds across all times
194  HashSet<fileName> cloudDirs;
195 
196  // Get times list. Flush first to force refresh.
197  fileHandler().flush();
198  instantList times = dbPtr_().times();
199  forAll(times, timei)
200  {
201  cloudDirs +=
202  readDir
203  (
204  dbPtr_->path()/times[timei].name()/lagrangianPrefix,
206  );
207  }
208 
209  forAllConstIter(HashSet<fileName>, cloudDirs, cloudIter)
210  {
211  arraySelection->AddArray
212  (
213  (cloudIter.key() + " - lagrangian").c_str()
214  );
215  }
216 
217  arrayRangeLagrangian_ += cloudDirs.size();
218 
219  if (debug)
220  {
221  // just for debug info
222  getSelectedArrayEntries(arraySelection);
223 
224  Info<< "<end> Foam::vtkPVFoam::updateInfoLagrangian" << endl;
225  }
226 }
227 
228 
229 void Foam::vtkPVFoam::updateInfoPatches
230 (
231  vtkDataArraySelection* arraySelection,
232  stringList& enabledEntries,
233  const bool first
234 )
235 {
236  if (debug)
237  {
238  Info<< "<beg> Foam::vtkPVFoam::updateInfoPatches"
239  << " [meshPtr=" << (meshPtr_ ? "set" : "nullptr") << "]" << endl;
240  }
241 
242 
243  HashSet<string> enabledEntriesSet(enabledEntries);
244 
245  arrayRangePatches_.reset(arraySelection->GetNumberOfArrays());
246 
247  int nPatches = 0;
248  if (meshPtr_)
249  {
250  const polyBoundaryMesh& patches = meshPtr_->boundaryMesh();
251  const HashTable<labelList, word>& groups = patches.groupPatchIDs();
252  const wordList allPatchNames = patches.names();
253 
254  // Add patch groups
255  // ~~~~~~~~~~~~~~~~
256 
257  for
258  (
259  HashTable<labelList, word>::const_iterator iter = groups.begin();
260  iter != groups.end();
261  ++iter
262  )
263  {
264  const word& groupName = iter.key();
265  const labelList& patchIDs = iter();
266 
267  label nFaces = 0;
268  forAll(patchIDs, i)
269  {
270  nFaces += patches[patchIDs[i]].size();
271  }
272 
273  // Valid patch if nFace > 0 - add patch to GUI list
274  if (nFaces)
275  {
276  string vtkGrpName = groupName + " - group";
277  arraySelection->AddArray(vtkGrpName.c_str());
278 
279  ++nPatches;
280 
281  if (enabledEntriesSet.found(vtkGrpName))
282  {
283  if (!reader_->GetShowGroupsOnly())
284  {
285  enabledEntriesSet.erase(vtkGrpName);
286  forAll(patchIDs, i)
287  {
288  const polyPatch& pp = patches[patchIDs[i]];
289  if (pp.size())
290  {
291  string vtkPatchName
292  (
293  pp.name() + " - " + pp.type()
294  );
295 
296  enabledEntriesSet.insert(vtkPatchName);
297  }
298  }
299  }
300  }
301  }
302  }
303 
304 
305  // Add patches
306  // ~~~~~~~~~~~
307 
308  if (!reader_->GetShowGroupsOnly())
309  {
310  forAll(patches, patchi)
311  {
312  const polyPatch& pp = patches[patchi];
313 
314  if (pp.size())
315  {
316  const string vtkPatchName = pp.name() + " - " + pp.type();
317 
318  // Add patch to GUI list
319  arraySelection->AddArray(vtkPatchName.c_str());
320 
321  ++nPatches;
322  }
323  }
324  }
325  }
326  else
327  {
328  // mesh not loaded - read from file
329  // but this could fail if we've supplied a bad region name
330  IOobject ioObj
331  (
332  "boundary",
333  dbPtr_().findInstance
334  (
335  meshDir_,
336  "boundary",
338  ),
339  meshDir_,
340  dbPtr_(),
343  false
344  );
345 
346  // this should only ever fail if the mesh region doesn't exist
347  if (ioObj.typeHeaderOk<polyBoundaryMesh>(true))
348  {
349  polyBoundaryMeshEntries patchEntries(ioObj);
350 
351 
352  // Read patches and determine sizes
353  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
354 
355  wordList names(patchEntries.size());
356  labelList sizes(patchEntries.size());
357 
358  forAll(patchEntries, patchi)
359  {
360  const dictionary& patchDict = patchEntries[patchi].dict();
361 
362  sizes[patchi] = readLabel(patchDict.lookup("nFaces"));
363  names[patchi] = patchEntries[patchi].keyword();
364  }
365 
366 
367  // Add (non-zero) patch groups to the list of mesh parts
368  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
369 
370  HashTable<labelList, word> groups(patchEntries.size());
371 
372  forAll(patchEntries, patchi)
373  {
374  const dictionary& patchDict = patchEntries[patchi].dict();
375 
376  wordList groupNames;
377  patchDict.readIfPresent("inGroups", groupNames);
378 
379  forAll(groupNames, groupI)
380  {
381  HashTable<labelList, word>::iterator iter = groups.find
382  (
383  groupNames[groupI]
384  );
385  if (iter != groups.end())
386  {
387  iter().append(patchi);
388  }
389  else
390  {
391  groups.insert(groupNames[groupI], labelList(1, patchi));
392  }
393  }
394  }
395 
396  for
397  (
399  groups.begin();
400  iter != groups.end();
401  ++iter
402  )
403  {
404  const word& groupName = iter.key();
405  const labelList& patchIDs = iter();
406 
407  label nFaces = 0;
408  forAll(patchIDs, i)
409  {
410  nFaces += sizes[patchIDs[i]];
411  }
412 
413  // Valid patch if nFace > 0 - add patch to GUI list
414  if (nFaces)
415  {
416  string vtkGrpName = groupName + " - group";
417  arraySelection->AddArray(vtkGrpName.c_str());
418 
419  ++nPatches;
420 
421  if (enabledEntriesSet.found(vtkGrpName))
422  {
423  if (!reader_->GetShowGroupsOnly())
424  {
425  enabledEntriesSet.erase(vtkGrpName);
426  forAll(patchIDs, i)
427  {
428  if (sizes[patchIDs[i]])
429  {
430  const word patchType
431  (
432  patchEntries[patchIDs[i]].dict().lookup
433  (
434  "type"
435  )
436  );
437 
438  string vtkPatchName
439  (
440  names[patchIDs[i]] + " - " + patchType
441  );
442 
443  enabledEntriesSet.insert(vtkPatchName);
444  }
445  }
446  }
447  }
448  }
449  }
450 
451 
452  // Add (non-zero) patches to the list of mesh parts
453  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
454 
455  if (!reader_->GetShowGroupsOnly())
456  {
457  const wordReList defaultPatchTypes
458  (
459  configDict_.lookupOrDefault
460  (
461  "defaultPatchTypes",
462  wordReList(wordList({"patch", "wall"}))
463  )
464  );
465 
466  forAll(names, patchi)
467  {
468  // Valid patch if nFace > 0 - add patch to GUI list
469  if (sizes[patchi])
470  {
471  const word patchType
472  (
473  patchEntries[patchi].dict().lookup("type")
474  );
475 
476  const string vtkPatchName
477  (
478  names[patchi] + " - " + patchType
479  );
480 
481  arraySelection->AddArray(vtkPatchName.c_str());
482 
483  if (first)
484  {
485  if (findStrings(defaultPatchTypes, patchType))
486  {
487  enabledEntriesSet.insert(vtkPatchName);
488  }
489  }
490 
491  ++nPatches;
492  }
493  }
494  }
495  }
496  }
497  arrayRangePatches_ += nPatches;
498 
499  // Update enabled entries in case of group selection
500  enabledEntries = enabledEntriesSet.toc();
501 
502  if (debug)
503  {
504  // just for debug info
505  getSelectedArrayEntries(arraySelection);
506 
507  Info<< "<end> Foam::vtkPVFoam::updateInfoPatches" << endl;
508  }
509 }
510 
511 
512 void Foam::vtkPVFoam::updateInfoZones
513 (
514  vtkDataArraySelection* arraySelection
515 )
516 {
517  if (!reader_->GetIncludeZones())
518  {
519  return;
520  }
521 
522  if (debug)
523  {
524  Info<< "<beg> Foam::vtkPVFoam::updateInfoZones"
525  << " [meshPtr=" << (meshPtr_ ? "set" : "nullptr") << "]" << endl;
526  }
527 
528  wordList namesLst;
529 
530  //
531  // cellZones information
532  // ~~~~~~~~~~~~~~~~~~~~~
533  if (meshPtr_)
534  {
535  namesLst = getZoneNames(meshPtr_->cellZones());
536  }
537  else
538  {
539  namesLst = getZoneNames("cellZones");
540  }
541 
542  arrayRangeCellZones_.reset(arraySelection->GetNumberOfArrays());
543  forAll(namesLst, elemI)
544  {
545  arraySelection->AddArray
546  (
547  (namesLst[elemI] + " - cellZone").c_str()
548  );
549  }
550  arrayRangeCellZones_ += namesLst.size();
551 
552 
553  //
554  // faceZones information
555  // ~~~~~~~~~~~~~~~~~~~~~
556  if (meshPtr_)
557  {
558  namesLst = getZoneNames(meshPtr_->faceZones());
559  }
560  else
561  {
562  namesLst = getZoneNames("faceZones");
563  }
564 
565  arrayRangeFaceZones_.reset(arraySelection->GetNumberOfArrays());
566  forAll(namesLst, elemI)
567  {
568  arraySelection->AddArray
569  (
570  (namesLst[elemI] + " - faceZone").c_str()
571  );
572  }
573  arrayRangeFaceZones_ += namesLst.size();
574 
575 
576  //
577  // pointZones information
578  // ~~~~~~~~~~~~~~~~~~~~~~
579  if (meshPtr_)
580  {
581  namesLst = getZoneNames(meshPtr_->pointZones());
582  }
583  else
584  {
585  namesLst = getZoneNames("pointZones");
586  }
587 
588  arrayRangePointZones_.reset(arraySelection->GetNumberOfArrays());
589  forAll(namesLst, elemI)
590  {
591  arraySelection->AddArray
592  (
593  (namesLst[elemI] + " - pointZone").c_str()
594  );
595  }
596  arrayRangePointZones_ += namesLst.size();
597 
598  if (debug)
599  {
600  // just for debug info
601  getSelectedArrayEntries(arraySelection);
602 
603  Info<< "<end> Foam::vtkPVFoam::updateInfoZones" << endl;
604  }
605 }
606 
607 
608 void Foam::vtkPVFoam::updateInfoSets
609 (
610  vtkDataArraySelection* arraySelection
611 )
612 {
613  if (!reader_->GetIncludeSets())
614  {
615  return;
616  }
617 
618  if (debug)
619  {
620  Info<< "<beg> Foam::vtkPVFoam::updateInfoSets" << endl;
621  }
622 
623  // Add names of sets. Search for last time directory with a sets
624  // subdirectory. Take care not to search beyond the last mesh.
625 
626  word facesInstance = dbPtr_().findInstance
627  (
628  meshDir_,
629  "faces",
631  );
632 
633  word setsInstance = dbPtr_().findInstance
634  (
635  meshDir_/"sets",
636  word::null,
638  facesInstance
639  );
640 
641  IOobjectList objects(dbPtr_(), setsInstance, meshDir_/"sets");
642 
643  if (debug)
644  {
645  Info<< " Foam::vtkPVFoam::updateInfoSets read "
646  << objects.names() << " from " << setsInstance << endl;
647  }
648 
649 
650  arrayRangeCellSets_.reset(arraySelection->GetNumberOfArrays());
651  arrayRangeCellSets_ += addToSelection<cellSet>
652  (
653  arraySelection,
654  objects,
655  " - cellSet"
656  );
657 
658  arrayRangeFaceSets_.reset(arraySelection->GetNumberOfArrays());
659  arrayRangeFaceSets_ += addToSelection<faceSet>
660  (
661  arraySelection,
662  objects,
663  " - faceSet"
664  );
665 
666  arrayRangePointSets_.reset(arraySelection->GetNumberOfArrays());
667  arrayRangePointSets_ += addToSelection<pointSet>
668  (
669  arraySelection,
670  objects,
671  " - pointSet"
672  );
673 
674  if (debug)
675  {
676  // just for debug info
677  getSelectedArrayEntries(arraySelection);
678 
679  Info<< "<end> Foam::vtkPVFoam::updateInfoSets" << endl;
680  }
681 }
682 
683 
684 void Foam::vtkPVFoam::updateInfoLagrangianFields()
685 {
686  if (debug)
687  {
688  Info<< "<beg> Foam::vtkPVFoam::updateInfoLagrangianFields"
689  << endl;
690  }
691 
692  vtkDataArraySelection* fieldSelection =
693  reader_->GetLagrangianFieldSelection();
694 
695  // preserve the enabled selections
696  stringList enabledEntries = getSelectedArrayEntries(fieldSelection);
697  fieldSelection->RemoveAllArrays();
698 
699  // use the db directly since this might be called without a mesh,
700  // but the region must get added back in
701  fileName lagrangianPrefix(cloud::prefix);
702  if (meshRegion_ != polyMesh::defaultRegion)
703  {
704  lagrangianPrefix = meshRegion_/cloud::prefix;
705  }
706 
707  // Add the available fields from all clouds and all time directories.
708  // Differing sets of fields from multiple clouds get combined into a single
709  // set. ParaView will display "(partial)" after field names that only apply
710  // to some of the clouds.
711  const arrayRange& range = arrayRangeLagrangian_;
712 
713  fileHandler().flush();
714  for (label partId = range.start(); partId < range.end(); ++ partId)
715  {
716  const instantList times = dbPtr_().times();
717  forAll(times, timei)
718  {
719  IOobjectList objects
720  (
721  dbPtr_(),
722  times[timei].name(),
723  lagrangianPrefix/getPartName(partId)
724  );
725 
726  addToSelection<IOField<label>>(fieldSelection, objects);
727  addToSelection<IOField<scalar>>(fieldSelection, objects);
728  addToSelection<IOField<vector>>(fieldSelection, objects);
729  addToSelection<IOField<sphericalTensor>>(fieldSelection, objects);
730  addToSelection<IOField<symmTensor>>(fieldSelection, objects);
731  addToSelection<IOField<tensor>>(fieldSelection, objects);
732  }
733  }
734 
735  // restore the enabled selections
736  setSelectedArrayEntries(fieldSelection, enabledEntries);
737 
738  if (debug)
739  {
740  Info<< "<end> Foam::vtkPVFoam::updateInfoLagrangianFields" << endl;
741  }
742 }
743 
744 
745 // ************************************************************************* //
label nPatches
Definition: readKivaGrid.H:402
List< instant > instantList
List of instants.
Definition: instantList.H:42
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:309
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
bool findStrings(const wordReListMatcher &matcher, const std::string &str)
Return true if string matches one of the regular expressions.
Definition: stringListOps.H:52
stressControl lookup("compactNormalStress") >> compactNormalStress
friend class const_iterator
Declare friendship with the const_iterator.
Definition: HashTable.H:197
static const word null
An empty word.
Definition: word.H:77
List< label > labelList
A List of labels.
Definition: labelList.H:56
const fileOperation & fileHandler()
Get current file handler.
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
label readLabel(Istream &is)
Definition: label.H:64
static const char nl
Definition: Ostream.H:265
static const word prefix
The prefix to local: lagrangian.
Definition: cloud.H:71
const bool writeData(readBool(pdfDictionary.lookup("writeData")))
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
List< word > wordList
A List of words.
Definition: fileName.H:54
List< string > stringList
A List of strings.
Definition: stringList.H:50
label patchi
fileNameList readDir(const fileName &, const fileName::Type=fileName::FILE, const bool filtergz=true, const bool followLink=true)
Read a directory and return the entries as a string list.
Definition: POSIX.C:635
messageStream Info
List< wordRe > wordReList
A List of wordRe (word or regular expression)
Definition: wordReList.H:50
friend class iterator
Declare friendship with the iterator.
Definition: HashTable.H:194
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition: error.H:366
ZoneMesh< cellZone, polyMesh > cellZoneMesh
A ZoneMesh with the type cellZone.
Namespace for OpenFOAM.