ENH: paraview reader module with internal caching of the vtk geometries

- The reader module allows two levels of caching.
  The OpenFOAM fvMesh can be cached in memory, for faster loading of
  fields. Additionally, the translated VTK geometries are held in a
  local cache. The cached VTK geometries should incur no additional
  overhead since they use the VTK reference counting for their storage
  management.
This commit is contained in:
Mark Olesen
2017-05-24 17:12:49 +02:00
parent 96d98cd2de
commit a42c35f64b
23 changed files with 1391 additions and 902 deletions

View File

@ -27,6 +27,8 @@
</Documentation> </Documentation>
</DoubleVectorProperty> </DoubleVectorProperty>
<!-- General Controls -->
<!-- Refresh (push button) --> <!-- Refresh (push button) -->
<Property <Property
name="Refresh" name="Refresh"
@ -35,12 +37,10 @@
<Documentation>Rescan for updated times/fields.</Documentation> <Documentation>Rescan for updated times/fields.</Documentation>
</Property> </Property>
<!-- General Controls -->
<!-- Skip Zero Time (check-box) --> <!-- Skip Zero Time (check-box) -->
<IntVectorProperty animateable="0" <IntVectorProperty animateable="0"
name="ZeroTime" name="ZeroTime"
label="Skip Zero Time" label="Skip 0/ time"
command="SetSkipZeroTime" command="SetSkipZeroTime"
default_values="1" default_values="1"
number_of_elements="1" number_of_elements="1"
@ -54,26 +54,28 @@
<!-- Include Sets (check-box) --> <!-- Include Sets (check-box) -->
<IntVectorProperty animateable="0" <IntVectorProperty animateable="0"
name="IncludeSets" name="IncludeSets"
label="With Sets"
command="SetIncludeSets" command="SetIncludeSets"
default_values="0" default_values="0"
number_of_elements="1" number_of_elements="1"
panel_visibility="default"> panel_visibility="default">
<BooleanDomain name="bool"/> <BooleanDomain name="bool"/>
<Documentation> <Documentation>
Search the polyMesh/sets/ directory Search the polyMesh/sets/ directory for {cell,face,point} sets
</Documentation> </Documentation>
</IntVectorProperty> </IntVectorProperty>
<!-- Include Zones (check-box) --> <!-- Include Zones (check-box) -->
<IntVectorProperty animateable="0" <IntVectorProperty animateable="0"
name="IncludeZones" name="IncludeZones"
label="With Zones"
command="SetIncludeZones" command="SetIncludeZones"
default_values="0" default_values="0"
number_of_elements="1" number_of_elements="1"
panel_visibility="default"> panel_visibility="default">
<BooleanDomain name="bool"/> <BooleanDomain name="bool"/>
<Documentation> <Documentation>
ZoneMesh information is used to find {cell,face,point}Zones. ZoneMesh information is used to find {cell,face,point} zones.
The polyMesh/ directory is only checked on startup. The polyMesh/ directory is only checked on startup.
</Documentation> </Documentation>
</IntVectorProperty> </IntVectorProperty>
@ -88,7 +90,7 @@
panel_visibility="default"> panel_visibility="default">
<BooleanDomain name="bool"/> <BooleanDomain name="bool"/>
<Documentation> <Documentation>
Show patchGroups only. Display patchGroups only instead of individual patches.
</Documentation> </Documentation>
</IntVectorProperty> </IntVectorProperty>
@ -109,6 +111,7 @@
<!-- Interpolate Fields (check-box) --> <!-- Interpolate Fields (check-box) -->
<IntVectorProperty animateable="0" <IntVectorProperty animateable="0"
name="InterpolateFields" name="InterpolateFields"
label="cell-to-point"
command="SetInterpolateVolFields" command="SetInterpolateVolFields"
default_values="1" default_values="1"
number_of_elements="1" number_of_elements="1"
@ -122,6 +125,7 @@
<!-- Extrapolate Patches (check-box) --> <!-- Extrapolate Patches (check-box) -->
<IntVectorProperty animateable="0" <IntVectorProperty animateable="0"
name="ExtrapolatePatches" name="ExtrapolatePatches"
label="field-to-patch"
command="SetExtrapolatePatches" command="SetExtrapolatePatches"
default_values="0" default_values="0"
number_of_elements="1" number_of_elements="1"
@ -132,7 +136,7 @@
</Documentation> </Documentation>
</IntVectorProperty> </IntVectorProperty>
<!-- Force GUI update (check-box) --> <!-- Force GUI update (push button) -->
<IntVectorProperty animateable="0" <IntVectorProperty animateable="0"
name="UpdateGUI" name="UpdateGUI"
command="SetUpdateGUI" command="SetUpdateGUI"
@ -159,16 +163,22 @@
</Documentation> </Documentation>
</IntVectorProperty> </IntVectorProperty>
<!-- Cache Mesh (check-box) --> <!-- Mesh Caching (combo-box) -->
<IntVectorProperty animateable="0" <IntVectorProperty animateable="0"
name="CacheMesh" name="MeshCaching"
command="SetCacheMesh" command="SetMeshCaching"
default_values="1" default_values="3"
number_of_elements="1" number_of_elements="1"
panel_visibility="default"> panel_visibility="default">
<BooleanDomain name="bool"/> <EnumerationDomain name="enum">
<Entry text="No caching" value="0" />
<Entry text="Cache fvMesh" value="1" />
<Entry text="Cache vtk,fvMesh" value="3" />
</EnumerationDomain>
<Documentation> <Documentation>
Cache the fvMesh in memory. Mesh caching styles.
Caching the OpenFOAM fvMesh reduces disk access.
Caching the VTK mesh reduces transcription overhead.
</Documentation> </Documentation>
</IntVectorProperty> </IntVectorProperty>
@ -185,7 +195,7 @@
<Property name="ShowPatchNames"/> <Property name="ShowPatchNames"/>
<Property name="UpdateGUI"/> <Property name="UpdateGUI"/>
<Property name="UseVTKPolyhedron"/> <Property name="UseVTKPolyhedron"/>
<Property name="CacheMesh"/> <Property name="MeshCaching"/>
</PropertyGroup> </PropertyGroup>
<!-- Parts Selections --> <!-- Parts Selections -->

View File

@ -26,6 +26,7 @@ License
#include "pqFoamReaderControls.h" #include "pqFoamReaderControls.h"
#include <QCheckBox> #include <QCheckBox>
#include <QComboBox>
#include <QFrame> #include <QFrame>
#include <QGridLayout> #include <QGridLayout>
#include <QPushButton> #include <QPushButton>
@ -42,6 +43,17 @@ License
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
// file-scope
// Add horizontal divider to layout
static void addHline(QGridLayout* layout, int row, int nCols)
{
QFrame* hline = new QFrame(layout->parentWidget());
hline->setFrameStyle(QFrame::HLine | QFrame::Sunken);
layout->addWidget(hline, row, 0, 1, nCols);
}
// file-scope // file-scope
// Widget properties // Widget properties
static QWidget* setWidgetProperties static QWidget* setWidgetProperties
@ -94,6 +106,66 @@ static QAbstractButton* setButtonProperties
} }
// file-scope
// Fill combo-box from XML enumeration
static QComboBox* setComboBoxContent
(
QComboBox* b,
vtkSMIntVectorProperty* prop
)
{
vtkSMEnumerationDomain* propEnum =
vtkSMEnumerationDomain::SafeDownCast
(
prop->FindDomain("vtkSMEnumerationDomain")
);
if (propEnum)
{
unsigned int n = propEnum->GetNumberOfEntries();
for (unsigned int idx=0; idx < n; ++idx)
{
const int val = propEnum->GetEntryValue(idx);
const char* txt = propEnum->GetEntryText(idx);
b->insertItem(val, txt);
}
// Set default
const int val = prop->GetElement(0);
unsigned int idx = 0;
if (!propEnum->IsInDomain(val, idx))
{
idx = 0;
}
b->setCurrentIndex(idx);
}
return b;
}
// file-scope
// Translate a combo-box index to a lookup value
static int comboBoxValue(vtkSMIntVectorProperty* prop, int idx)
{
vtkSMEnumerationDomain* propEnum =
vtkSMEnumerationDomain::SafeDownCast
(
prop->FindDomain("vtkSMEnumerationDomain")
);
if (propEnum)
{
return propEnum->GetEntryValue(idx);
}
else
{
return idx;
}
}
static vtkSMIntVectorProperty* lookupIntProp static vtkSMIntVectorProperty* lookupIntProp
( (
vtkSMPropertyGroup* group, vtkSMPropertyGroup* group,
@ -154,9 +226,9 @@ void pqFoamReaderControls::refreshPressed()
} }
void pqFoamReaderControls::cacheMesh(int val) void pqFoamReaderControls::cacheMesh(int idx)
{ {
fireCommand(cacheMesh_, val); fireCommand(meshCaching_, comboBoxValue(meshCaching_, idx));
} }
@ -210,12 +282,14 @@ pqFoamReaderControls::pqFoamReaderControls
showGroupsOnly_(lookupIntProp(group, "ShowGroupsOnly")), showGroupsOnly_(lookupIntProp(group, "ShowGroupsOnly")),
includeSets_(lookupIntProp(group, "IncludeSets")), includeSets_(lookupIntProp(group, "IncludeSets")),
includeZones_(lookupIntProp(group, "IncludeZones")), includeZones_(lookupIntProp(group, "IncludeZones")),
cacheMesh_(lookupIntProp(group, "CacheMesh")) meshCaching_(lookupIntProp(group, "MeshCaching"))
{ {
typedef vtkSMIntVectorProperty intProp; typedef vtkSMIntVectorProperty intProp;
QGridLayout* form = new QGridLayout(this); QGridLayout* form = new QGridLayout(this);
const int nCols = 3;
// ROW // ROW
// ~~~ // ~~~
int row = 0; int row = 0;
@ -243,13 +317,7 @@ pqFoamReaderControls::pqFoamReaderControls
} }
// LINE // LINE
// ~~~~ addHline(form, ++row, nCols);
++row;
{
QFrame* hline = new QFrame(this);
hline->setFrameStyle(QFrame::HLine | QFrame::Sunken);
form->addWidget(hline, row, 0, 1, 4);
}
// ROW // ROW
// ~~~ // ~~~
@ -321,13 +389,7 @@ pqFoamReaderControls::pqFoamReaderControls
} }
// LINE // LINE
// ~~~~ addHline(form, ++row, nCols);
++row;
{
QFrame* hline = new QFrame(this);
hline->setFrameStyle(QFrame::HLine | QFrame::Sunken);
form->addWidget(hline, row, 0, 1, 4);
}
// ROW // ROW
// ~~~ // ~~~
@ -360,13 +422,7 @@ pqFoamReaderControls::pqFoamReaderControls
} }
// LINE // LINE
// ~~~~ addHline(form, ++row, nCols);
++row;
{
QFrame* hline = new QFrame(this);
hline->setFrameStyle(QFrame::HLine | QFrame::Sunken);
form->addWidget(hline, row, 0, 1, 4);
}
// ROW // ROW
// ~~~ // ~~~
@ -398,14 +454,22 @@ pqFoamReaderControls::pqFoamReaderControls
); );
} }
if (cacheMesh_) if (meshCaching_)
{ {
QCheckBox* b = new QCheckBox(this); QComboBox* b = new QComboBox(this);
setButtonProperties(b, cacheMesh_);
form->addWidget(b, row, 2, Qt::AlignLeft); form->addWidget(b, row, 2, Qt::AlignLeft);
setWidgetProperties(b, meshCaching_);
setComboBoxContent(b, meshCaching_);
addPropertyLink
(
b, "indexChanged", SIGNAL(currentIndexChanged(int)), meshCaching_
);
connect connect
( (
b, SIGNAL(toggled(bool)), this, SLOT(cacheMesh(bool)) b, SIGNAL(currentIndexChanged(int)), this, SLOT(cacheMesh(int))
); );
} }
} }

View File

@ -69,8 +69,8 @@ class pqFoamReaderControls
//- IncludeZones (bool property) //- IncludeZones (bool property)
vtkSMIntVectorProperty* includeZones_; vtkSMIntVectorProperty* includeZones_;
//- CacheMesh (bool property) //- MeshCaching (enum property)
vtkSMIntVectorProperty* cacheMesh_; vtkSMIntVectorProperty* meshCaching_;
// Private Member Functions // Private Member Functions
@ -102,7 +102,7 @@ protected slots:
// Protected Member Functions // Protected Member Functions
void refreshPressed(); void refreshPressed();
void cacheMesh(bool checked); void cacheMesh(int idx);
void showPatchNames(bool checked); void showPatchNames(bool checked);
void showGroupsOnly(bool checked); void showGroupsOnly(bool checked);
void includeSets(bool checked); void includeSets(bool checked);

View File

@ -69,8 +69,7 @@ vtkPVFoamReader::vtkPVFoamReader()
// Add second output for the Lagrangian // Add second output for the Lagrangian
this->SetNumberOfOutputPorts(2); this->SetNumberOfOutputPorts(2);
vtkSmartPointer<vtkMultiBlockDataSet> lagrangian = auto lagrangian = vtkSmartPointer<vtkMultiBlockDataSet>::New();
vtkSmartPointer<vtkMultiBlockDataSet>::New();
lagrangian->ReleaseData(); lagrangian->ReleaseData();
@ -80,7 +79,7 @@ vtkPVFoamReader::vtkPVFoamReader()
TimeStepRange[0] = 0; TimeStepRange[0] = 0;
TimeStepRange[1] = 0; TimeStepRange[1] = 0;
CacheMesh = true; MeshCaching = 3; // fvMesh+vtk
SkipZeroTime = true; SkipZeroTime = true;
ExtrapolatePatches = false; ExtrapolatePatches = false;

View File

@ -83,9 +83,9 @@ public:
virtual void PrintInfo(); virtual void PrintInfo();
// Description: // Description:
// OpenFOAM mesh caching control // Mesh caching control (0:none,1:fvMesh,3:fvMesh+vtk)
vtkSetMacro(CacheMesh, bool); vtkSetMacro(MeshCaching, int);
vtkGetMacro(CacheMesh, bool); vtkGetMacro(MeshCaching, int);
// Description: // Description:
// OpenFOAM refresh times/fields // OpenFOAM refresh times/fields
@ -232,7 +232,7 @@ private:
void updatePatchNamesView(const bool show); void updatePatchNamesView(const bool show);
int TimeStepRange[2]; int TimeStepRange[2];
bool CacheMesh; int MeshCaching;
bool SkipZeroTime; bool SkipZeroTime;
bool ExtrapolatePatches; bool ExtrapolatePatches;

View File

@ -136,12 +136,12 @@ bool Foam::vtkPVFoam::addOutputBlock
if (selectedPartIds_.found(partId)) if (selectedPartIds_.found(partId))
{ {
const auto& longName = selectedPartIds_[partId]; const auto& longName = selectedPartIds_[partId];
const word shortName = getPartName(partId); const word shortName = getFoamName(longName);
auto iter = cache.find(longName); auto iter = cache.find(longName);
if (iter.found() && (*iter).vtkmesh) if (iter.found() && iter.object().dataset)
{ {
auto dataset = (*iter).vtkmesh; auto dataset = iter.object().dataset;
if (singleDataset) if (singleDataset)
{ {
@ -224,7 +224,6 @@ int Foam::vtkPVFoam::setTime(int nRequest, const double requestTimes[])
runTime.setTime(Times[nearestIndex], nearestIndex); runTime.setTime(Times[nearestIndex], nearestIndex);
// When the changes, so do the fields // When the changes, so do the fields
fieldsChanged_ = true;
meshState_ = meshPtr_ ? meshPtr_->readUpdate() : polyMesh::TOPO_CHANGE; meshState_ = meshPtr_ ? meshPtr_->readUpdate() : polyMesh::TOPO_CHANGE;
reader_->UpdateProgress(0.05); reader_->UpdateProgress(0.05);
@ -238,27 +237,13 @@ int Foam::vtkPVFoam::setTime(int nRequest, const double requestTimes[])
Info<< "<end> setTime() - selectedTime=" Info<< "<end> setTime() - selectedTime="
<< Times[nearestIndex].name() << " index=" << timeIndex_ << Times[nearestIndex].name() << " index=" << timeIndex_
<< "/" << Times.size() << "/" << Times.size()
<< " meshUpdateState=" << updateStateName(meshState_) << " meshUpdateState=" << updateStateName(meshState_) << endl;
<< " fieldsChanged=" << Switch(fieldsChanged_) << endl;
} }
return nearestIndex; return nearestIndex;
} }
Foam::word Foam::vtkPVFoam::getPartName(const int partId) const
{
if (selectedPartIds_.found(partId))
{
return getFoamName(selectedPartIds_[partId]);
}
else
{
return word::null;
}
}
Foam::word Foam::vtkPVFoam::getReaderPartName(const int partId) const Foam::word Foam::vtkPVFoam::getReaderPartName(const int partId) const
{ {
return getFoamName(reader_->GetPartArrayName(partId)); return getFoamName(reader_->GetPartArrayName(partId));
@ -279,8 +264,8 @@ Foam::vtkPVFoam::vtkPVFoam
meshRegion_(polyMesh::defaultRegion), meshRegion_(polyMesh::defaultRegion),
meshDir_(polyMesh::meshSubDir), meshDir_(polyMesh::meshSubDir),
timeIndex_(-1), timeIndex_(-1),
decomposePoly_(false),
meshState_(polyMesh::TOPO_CHANGE), meshState_(polyMesh::TOPO_CHANGE),
fieldsChanged_(true),
rangeVolume_("unzoned"), rangeVolume_("unzoned"),
rangePatches_("patch"), rangePatches_("patch"),
rangeLagrangian_("lagrangian"), rangeLagrangian_("lagrangian"),
@ -414,16 +399,16 @@ void Foam::vtkPVFoam::updateInfo()
// time of the vtkDataArraySelection, but the qt/paraview proxy // time of the vtkDataArraySelection, but the qt/paraview proxy
// layer doesn't care about that anyhow. // layer doesn't care about that anyhow.
HashSet<string> enabledEntries; HashSet<string> enabled;
if (!partSelection->GetNumberOfArrays() && !meshPtr_) if (!partSelection->GetNumberOfArrays() && !meshPtr_)
{ {
// enable 'internalMesh' on the first call // Fake enable 'internalMesh' on the first call
enabledEntries = { "internalMesh" }; enabled = { "internalMesh" };
} }
else else
{ {
// preserve the enabled selections // preserve the enabled selections
enabledEntries = getSelectedArrayEntries(partSelection); enabled = getSelectedArraySet(partSelection);
} }
// Clear current mesh parts list // Clear current mesh parts list
@ -431,18 +416,13 @@ void Foam::vtkPVFoam::updateInfo()
// Update mesh parts list - add Lagrangian at the bottom // Update mesh parts list - add Lagrangian at the bottom
updateInfoInternalMesh(partSelection); updateInfoInternalMesh(partSelection);
updateInfoPatches(partSelection, enabledEntries); updateInfoPatches(partSelection, enabled);
updateInfoSets(partSelection); updateInfoSets(partSelection);
updateInfoZones(partSelection); updateInfoZones(partSelection);
updateInfoLagrangian(partSelection); updateInfoLagrangian(partSelection);
// Adjust/restore the enabled selections // Adjust/restore the enabled selections
setSelectedArrayEntries(partSelection, enabledEntries); setSelectedArrayEntries(partSelection, enabled);
if (meshState_ != polyMesh::UNCHANGED)
{
fieldsChanged_ = true;
}
// Update volume, point and lagrangian fields // Update volume, point and lagrangian fields
updateInfoFields<fvPatchField, volMesh> updateInfoFields<fvPatchField, volMesh>
@ -480,42 +460,28 @@ void Foam::vtkPVFoam::Update
} }
reader_->UpdateProgress(0.1); reader_->UpdateProgress(0.1);
const int caching = reader_->GetMeshCaching();
const bool oldDecomp = decomposePoly_;
decomposePoly_ = !reader_->GetUseVTKPolyhedron();
// Set up mesh parts selection(s) // Set up mesh parts selection(s)
// Update cached, saved, unneed values.
{ {
vtkDataArraySelection* selection = reader_->GetPartSelection(); vtkDataArraySelection* selection = reader_->GetPartSelection();
const int n = selection->GetNumberOfArrays(); const int n = selection->GetNumberOfArrays();
// All previously selected (enabled) names
HashSet<string> original;
forAllConstIters(selectedPartIds_, iter)
{
original.insert(iter.object());
}
selectedPartIds_.clear(); selectedPartIds_.clear();
HashSet<string> nowActive;
for (int id=0; id < n; ++id) for (int id=0; id < n; ++id)
{ {
string str(selection->GetArrayName(id)); const string str(selection->GetArrayName(id));
bool status = selection->GetArraySetting(id); const bool status = selection->GetArraySetting(id);
if (status) if (status)
{ {
selectedPartIds_.set(id, str); // id -> name selectedPartIds_.set(id, str); // id -> name
nowActive.set(str);
if (!original.erase(str))
{
// New part, or newly enabled
//? meshChanged_ = true;
}
}
else
{
if (original.erase(str))
{
// Part disappeared, or newly disabled
//? meshChanged_ = true;
}
} }
if (debug > 1) if (debug > 1)
@ -524,6 +490,39 @@ void Foam::vtkPVFoam::Update
<< " : " << str << nl; << " : " << str << nl;
} }
} }
// Dispose of unneeded components
cachedVtp_.retain(nowActive);
cachedVtu_.retain(nowActive);
if
(
!caching
|| meshState_ == polyMesh::TOPO_CHANGE
|| meshState_ == polyMesh::TOPO_PATCH_CHANGE
)
{
// Eliminate cached values that would be unreliable
forAllIters(cachedVtp_, iter)
{
iter.object().clearGeom();
iter.object().clear();
}
forAllIters(cachedVtu_, iter)
{
iter.object().clearGeom();
iter.object().clear();
}
}
else if (oldDecomp != decomposePoly_)
{
// poly-decompose changed - dispose of cached values
forAllIters(cachedVtu_, iter)
{
iter.object().clearGeom();
iter.object().clear();
}
}
} }
reader_->UpdateProgress(0.15); reader_->UpdateProgress(0.15);
@ -536,7 +535,7 @@ void Foam::vtkPVFoam::Update
printMemory(); printMemory();
} }
if (!reader_->GetCacheMesh()) if (!caching)
{ {
delete meshPtr_; delete meshPtr_;
meshPtr_ = nullptr; meshPtr_ = nullptr;
@ -549,7 +548,6 @@ void Foam::vtkPVFoam::Update
{ {
Info<< "Creating OpenFOAM mesh for region " << meshRegion_ Info<< "Creating OpenFOAM mesh for region " << meshRegion_
<< " at time=" << dbPtr_().timeName() << endl; << " at time=" << dbPtr_().timeName() << endl;
} }
meshPtr_ = new fvMesh meshPtr_ = new fvMesh
@ -582,17 +580,6 @@ void Foam::vtkPVFoam::Update
reader_->UpdateProgress(0.4); reader_->UpdateProgress(0.4);
// Update cached, saved, unneed values:
HashSet<string> nowActive;
forAllConstIters(selectedPartIds_, iter)
{
nowActive.insert(iter.object());
}
// Dispose of unneeded components
cachedVtp_.retain(nowActive);
cachedVtu_.retain(nowActive);
convertMeshVolume(); convertMeshVolume();
convertMeshPatches(); convertMeshPatches();
reader_->UpdateProgress(0.6); reader_->UpdateProgress(0.6);
@ -645,18 +632,28 @@ void Foam::vtkPVFoam::Update
} }
reader_->UpdateProgress(0.95); reader_->UpdateProgress(0.95);
fieldsChanged_ = false;
meshState_ = polyMesh::UNCHANGED; meshState_ = polyMesh::UNCHANGED;
// Standard memory cleanup if (caching & 2)
cachedVtp_.clear(); {
cachedVtu_.clear(); // Suppress caching of Lagrangian since it normally always changes.
cachedVtp_.filterKeys
(
[](const word& k){ return k.startsWith("lagrangian/"); },
true // prune
);
}
else
{
cachedVtp_.clear();
cachedVtu_.clear();
}
} }
void Foam::vtkPVFoam::UpdateFinalize() void Foam::vtkPVFoam::UpdateFinalize()
{ {
if (!reader_->GetCacheMesh()) if (!reader_->GetMeshCaching())
{ {
delete meshPtr_; delete meshPtr_;
meshPtr_ = nullptr; meshPtr_ = nullptr;

View File

@ -25,7 +25,25 @@ Class
Foam::vtkPVFoam Foam::vtkPVFoam
Description Description
Provides a reader interface for OpenFOAM to VTK interaction. The backend for the vtkPVFoamReader reader module -
providing a paraview reader interface for OpenFOAM meshes and fields.
Similar, and sometimes better, functionality may be provided by the
native VTK OpenFOAM reader. OpenCFD has recently (2017) been working
on improving the native VTK OpenFOAM reader for the benefit of everyone.
In some areas the reader module lacks compared to the native reader
(notably the ability to work on decomosed datasets), but provides
additional handling of sets,zones,groups. Some features have also since
been adapted to the native reader. Additionally, the reader module
provides a useful platform for testing new ideas.
Note
The reader module allows two levels of caching. The OpenFOAM fvMesh
can be cached in memory, for faster loading of fields. Additionally,
the translated VTK geometries are held in a local cache. The cached
VTK geometries should incur no additional overhead since they use
the VTK reference counting for their storage management.
SourceFiles SourceFiles
vtkPVFoam.C vtkPVFoam.C
@ -56,22 +74,22 @@ SourceFiles
#include "foamPvCore.H" #include "foamPvCore.H"
#include "foamVtkMeshMaps.H" #include "foamVtkMeshMaps.H"
#include "vtkSmartPointer.h" #include "vtkPoints.h"
#include "vtkPolyData.h" #include "vtkPolyData.h"
#include "vtkSmartPointer.h"
#include "vtkUnstructuredGrid.h" #include "vtkUnstructuredGrid.h"
// * * * * * * * * * * * * * Forward Declarations * * * * * * * * * * * * * // // * * * * * * * * * * * * * Forward Declarations * * * * * * * * * * * * * //
class vtkCellArray;
class vtkDataArraySelection; class vtkDataArraySelection;
class vtkDataSet; class vtkDataSet;
class vtkFloatArray; class vtkFloatArray;
class vtkPoints; class vtkIndent;
class vtkMultiBlockDataSet;
class vtkPVFoamReader; class vtkPVFoamReader;
class vtkRenderer; class vtkRenderer;
class vtkTextActor; class vtkTextActor;
class vtkMultiBlockDataSet;
class vtkIndent;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -104,20 +122,99 @@ class vtkPVFoam
// Private classes // Private classes
//- Bookkeeping for vtkPolyData //- Bookkeeping for internal caching.
class foamVtpData // Retain an original copy of the geometry as well as a shallow copy
// with the output fields.
// The original copy is reused for different timestep
template<class DataType>
class foamVtkCaching
{ {
public: public:
vtkSmartPointer<vtkPolyData> vtkmesh; typedef DataType dataType;
//- The geometry, without any cell/point data
vtkSmartPointer<dataType> vtkgeom;
//- The shallow-copy of geometry, plus additional data
vtkSmartPointer<dataType> dataset;
//- Number of points associated with geometry
inline uint64_t nPoints() const
{
return vtkgeom ? vtkgeom->GetNumberOfPoints() : 0;
}
//- Clear geometry and dataset
void clearGeom()
{
vtkgeom = nullptr;
dataset = nullptr;
}
//- Return a shallow copy of vtkgeom for manipulation
vtkSmartPointer<dataType> getCopy() const
{
auto copy = vtkSmartPointer<dataType>::New();
copy->ShallowCopy(vtkgeom);
return copy;
}
//- Make a shallow copy of vtkgeom into dataset
void reuse()
{
dataset = vtkSmartPointer<dataType>::New();
dataset->ShallowCopy(vtkgeom);
}
//- Set the geometry and make a shallow copy to dataset
void set(vtkSmartPointer<dataType> geom)
{
vtkgeom = geom;
reuse();
}
//- Report basic information to output
void PrintSelf(std::ostream& os) const
{
os << "geom" << nl;
if (vtkgeom)
{
vtkgeom->PrintSelf(std::cout, vtkIndent(2));
}
else
{
os << "nullptr";
}
os << nl;
os << "copy" << nl;
if (dataset)
{
dataset->PrintSelf(std::cout, vtkIndent(2));
}
else
{
os << "nullptr";
}
os << nl;
}
}; };
//- Bookkeeping for vtkPolyData
class foamVtpData
:
public foamVtkCaching<vtkPolyData>,
public foamVtkMeshMaps
{};
//- Bookkeeping for vtkUnstructuredGrid //- Bookkeeping for vtkUnstructuredGrid
class foamVtuData : public foamVtkMeshMaps class foamVtuData
{ :
public: public foamVtkCaching<vtkUnstructuredGrid>,
vtkSmartPointer<vtkUnstructuredGrid> vtkmesh; public foamVtkMeshMaps
}; {};
// Private Data // Private Data
@ -140,12 +237,12 @@ class vtkPVFoam
//- The time index //- The time index
int timeIndex_; int timeIndex_;
//- Previous/current decomposition request
bool decomposePoly_;
//- Track changes in mesh geometry //- Track changes in mesh geometry
enum polyMesh::readUpdateState meshState_; enum polyMesh::readUpdateState meshState_;
//- Track changes in fields
bool fieldsChanged_;
//- The index of selected parts mapped to their names //- The index of selected parts mapped to their names
Map<string> selectedPartIds_; Map<string> selectedPartIds_;
@ -232,75 +329,143 @@ class vtkPVFoam
// Mesh conversion functions // Mesh conversion functions
//- Convert volume mesh //- Convert InternalMesh
void convertMeshVolume(); void convertMeshVolume();
//- Convert Lagrangian points //- Convert Lagrangian points
void convertMeshLagrangian(); void convertMeshLagrangian();
//- Convert mesh patches //- Convert mesh patches.
// The additionalIds (cached data) contain the patch Ids.
// There will be several for groups, but only one for regular patches.
void convertMeshPatches(); void convertMeshPatches();
//- Convert subsetted mesh
void convertMeshSubset
(
const fvMeshSubset& subsetter,
const string& longName
);
//- Convert cell zones //- Convert cell zones
void convertMeshCellZones(); void convertMeshCellZones();
//- Convert face zones
void convertMeshFaceZones();
//- Convert point zones
void convertMeshPointZones();
//- Convert cell sets //- Convert cell sets
void convertMeshCellSets(); void convertMeshCellSets();
//- Convert face zones
void convertMeshFaceZones();
//- Convert face sets //- Convert face sets
// The cellMap (cached data) contains the face-labels.
void convertMeshFaceSets(); void convertMeshFaceSets();
//- Convert point zones
// The pointMap (cached data) contains the point-labels.
void convertMeshPointZones();
//- Convert point sets //- Convert point sets
// The pointMap (cached data) contains the point-labels.
void convertMeshPointSets(); void convertMeshPointSets();
// Add mesh functions // Add mesh functions
//- Volume meshes as vtkUnstructuredGrid //- Generate vtk points for the current mesh points/decomposition
static vtkSmartPointer<vtkPoints> movePoints
(
const fvMesh& mesh,
const foamVtuData& vtuData
);
//- Generate vtk points for the current mesh points/decomposition,
// using the provided pointMap
static vtkSmartPointer<vtkPoints> movePoints
(
const fvMesh& mesh,
const foamVtuData& vtuData,
const labelUList& pointMap
);
//- Volume mesh as vtkUnstructuredGrid
static vtkSmartPointer<vtkUnstructuredGrid> volumeVTKMesh
(
const fvMesh& mesh,
foamVtuData& vtuData,
const bool decompPoly
);
//- Subsetted mesh as vtkUnstructuredGrid
static vtkSmartPointer<vtkUnstructuredGrid> volumeVTKSubsetMesh
(
const fvMeshSubset& subsetter,
foamVtuData& vtuData,
const bool decompPoly
);
//- Volume mesh as vtkUnstructuredGrid
vtkSmartPointer<vtkUnstructuredGrid> volumeVTKMesh vtkSmartPointer<vtkUnstructuredGrid> volumeVTKMesh
( (
const fvMesh& mesh, const fvMesh& mesh,
foamVtuData& vtuData foamVtuData& vtuData
); ) const;
//- Subsetted mesh as vtkUnstructuredGrid
vtkSmartPointer<vtkUnstructuredGrid> volumeVTKSubsetMesh
(
const fvMeshSubset& subsetter,
foamVtuData& vtuData
) const;
//- Lagrangian positions as vtkPolyData //- Lagrangian positions as vtkPolyData
vtkSmartPointer<vtkPolyData> lagrangianVTKMesh vtkSmartPointer<vtkPolyData> lagrangianVTKMesh
( (
const polyMesh& mesh, const polyMesh& mesh,
const word& cloudName const word& cloudName
) const;
//- Patch points
template<class PatchType>
static vtkSmartPointer<vtkPoints> movePatchPoints
(
const PatchType& p
);
//- Patch faces as vtk-cells
template<class PatchType>
static vtkSmartPointer<vtkCellArray> patchFacesVTKCells
(
const PatchType& p
); );
//- Patches (mesh or primitive) as vtkPolyData //- Patches (mesh or primitive) as vtkPolyData
template<class PatchType> template<class PatchType>
vtkSmartPointer<vtkPolyData> patchVTKMesh static vtkSmartPointer<vtkPolyData> patchVTKMesh
( (
const string& name,
const PatchType& p const PatchType& p
); );
// Field conversion functions // Field conversion functions
//- Convert Field to VTK field //- Copy list to pre-allocated vtk array.
// \return number of input items copied
template<class Type>
static label transcribeFloatData
(
vtkFloatArray* array,
const UList<Type>& input,
const label start = 0
);
//- Create named field initialized to zero
template<class Type>
static vtkSmartPointer<vtkFloatArray> zeroVTKField
(
const word& name,
const label size
);
//- Convert float data to VTK field
template<class Type> template<class Type>
vtkSmartPointer<vtkFloatArray> convertFieldToVTK vtkSmartPointer<vtkFloatArray> convertFieldToVTK
( (
const word& name, const word& name,
const Field<Type>& fld const UList<Type>& fld
); ) const;
//- Face set/zone field //- Face set/zone field
template<class Type> template<class Type>
@ -308,7 +473,7 @@ class vtkPVFoam
( (
const GeometricField<Type, fvPatchField, volMesh>& fld, const GeometricField<Type, fvPatchField, volMesh>& fld,
const labelUList& faceLabels const labelUList& faceLabels
); ) const;
//- Volume field //- Volume field
template<class Type> template<class Type>
@ -316,7 +481,7 @@ class vtkPVFoam
( (
const GeometricField<Type, fvPatchField, volMesh>& fld, const GeometricField<Type, fvPatchField, volMesh>& fld,
const foamVtuData& vtuData const foamVtuData& vtuData
); ) const;
//- Convert volume fields //- Convert volume fields
@ -392,9 +557,8 @@ class vtkPVFoam
//- Point field //- Point field
template<class Type> template<class Type>
void convertPointField vtkSmartPointer<vtkFloatArray> convertPointField
( (
vtkUnstructuredGrid* vtkmesh,
const GeometricField<Type, pointPatchField, pointMesh>& pfld, const GeometricField<Type, pointPatchField, pointMesh>& pfld,
const GeometricField<Type, fvPatchField, volMesh>& vfld, const GeometricField<Type, fvPatchField, volMesh>& vfld,
const foamVtuData& vtuData const foamVtuData& vtuData
@ -403,17 +567,6 @@ class vtkPVFoam
// GUI selection helper functions // GUI selection helper functions
//- Only retain specified fields
static void pruneObjectList
(
IOobjectList& objects,
const hashedWordList& retain
);
//- Get the first word from selectedPartIds_
word getPartName(const int partId) const;
//- Get the first word from the reader 'parts' selection //- Get the first word from the reader 'parts' selection
word getReaderPartName(const int partId) const; word getReaderPartName(const int partId) const;

View File

@ -30,6 +30,7 @@ InClass
#define vtkPVFoamFieldTemplates_C #define vtkPVFoamFieldTemplates_C
// OpenFOAM includes // OpenFOAM includes
#include "error.H"
#include "emptyFvPatchField.H" #include "emptyFvPatchField.H"
#include "wallPolyPatch.H" #include "wallPolyPatch.H"
#include "faceSet.H" #include "faceSet.H"
@ -81,92 +82,103 @@ void Foam::vtkPVFoam::convertVolField
convertVolFieldBlock(fld, ptfPtr, rangeCellZones_); // cellZones convertVolFieldBlock(fld, ptfPtr, rangeCellZones_); // cellZones
convertVolFieldBlock(fld, ptfPtr, rangeCellSets_); // cellSets convertVolFieldBlock(fld, ptfPtr, rangeCellSets_); // cellSets
// Patches - currently skip field conversion for groups
// Patches - skip field conversion for groups
for (auto partId : rangePatches_) for (auto partId : rangePatches_)
{ {
if if (!selectedPartIds_.found(partId))
{
continue;
}
const auto& longName = selectedPartIds_[partId];
auto iter = cachedVtp_.find(longName);
if (!iter.found() || !iter.object().dataset)
{
// Should not happen, but for safety require a vtk geometry
continue;
}
foamVtpData& vtpData = iter.object();
auto dataset = vtpData.dataset;
const labelList& patchIds = vtpData.additionalIds();
if (patchIds.empty())
{
continue;
}
// This is slightly roundabout, but we deal with groups and with
// single patches.
// For groups (spanning several patches) it is fairly messy to
// get interpolated point fields. We would need to create a indirect
// patch each time to obtain the mesh points. We thus skip that.
//
// To improve code reuse, we allocate the CellData as a zeroed-field
// ahead of time.
vtkSmartPointer<vtkFloatArray> cdata = zeroVTKField<Type>
( (
!selectedPartIds_.found(partId) fld.name(),
|| selectedPartIds_[partId].startsWith("group/") dataset->GetNumberOfPolys()
) );
vtkSmartPointer<vtkFloatArray> pdata;
const bool allowPdata = (interpField && patchIds.size() == 1);
label coffset = 0; // the write offset into cell-data
for (label patchId : patchIds)
{ {
continue; const fvPatchField<Type>& ptf = fld.boundaryField()[patchId];
}
const word patchName = getPartName(partId); if
const label patchId = patches.findPatchID(patchName);
if (patchId < 0)
{
continue;
}
auto iter = cachedVtp_.find(selectedPartIds_[partId]);
if (!iter.found() || !(*iter).vtkmesh)
{
continue;
}
auto vtkmesh = (*iter).vtkmesh;
const fvPatchField<Type>& ptf = fld.boundaryField()[patchId];
if
(
isType<emptyFvPatchField<Type>>(ptf)
||
( (
extrapPatch isType<emptyFvPatchField<Type>>(ptf)
&& !polyPatch::constraintType(patches[patchId].type()) ||
(
extrapPatch
&& !polyPatch::constraintType(patches[patchId].type())
)
) )
)
{
fvPatch p(ptf.patch().patch(), mesh.boundary());
tmp<Field<Type>> tpptf
(
fvPatchField<Type>(p, fld).patchInternalField()
);
vtkSmartPointer<vtkFloatArray> cdata =
convertFieldToVTK
(
fld.name(),
tpptf()
);
vtkmesh->GetCellData()->AddArray(cdata);
if (patchId < patchInterpList.size())
{ {
vtkSmartPointer<vtkFloatArray> pdata = convertFieldToVTK fvPatch p(ptf.patch().patch(), mesh.boundary());
tmp<Field<Type>> tpptf
( (
fld.name(), fvPatchField<Type>(p, fld).patchInternalField()
patchInterpList[patchId].faceToPointInterpolate(tpptf)()
); );
vtkmesh->GetPointData()->AddArray(pdata); coffset += transcribeFloatData(cdata, tpptf(), coffset);
if (allowPdata && patchId < patchInterpList.size())
{
pdata = convertFieldToVTK
(
fld.name(),
patchInterpList[patchId].faceToPointInterpolate(tpptf)()
);
}
}
else
{
coffset += transcribeFloatData(cdata, ptf, coffset);
if (allowPdata && patchId < patchInterpList.size())
{
pdata = convertFieldToVTK
(
fld.name(),
patchInterpList[patchId].faceToPointInterpolate(ptf)()
);
}
} }
} }
else
if (cdata)
{ {
vtkSmartPointer<vtkFloatArray> cdata = dataset->GetCellData()->AddArray(cdata);
convertFieldToVTK }
( if (pdata)
fld.name(), {
ptf dataset->GetPointData()->AddArray(pdata);
);
vtkmesh->GetCellData()->AddArray(cdata);
if (patchId < patchInterpList.size())
{
vtkSmartPointer<vtkFloatArray> pdata = convertFieldToVTK
(
fld.name(),
patchInterpList[patchId].faceToPointInterpolate(ptf)()
);
vtkmesh->GetPointData()->AddArray(pdata);
}
} }
} }
@ -178,15 +190,18 @@ void Foam::vtkPVFoam::convertVolField
{ {
continue; continue;
} }
const auto& longName = selectedPartIds_[partId];
const word zoneName = getFoamName(longName);
auto iter = cachedVtu_.find(selectedPartIds_[partId]); auto iter = cachedVtp_.find(longName);
if (!iter.found() || !(*iter).vtkmesh) if (!iter.found() || !iter.object().dataset)
{ {
// Should not happen, but for safety require a vtk geometry
continue; continue;
} }
auto vtkmesh = (*iter).vtkmesh; foamVtpData& vtpData = iter.object();
auto dataset = vtpData.dataset;
const word zoneName = getPartName(partId);
const faceZoneMesh& zMesh = mesh.faceZones(); const faceZoneMesh& zMesh = mesh.faceZones();
const label zoneId = zMesh.findZoneID(zoneName); const label zoneId = zMesh.findZoneID(zoneName);
@ -195,15 +210,16 @@ void Foam::vtkPVFoam::convertVolField
continue; continue;
} }
vtkSmartPointer<vtkFloatArray> cdata = convertFaceFieldToVTK vtkSmartPointer<vtkFloatArray> cdata =
( convertFaceFieldToVTK
fld, (
zMesh[zoneId] fld,
); zMesh[zoneId]
);
vtkmesh->GetCellData()->AddArray(cdata); dataset->GetCellData()->AddArray(cdata);
// TODO: points // TODO: point data
} }
@ -214,26 +230,27 @@ void Foam::vtkPVFoam::convertVolField
{ {
continue; continue;
} }
const auto& longName = selectedPartIds_[partId];
const word selectName = getFoamName(longName);
auto iter = cachedVtu_.find(selectedPartIds_[partId]); auto iter = cachedVtp_.find(longName);
if (!iter.found() || !(*iter).vtkmesh) if (!iter.found() || !iter.object().dataset)
{ {
// Should not happen, but for safety require a vtk geometry
continue; continue;
} }
auto vtkmesh = (*iter).vtkmesh; foamVtpData& vtpData = iter.object();
auto dataset = vtpData.dataset;
const word selectName = getPartName(partId);
const faceSet fSet(mesh, selectName);
vtkSmartPointer<vtkFloatArray> cdata = convertFaceFieldToVTK vtkSmartPointer<vtkFloatArray> cdata = convertFaceFieldToVTK
( (
fld, fld,
fSet.sortedToc() vtpData.cellMap()
); );
vtkmesh->GetCellData()->AddArray(cdata); dataset->GetCellData()->AddArray(cdata);
// TODO: points // TODO: point data
} }
} }
@ -246,27 +263,21 @@ void Foam::vtkPVFoam::convertVolFields
const IOobjectList& objects const IOobjectList& objects
) )
{ {
typedef GeometricField<Type, fvPatchField, volMesh> FieldType;
forAllConstIters(objects, iter) forAllConstIters(objects, iter)
{ {
// Restrict to GeometricField<Type, ...> // Restrict to GeometricField<Type, ...>
if const auto& ioobj = *(iter.object());
(
iter()->headerClassName() if (ioobj.headerClassName() == FieldType::typeName)
!= GeometricField<Type, fvPatchField, volMesh>::typeName
)
{ {
continue; // Load field
FieldType fld(ioobj, mesh);
// Convert
convertVolField(patchInterpList, fld);
} }
// Load field
GeometricField<Type, fvPatchField, volMesh> fld
(
*iter(),
mesh
);
// Convert
convertVolField(patchInterpList, fld);
} }
} }
@ -279,22 +290,21 @@ void Foam::vtkPVFoam::convertDimFields
const IOobjectList& objects const IOobjectList& objects
) )
{ {
typedef DimensionedField<Type, volMesh> FieldType;
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType; typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
forAllConstIters(objects, iter) forAllConstIters(objects, iter)
{ {
// Restrict to DimensionedField<Type, ...> // Restrict to DimensionedField<Type, ...>
if const auto& ioobj = *(iter.object());
(
iter()->headerClassName() if (ioobj.headerClassName() != FieldType::typeName)
!= DimensionedField<Type, volMesh>::typeName
)
{ {
continue; continue;
} }
// Load field // Load field
DimensionedField<Type, volMesh> dimFld(*iter(), mesh); FieldType dimFld(ioobj, mesh);
// Construct volField with zero-gradient patch fields // Construct volField with zero-gradient patch fields
@ -345,25 +355,33 @@ void Foam::vtkPVFoam::convertVolFieldBlock
{ {
continue; continue;
} }
const auto& longName = selectedPartIds_[partId];
auto iter = cachedVtu_.find(selectedPartIds_[partId]); auto iter = cachedVtu_.find(longName);
if (!iter.found() || !(*iter).vtkmesh) if (!iter.found() || !iter.object().dataset)
{ {
// Should not happen, but for safety require a vtk geometry
continue; continue;
} }
auto vtuData = (*iter); foamVtuData& vtuData = iter.object();
auto vtkmesh = (*iter).vtkmesh; auto dataset = vtuData.dataset;
vtkSmartPointer<vtkFloatArray> cdata = convertVolFieldToVTK vtkSmartPointer<vtkFloatArray> cdata = convertVolFieldToVTK
( (
fld, fld,
vtuData vtuData
); );
vtkmesh->GetCellData()->AddArray(cdata); dataset->GetCellData()->AddArray(cdata);
if (ptfPtr.valid()) if (ptfPtr.valid())
{ {
convertPointField(vtkmesh, ptfPtr(), fld, vtuData); vtkSmartPointer<vtkFloatArray> pdata = convertPointField
(
ptfPtr(),
fld,
vtuData
);
dataset->GetPointData()->AddArray(pdata);
} }
} }
} }
@ -382,17 +400,16 @@ void Foam::vtkPVFoam::convertPointFields
) )
{ {
const polyMesh& mesh = pMesh.mesh(); const polyMesh& mesh = pMesh.mesh();
const polyBoundaryMesh& patches = mesh.boundaryMesh();
typedef GeometricField<Type, pointPatchField, pointMesh> FieldType;
forAllConstIters(objects, iter) forAllConstIters(objects, iter)
{ {
const word& fieldName = iter()->name();
// Restrict to this GeometricField<Type, ...> // Restrict to this GeometricField<Type, ...>
if const auto& ioobj = *(iter.object());
(
iter()->headerClassName() const word& fieldName = ioobj.name();
!= GeometricField<Type, pointPatchField, pointMesh>::typeName if (ioobj.headerClassName() != FieldType::typeName)
)
{ {
continue; continue;
} }
@ -402,15 +419,13 @@ void Foam::vtkPVFoam::convertPointFields
Info<< "convertPointFields : " << fieldName << endl; Info<< "convertPointFields : " << fieldName << endl;
} }
GeometricField<Type, pointPatchField, pointMesh> pfld(*iter(), pMesh); FieldType pfld(ioobj, pMesh);
convertPointFieldBlock(pfld, rangeVolume_); // internalMesh convertPointFieldBlock(pfld, rangeVolume_); // internalMesh
convertPointFieldBlock(pfld, rangeCellZones_); // cellZones convertPointFieldBlock(pfld, rangeCellZones_); // cellZones
convertPointFieldBlock(pfld, rangeCellSets_); // cellSets convertPointFieldBlock(pfld, rangeCellSets_); // cellSets
// Patches - currently skip field conversion for groups
// Patches)
for (auto partId : rangePatches_) for (auto partId : rangePatches_)
{ {
if (!selectedPartIds_.found(partId)) if (!selectedPartIds_.found(partId))
@ -419,26 +434,22 @@ void Foam::vtkPVFoam::convertPointFields
} }
const auto& longName = selectedPartIds_[partId]; const auto& longName = selectedPartIds_[partId];
if (longName.startsWith("group/")) auto iter = cachedVtp_.find(longName);
if (!iter.found() || !iter.object().dataset)
{ {
// Skip patch-groups // Should not happen, but for safety require a vtk geometry
continue; continue;
} }
foamVtpData& vtpData = iter.object();
auto dataset = vtpData.dataset;
const word patchName = getPartName(partId); const labelList& patchIds = vtpData.additionalIds();
const label patchId = patches.findPatchID(patchName); if (patchIds.size() != 1)
if (patchId < 0)
{ {
continue; continue;
} }
auto iter = cachedVtp_.find(selectedPartIds_[partId]); const label patchId = patchIds[0];
if (!iter.found() || !(*iter).vtkmesh)
{
continue;
}
auto vtkmesh = (*iter).vtkmesh;
vtkSmartPointer<vtkFloatArray> pdata = convertFieldToVTK vtkSmartPointer<vtkFloatArray> pdata = convertFieldToVTK
( (
@ -446,27 +457,28 @@ void Foam::vtkPVFoam::convertPointFields
pfld.boundaryField()[patchId].patchInternalField()() pfld.boundaryField()[patchId].patchInternalField()()
); );
vtkmesh->GetPointData()->AddArray(pdata); dataset->GetPointData()->AddArray(pdata);
} }
// // Face Zones
// Convert (selected) faceZones
//
for (auto partId : rangeFaceZones_) for (auto partId : rangeFaceZones_)
{ {
if (!selectedPartIds_.found(partId)) if (!selectedPartIds_.found(partId))
{ {
continue; continue;
} }
const auto& longName = selectedPartIds_[partId];
const word zoneName = getFoamName(longName);
auto iter = cachedVtp_.find(selectedPartIds_[partId]); auto iter = cachedVtp_.find(longName);
if (!iter.found() || !(*iter).vtkmesh) if (!iter.found() || !iter.object().dataset)
{ {
// Should not happen, but for safety require a vtk geometry
continue; continue;
} }
auto vtkmesh = (*iter).vtkmesh; foamVtpData& vtpData = iter.object();
auto dataset = vtpData.dataset;
const word zoneName = getPartName(partId);
const label zoneId = mesh.faceZones().findZoneID(zoneName); const label zoneId = mesh.faceZones().findZoneID(zoneName);
if (zoneId < 0) if (zoneId < 0)
@ -488,7 +500,7 @@ void Foam::vtkPVFoam::convertPointFields
znfld znfld
); );
vtkmesh->GetPointData()->AddArray(pdata); dataset->GetPointData()->AddArray(pdata);
} }
} }
} }
@ -507,63 +519,58 @@ void Foam::vtkPVFoam::convertPointFieldBlock
{ {
continue; continue;
} }
const auto& longName = selectedPartIds_[partId];
auto iter = cachedVtu_.find(selectedPartIds_[partId]); auto iter = cachedVtu_.find(longName);
if (!iter.found() || ! (*iter).vtkmesh) if (!iter.found() || !iter.object().dataset)
{ {
// Should not happen, but for safety require a vtk geometry
continue; continue;
} }
auto vtuData = (*iter); foamVtuData& vtuData = iter.object();
auto vtkmesh = (*iter).vtkmesh; auto dataset = vtuData.dataset;
convertPointField vtkSmartPointer<vtkFloatArray> pdata = convertPointField
( (
vtkmesh,
pfld, pfld,
GeometricField<Type, fvPatchField, volMesh>::null(), GeometricField<Type, fvPatchField, volMesh>::null(),
vtuData vtuData
); );
dataset->GetPointData()->AddArray(pdata);
} }
} }
template<class Type> template<class Type>
void Foam::vtkPVFoam::convertPointField vtkSmartPointer<vtkFloatArray> Foam::vtkPVFoam::convertPointField
( (
vtkUnstructuredGrid* vtkmesh,
const GeometricField<Type, pointPatchField, pointMesh>& pfld, const GeometricField<Type, pointPatchField, pointMesh>& pfld,
const GeometricField<Type, fvPatchField, volMesh>& vfld, const GeometricField<Type, fvPatchField, volMesh>& vfld,
const foamVtuData& vtuData const foamVtuData& vtuData
) )
{ {
if (!vtkmesh) const int nComp(pTraits<Type>::nComponents);
{
return;
}
const label nComp = pTraits<Type>::nComponents;
const labelUList& addPointCellLabels = vtuData.additionalIds(); const labelUList& addPointCellLabels = vtuData.additionalIds();
const labelUList& pointMap = vtuData.pointMap(); const labelUList& pointMap = vtuData.pointMap();
// Use a pointMap or address directly into mesh // Use a pointMap or address directly into mesh
const label nPoints = (pointMap.size() ? pointMap.size() : pfld.size()); const label nPoints = (pointMap.size() ? pointMap.size() : pfld.size());
vtkSmartPointer<vtkFloatArray> fldData = auto data = vtkSmartPointer<vtkFloatArray>::New();
vtkSmartPointer<vtkFloatArray>::New(); data->SetNumberOfComponents(nComp);
data->SetNumberOfTuples(nPoints + addPointCellLabels.size());
fldData->SetNumberOfComponents(nComp);
fldData->SetNumberOfTuples(nPoints + addPointCellLabels.size());
// Note: using the name of the original volField // Note: using the name of the original volField
// not the name generated by the interpolation "volPointInterpolate(<name>)" // not the name generated by the interpolation "volPointInterpolate(<name>)"
if (&vfld != &GeometricField<Type, fvPatchField, volMesh>::null()) if (notNull(vfld))
{ {
fldData->SetName(vfld.name().c_str()); data->SetName(vfld.name().c_str());
} }
else else
{ {
fldData->SetName(pfld.name().c_str()); data->SetName(pfld.name().c_str());
} }
if (debug) if (debug)
@ -589,7 +596,7 @@ void Foam::vtkPVFoam::convertPointField
} }
foamPvFields::remapTuple<Type>(vec); foamPvFields::remapTuple<Type>(vec);
fldData->SetTuple(pointi++, vec); data->SetTuple(pointi++, vec);
} }
} }
else else
@ -603,13 +610,13 @@ void Foam::vtkPVFoam::convertPointField
} }
foamPvFields::remapTuple<Type>(vec); foamPvFields::remapTuple<Type>(vec);
fldData->SetTuple(pointi++, vec); data->SetTuple(pointi++, vec);
} }
} }
// Continue additional points // Continue with additional points
if (&vfld != &GeometricField<Type, fvPatchField, volMesh>::null()) if (notNull(vfld))
{ {
forAll(addPointCellLabels, apI) forAll(addPointCellLabels, apI)
{ {
@ -620,7 +627,7 @@ void Foam::vtkPVFoam::convertPointField
} }
foamPvFields::remapTuple<Type>(vec); foamPvFields::remapTuple<Type>(vec);
fldData->SetTuple(pointi++, vec); data->SetTuple(pointi++, vec);
} }
} }
else else
@ -634,11 +641,11 @@ void Foam::vtkPVFoam::convertPointField
} }
foamPvFields::remapTuple<Type>(vec); foamPvFields::remapTuple<Type>(vec);
fldData->SetTuple(pointi++, vec); data->SetTuple(pointi++, vec);
} }
} }
vtkmesh->GetPointData()->AddArray(fldData); return data;
} }
@ -656,19 +663,23 @@ void Foam::vtkPVFoam::convertLagrangianFields
{ {
forAllConstIters(objects, iter) forAllConstIters(objects, iter)
{ {
// restrict to this IOField<Type> // Restrict to IOField<Type>
if (iter()->headerClassName() == IOField<Type>::typeName) const auto& ioobj = *(iter.object());
{
IOField<Type> fld(*iter());
vtkSmartPointer<vtkFloatArray> fldData = if (ioobj.headerClassName() == IOField<Type>::typeName)
{
IOField<Type> fld(ioobj);
vtkSmartPointer<vtkFloatArray> data =
convertFieldToVTK convertFieldToVTK
( (
fld.name(), ioobj.name(),
fld fld
); );
vtkmesh->GetPointData()->AddArray(fldData); // Provide identical data as cell and as point data
vtkmesh->GetCellData()->AddArray(data);
vtkmesh->GetPointData()->AddArray(data);
} }
} }
} }
@ -679,45 +690,116 @@ void Foam::vtkPVFoam::convertLagrangianFields
// low-level conversions // low-level conversions
// //
template<class Type>
vtkSmartPointer<vtkFloatArray>
Foam::vtkPVFoam::zeroVTKField
(
const word& name,
const label size
)
{
auto data = vtkSmartPointer<vtkFloatArray>::New();
data->SetName(name.c_str());
data->SetNumberOfComponents(int(pTraits<Type>::nComponents));
data->SetNumberOfTuples(size);
data->Fill(0);
return data;
}
template<class Type>
Foam::label Foam::vtkPVFoam::transcribeFloatData
(
vtkFloatArray* array,
const UList<Type>& input,
const label start
)
{
const int nComp(pTraits<Type>::nComponents);
if (array->GetNumberOfComponents() != nComp)
{
FatalErrorInFunction
<< "vtk array '" << array->GetName()
<< "' has mismatch in number of components for type '"
<< pTraits<Type>::typeName
<< "' : target array has " << array->GetNumberOfComponents()
<< " components instead of " << nComp
<< endl;
}
const vtkIdType maxSize = array->GetNumberOfTuples();
const vtkIdType endPos = vtkIdType(start) + vtkIdType(input.size());
if (start < 0 || vtkIdType(start) >= maxSize)
{
WarningInFunction
<< "vtk array '" << array->GetName()
<< "' copy with out-of-range (0-" << long(maxSize-1) << ")"
<< " starting location"
<< endl;
return 0;
}
else if (endPos > maxSize)
{
WarningInFunction
<< "vtk array '" << array->GetName()
<< "' copy ends out-of-range (" << long(maxSize) << ")"
<< " using sizing (start,size) = ("
<< start << "," << input.size() << ")"
<< endl;
return 0;
}
float scratch[nComp];
forAll(input, idx)
{
const Type& t = input[idx];
for (direction d=0; d<nComp; ++d)
{
scratch[d] = component(t, d);
}
foamPvFields::remapTuple<Type>(scratch);
array->SetTuple(start+idx, scratch);
}
return input.size();
}
template<class Type> template<class Type>
vtkSmartPointer<vtkFloatArray> vtkSmartPointer<vtkFloatArray>
Foam::vtkPVFoam::convertFieldToVTK Foam::vtkPVFoam::convertFieldToVTK
( (
const word& name, const word& name,
const Field<Type>& fld const UList<Type>& fld
) ) const
{ {
const int nComp(pTraits<Type>::nComponents);
if (debug) if (debug)
{ {
Info<< "convert Field<" << pTraits<Type>::typeName << "> " Info<< "convert UList<" << pTraits<Type>::typeName << "> "
<< name << name
<< " size=" << fld.size() << " size=" << fld.size()
<< " nComp=" << label(pTraits<Type>::nComponents) << endl; << " nComp=" << nComp << endl;
} }
const label nComp = pTraits<Type>::nComponents; auto data = vtkSmartPointer<vtkFloatArray>::New();
vtkSmartPointer<vtkFloatArray> fldData = data->SetName(name.c_str());
vtkSmartPointer<vtkFloatArray>::New(); data->SetNumberOfComponents(nComp);
data->SetNumberOfTuples(fld.size());
fldData->SetNumberOfComponents(nComp); transcribeFloatData(data, fld);
fldData->SetNumberOfTuples(fld.size());
fldData->SetName(name.c_str());
float vec[nComp]; return data;
forAll(fld, idx)
{
const Type& t = fld[idx];
for (direction d=0; d<nComp; ++d)
{
vec[d] = component(t, d);
}
foamPvFields::remapTuple<Type>(vec);
fldData->SetTuple(idx, vec);
}
return fldData;
} }
@ -727,34 +809,32 @@ Foam::vtkPVFoam::convertFaceFieldToVTK
( (
const GeometricField<Type, fvPatchField, volMesh>& fld, const GeometricField<Type, fvPatchField, volMesh>& fld,
const labelUList& faceLabels const labelUList& faceLabels
) ) const
{ {
if (debug) if (debug)
{ {
Info<< "convert face field: " Info<< "convert face field: "
<< fld.name() << fld.name()
<< " size=" << faceLabels.size() << " size=" << faceLabels.size()
<< " nComp=" << label(pTraits<Type>::nComponents) << endl; << " nComp=" << int(pTraits<Type>::nComponents) << endl;
} }
const fvMesh& mesh = fld.mesh(); const fvMesh& mesh = fld.mesh();
const label nComp = pTraits<Type>::nComponents; const int nComp(pTraits<Type>::nComponents);
const label nInternalFaces = mesh.nInternalFaces(); const label nInternalFaces = mesh.nInternalFaces();
const labelList& faceOwner = mesh.faceOwner(); const labelList& faceOwner = mesh.faceOwner();
const labelList& faceNeigh = mesh.faceNeighbour(); const labelList& faceNeigh = mesh.faceNeighbour();
vtkSmartPointer<vtkFloatArray> fldData = auto data = vtkSmartPointer<vtkFloatArray>::New();
vtkSmartPointer<vtkFloatArray>::New(); data->SetName(fld.name().c_str());
data->SetNumberOfComponents(nComp);
data->SetNumberOfTuples(faceLabels.size());
fldData->SetNumberOfComponents(nComp); float scratch[nComp];
fldData->SetNumberOfTuples(faceLabels.size());
fldData->SetName(fld.name().c_str());
float vec[nComp]; // Interior faces: average owner/neighbour
// Boundary faces: the owner value
// for interior faces: average owner/neighbour
// for boundary faces: owner
forAll(faceLabels, idx) forAll(faceLabels, idx)
{ {
const label faceNo = faceLabels[idx]; const label faceNo = faceLabels[idx];
@ -764,7 +844,7 @@ Foam::vtkPVFoam::convertFaceFieldToVTK
for (direction d=0; d<nComp; ++d) for (direction d=0; d<nComp; ++d)
{ {
vec[d] = component(t, d); scratch[d] = component(t, d);
} }
} }
else else
@ -772,15 +852,15 @@ Foam::vtkPVFoam::convertFaceFieldToVTK
const Type& t = fld[faceOwner[faceNo]]; const Type& t = fld[faceOwner[faceNo]];
for (direction d=0; d<nComp; ++d) for (direction d=0; d<nComp; ++d)
{ {
vec[d] = component(t, d); scratch[d] = component(t, d);
} }
} }
foamPvFields::remapTuple<Type>(vec); foamPvFields::remapTuple<Type>(scratch);
fldData->SetTuple(idx, vec); data->SetTuple(idx, scratch);
} }
return fldData; return data;
} }
@ -790,17 +870,15 @@ Foam::vtkPVFoam::convertVolFieldToVTK
( (
const GeometricField<Type, fvPatchField, volMesh>& fld, const GeometricField<Type, fvPatchField, volMesh>& fld,
const foamVtuData& vtuData const foamVtuData& vtuData
) ) const
{ {
const label nComp = pTraits<Type>::nComponents; const int nComp(pTraits<Type>::nComponents);
const labelList& cellMap = vtuData.cellMap(); const labelUList& cellMap = vtuData.cellMap();
vtkSmartPointer<vtkFloatArray> fldData = auto data = vtkSmartPointer<vtkFloatArray>::New();
vtkSmartPointer<vtkFloatArray>::New(); data->SetName(fld.name().c_str());
data->SetNumberOfComponents(nComp);
fldData->SetNumberOfComponents(nComp); data->SetNumberOfTuples(cellMap.size());
fldData->SetNumberOfTuples(cellMap.size());
fldData->SetName(fld.name().c_str());
if (debug) if (debug)
{ {
@ -812,20 +890,20 @@ Foam::vtkPVFoam::convertVolFieldToVTK
<< ") nComp=" << nComp << endl; << ") nComp=" << nComp << endl;
} }
float vec[nComp]; float scratch[nComp];
forAll(cellMap, idx) forAll(cellMap, idx)
{ {
const Type& t = fld[cellMap[idx]]; const Type& t = fld[cellMap[idx]];
for (direction d=0; d<nComp; ++d) for (direction d=0; d<nComp; ++d)
{ {
vec[d] = component(t, d); scratch[d] = component(t, d);
} }
foamPvFields::remapTuple<Type>(vec); foamPvFields::remapTuple<Type>(scratch);
fldData->SetTuple(idx, vec); data->SetTuple(idx, scratch);
} }
return fldData; return data;
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -40,28 +40,6 @@ License
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::vtkPVFoam::pruneObjectList
(
IOobjectList& objects,
const hashedWordList& retain
)
{
if (retain.empty())
{
objects.clear();
}
// only retain specified fields
forAllIters(objects, iter)
{
if (!retain.found(iter()->name()))
{
objects.erase(iter);
}
}
}
void Foam::vtkPVFoam::convertVolFields() void Foam::vtkPVFoam::convertVolFields()
{ {
const fvMesh& mesh = *meshPtr_; const fvMesh& mesh = *meshPtr_;
@ -80,7 +58,7 @@ void Foam::vtkPVFoam::convertVolFields()
// Get objects (fields) for this time - only keep selected fields // Get objects (fields) for this time - only keep selected fields
// the region name is already in the mesh db // the region name is already in the mesh db
IOobjectList objects(mesh, dbPtr_().timeName()); IOobjectList objects(mesh, dbPtr_().timeName());
pruneObjectList(objects, selectedFields); objects.filterKeys(selectedFields);
if (objects.empty()) if (objects.empty())
{ {
@ -89,7 +67,7 @@ void Foam::vtkPVFoam::convertVolFields()
if (debug) if (debug)
{ {
Info<< "<beg> convert volume fields" << endl; Info<< "<beg> " << FUNCTION_NAME << endl;
forAllConstIters(objects, iter) forAllConstIters(objects, iter)
{ {
Info<< " " << iter()->name() Info<< " " << iter()->name()
@ -132,7 +110,7 @@ void Foam::vtkPVFoam::convertVolFields()
if (debug) if (debug)
{ {
Info<< "<end> convert volume fields" << endl; Info<< "<end> " << FUNCTION_NAME << endl;
printMemory(); printMemory();
} }
} }
@ -159,7 +137,7 @@ void Foam::vtkPVFoam::convertPointFields()
// Get objects (fields) for this time - only keep selected fields // Get objects (fields) for this time - only keep selected fields
// the region name is already in the mesh db // the region name is already in the mesh db
IOobjectList objects(mesh, dbPtr_().timeName()); IOobjectList objects(mesh, dbPtr_().timeName());
pruneObjectList(objects, selectedFields); objects.filterKeys(selectedFields);
if (objects.empty()) if (objects.empty())
{ {
@ -196,7 +174,7 @@ void Foam::vtkPVFoam::convertPointFields()
void Foam::vtkPVFoam::convertLagrangianFields() void Foam::vtkPVFoam::convertLagrangianFields()
{ {
arrayRange& range = rangeLagrangian_; const arrayRange& range = rangeLagrangian_;
const fvMesh& mesh = *meshPtr_; const fvMesh& mesh = *meshPtr_;
hashedWordList selectedFields = getSelected hashedWordList selectedFields = getSelected
@ -211,7 +189,7 @@ void Foam::vtkPVFoam::convertLagrangianFields()
if (debug) if (debug)
{ {
Info<< "<beg> convert Lagrangian fields" << endl; Info<< "<beg> " << FUNCTION_NAME << endl;
printMemory(); printMemory();
} }
@ -222,14 +200,16 @@ void Foam::vtkPVFoam::convertLagrangianFields()
continue; continue;
} }
const word cloudName = getPartName(partId); const auto& longName = selectedPartIds_[partId];
auto iter = cachedVtp_.find(selectedPartIds_[partId]); const word cloudName = getFoamName(longName);
if (!iter.found() || !(*iter).vtkmesh) auto iter = cachedVtp_.find(longName);
if (!iter.found() || !iter.object().dataset)
{ {
// Should not happen, but for safety require a vtk geometry
continue; continue;
} }
auto vtkmesh = (*iter).vtkmesh; auto dataset = iter.object().dataset;
// Get the Lagrangian fields for this time and this cloud // Get the Lagrangian fields for this time and this cloud
// but only keep selected fields // but only keep selected fields
@ -240,7 +220,7 @@ void Foam::vtkPVFoam::convertLagrangianFields()
dbPtr_().timeName(), dbPtr_().timeName(),
cloud::prefix/cloudName cloud::prefix/cloudName
); );
pruneObjectList(objects, selectedFields); objects.filterKeys(selectedFields);
if (objects.empty()) if (objects.empty())
{ {
@ -257,17 +237,17 @@ void Foam::vtkPVFoam::convertLagrangianFields()
} }
} }
convertLagrangianFields<label>(objects, vtkmesh); convertLagrangianFields<label>(objects, dataset);
convertLagrangianFields<scalar>(objects, vtkmesh); convertLagrangianFields<scalar>(objects, dataset);
convertLagrangianFields<vector>(objects, vtkmesh); convertLagrangianFields<vector>(objects, dataset);
convertLagrangianFields<sphericalTensor>(objects, vtkmesh); convertLagrangianFields<sphericalTensor>(objects, dataset);
convertLagrangianFields<symmTensor>(objects, vtkmesh); convertLagrangianFields<symmTensor>(objects, dataset);
convertLagrangianFields<tensor>(objects, vtkmesh); convertLagrangianFields<tensor>(objects, dataset);
} }
if (debug) if (debug)
{ {
Info<< "<end> convert Lagrangian fields" << endl; Info<< "<end> " << FUNCTION_NAME << endl;
printMemory(); printMemory();
} }
} }

View File

@ -44,7 +44,7 @@ License
void Foam::vtkPVFoam::convertMeshVolume() void Foam::vtkPVFoam::convertMeshVolume()
{ {
arrayRange& range = rangeVolume_; const arrayRange& range = rangeVolume_;
const fvMesh& mesh = *meshPtr_; const fvMesh& mesh = *meshPtr_;
if (debug) if (debug)
@ -60,15 +60,38 @@ void Foam::vtkPVFoam::convertMeshVolume()
if (selectedPartIds_.found(partId)) if (selectedPartIds_.found(partId))
{ {
const auto& longName = selectedPartIds_[partId]; const auto& longName = selectedPartIds_[partId];
foamVtuData& vtuData = cachedVtu_(longName);
vtkSmartPointer<vtkUnstructuredGrid> vtkmesh = vtkSmartPointer<vtkUnstructuredGrid> vtkgeom;
volumeVTKMesh if (vtuData.nPoints())
( {
mesh, if (meshState_ == polyMesh::UNCHANGED)
cachedVtu_(longName) {
); if (debug)
{
Info<< "reuse " << longName << nl;
}
vtuData.reuse(); // reuse
continue;
}
else if (meshState_ == polyMesh::POINTS_MOVED)
{
if (debug)
{
Info<< "move points " << longName << nl;
}
vtkgeom = vtuData.getCopy();
vtkgeom->SetPoints(movePoints(mesh, vtuData));
}
}
cachedVtu_[longName].vtkmesh = vtkmesh; if (!vtkgeom)
{
// Nothing usable from cache - create new geometry
vtkgeom = volumeVTKMesh(mesh, vtuData);
}
vtuData.set(vtkgeom);
} }
} }
@ -82,7 +105,7 @@ void Foam::vtkPVFoam::convertMeshVolume()
void Foam::vtkPVFoam::convertMeshLagrangian() void Foam::vtkPVFoam::convertMeshLagrangian()
{ {
arrayRange& range = rangeLagrangian_; const arrayRange& range = rangeLagrangian_;
const fvMesh& mesh = *meshPtr_; const fvMesh& mesh = *meshPtr_;
if (debug) if (debug)
@ -96,16 +119,13 @@ void Foam::vtkPVFoam::convertMeshLagrangian()
if (selectedPartIds_.found(partId)) if (selectedPartIds_.found(partId))
{ {
const auto& longName = selectedPartIds_[partId]; const auto& longName = selectedPartIds_[partId];
const word cloudName = getPartName(partId); const word cloudName = getFoamName(longName);
vtkSmartPointer<vtkPolyData> vtkmesh = // Direct conversion, no caching for Lagrangian
lagrangianVTKMesh cachedVtp_(longName).set
( (
mesh, lagrangianVTKMesh(mesh, cloudName)
cloudName );
);
cachedVtp_(longName).vtkmesh = vtkmesh;
} }
} }
@ -119,7 +139,7 @@ void Foam::vtkPVFoam::convertMeshLagrangian()
void Foam::vtkPVFoam::convertMeshPatches() void Foam::vtkPVFoam::convertMeshPatches()
{ {
arrayRange& range = rangePatches_; const arrayRange& range = rangePatches_;
const fvMesh& mesh = *meshPtr_; const fvMesh& mesh = *meshPtr_;
const polyBoundaryMesh& patches = mesh.boundaryMesh(); const polyBoundaryMesh& patches = mesh.boundaryMesh();
@ -136,14 +156,42 @@ void Foam::vtkPVFoam::convertMeshPatches()
continue; continue;
} }
const auto& longName = selectedPartIds_[partId]; const auto& longName = selectedPartIds_[partId];
const word partName = getPartName(partId); const word partName = getFoamName(longName);
foamVtpData& vtpData = cachedVtp_(longName);
vtkSmartPointer<vtkPolyData> vtkmesh; vtkSmartPointer<vtkPolyData> vtkgeom;
if (vtpData.nPoints())
{
if (meshState_ == polyMesh::UNCHANGED)
{
// Without movement is easy.
if (debug)
{
Info<< "reuse " << longName << nl;
}
vtpData.reuse();
continue;
}
else if (meshState_ == polyMesh::POINTS_MOVED)
{
// Point movement on single patch is OK
const labelList& patchIds = vtpData.additionalIds();
if (patchIds.size() == 1)
{
vtkgeom = vtpData.getCopy();
vtkgeom->SetPoints(movePatchPoints(patches[patchIds[0]]));
continue;
}
}
}
if (longName.startsWith("group/")) if (longName.startsWith("group/"))
{ {
// Patch group. Collect patch faces. // Patch group. Collect patch faces.
vtpData.clear(); // Remove any old mappings
const labelList& patchIds = const labelList& patchIds =
patches.groupPatchIDs().lookup(partName, labelList()); patches.groupPatchIDs().lookup(partName, labelList());
@ -153,19 +201,32 @@ void Foam::vtkPVFoam::convertMeshPatches()
<< longName << endl; << longName << endl;
} }
// Store good patch ids as additionalIds
vtpData.additionalIds().reserve(patchIds.size());
label sz = 0; label sz = 0;
for (auto id : patchIds) for (auto id : patchIds)
{ {
sz += patches[id].size(); const label n = patches[id].size();
if (n)
{
vtpData.additionalIds().append(id);
sz += n;
}
} }
labelList faceLabels(sz); Foam::sort(vtpData.additionalIds());
sz = 0;
for (auto id : patchIds) // Temporarily (mis)use cellMap for face labels
DynamicList<label>& faceLabels = vtpData.cellMap();
faceLabels.reserve(sz);
for (auto id : vtpData.additionalIds())
{ {
const auto& pp = patches[id]; const auto& pp = patches[id];
forAll(pp, i) forAll(pp, i)
{ {
faceLabels[sz++] = pp.start()+i; faceLabels.append(pp.start()+i);
} }
} }
@ -177,11 +238,15 @@ void Foam::vtkPVFoam::convertMeshPatches()
mesh.points() mesh.points()
); );
vtkmesh = patchVTKMesh(partName, pp); vtkgeom = patchVTKMesh(pp);
} }
faceLabels.clear(); // Unneeded
} }
else else
{ {
vtpData.clear(); // Remove any old mappings
const label patchId = patches.findPatchID(partName); const label patchId = patches.findPatchID(partName);
if (debug) if (debug)
@ -192,13 +257,20 @@ void Foam::vtkPVFoam::convertMeshPatches()
if (patchId >= 0) if (patchId >= 0)
{ {
vtkmesh = patchVTKMesh(partName, patches[patchId]); // Store good patch id as additionalIds
vtpData.additionalIds() = {patchId};
vtkgeom = patchVTKMesh(patches[patchId]);
} }
} }
if (vtkmesh) if (vtkgeom)
{ {
cachedVtp_(longName).vtkmesh = vtkmesh; vtpData.set(vtkgeom);
}
else
{
cachedVtp_.erase(longName);
} }
} }
@ -210,36 +282,6 @@ void Foam::vtkPVFoam::convertMeshPatches()
} }
void Foam::vtkPVFoam::convertMeshSubset
(
const fvMeshSubset& subsetter,
const string& longName
)
{
vtkSmartPointer<vtkUnstructuredGrid> vtkmesh = volumeVTKMesh
(
subsetter.subMesh(),
cachedVtu_(longName)
);
// Convert cellMap, addPointCellLabels to global cell ids
inplaceRenumber
(
subsetter.cellMap(),
cachedVtu_[longName].cellMap()
);
inplaceRenumber
(
subsetter.cellMap(),
cachedVtu_[longName].additionalIds()
);
// copy pointMap as well, otherwise pointFields fail
cachedVtu_[longName].pointMap() = subsetter.pointMap();
cachedVtu_[longName].vtkmesh = vtkmesh;
}
void Foam::vtkPVFoam::convertMeshCellZones() void Foam::vtkPVFoam::convertMeshCellZones()
{ {
const arrayRange& range = rangeCellZones_; const arrayRange& range = rangeCellZones_;
@ -265,7 +307,7 @@ void Foam::vtkPVFoam::convertMeshCellZones()
} }
const auto& longName = selectedPartIds_[partId]; const auto& longName = selectedPartIds_[partId];
const word zoneName = getPartName(partId); const word zoneName = getFoamName(longName);
const label zoneId = zMesh.findZoneID(zoneName); const label zoneId = zMesh.findZoneID(zoneName);
if (zoneId < 0) if (zoneId < 0)
@ -279,10 +321,43 @@ void Foam::vtkPVFoam::convertMeshCellZones()
<< zoneName << endl; << zoneName << endl;
} }
fvMeshSubset subsetter(mesh); foamVtuData& vtuData = cachedVtu_(longName);
subsetter.setLargeCellSubset(zMesh[zoneId]);
convertMeshSubset(subsetter, longName); vtkSmartPointer<vtkUnstructuredGrid> vtkgeom;
if (vtuData.nPoints() && vtuData.pointMap().size())
{
if (meshState_ == polyMesh::UNCHANGED)
{
if (debug)
{
Info<< "reuse " << longName << nl;
}
vtuData.reuse();
continue;
}
else if (meshState_ == polyMesh::POINTS_MOVED)
{
if (debug)
{
Info<< "move points " << longName << nl;
}
vtkgeom = vtuData.getCopy();
vtkgeom->SetPoints
(
movePoints(mesh, vtuData, vtuData.pointMap())
);
}
}
if (!vtkgeom)
{
fvMeshSubset subsetter(mesh);
subsetter.setLargeCellSubset(zMesh[zoneId]);
vtkgeom = volumeVTKSubsetMesh(subsetter, vtuData);
}
vtuData.set(vtkgeom);
} }
if (debug) if (debug)
@ -312,18 +387,50 @@ void Foam::vtkPVFoam::convertMeshCellSets()
} }
const auto& longName = selectedPartIds_[partId]; const auto& longName = selectedPartIds_[partId];
const word partName = getPartName(partId); const word partName = getFoamName(longName);
if (debug) if (debug)
{ {
Info<< "Creating VTK mesh for cellSet=" << partName << endl; Info<< "Creating VTK mesh for cellSet=" << partName << endl;
} }
const cellSet cSet(mesh, partName); foamVtuData& vtuData = cachedVtu_(longName);
fvMeshSubset subsetter(mesh);
subsetter.setLargeCellSubset(cSet);
convertMeshSubset(subsetter, longName); vtkSmartPointer<vtkUnstructuredGrid> vtkgeom;
if (vtuData.nPoints() && vtuData.pointMap().size())
{
if (meshState_ == polyMesh::UNCHANGED)
{
if (debug)
{
Info<< "reuse " << longName << nl;
}
vtuData.reuse();
continue;
}
else if (meshState_ == polyMesh::POINTS_MOVED)
{
if (debug)
{
Info<< "move points " << longName << nl;
}
vtkgeom = vtuData.getCopy();
vtkgeom->SetPoints
(
movePoints(mesh, vtuData, vtuData.pointMap())
);
}
}
if (!vtkgeom)
{
fvMeshSubset subsetter(mesh);
subsetter.setLargeCellSubset(cellSet(mesh, partName));
vtkgeom = volumeVTKSubsetMesh(subsetter, vtuData);
}
vtuData.set(vtkgeom);
} }
if (debug) if (debug)
@ -336,7 +443,7 @@ void Foam::vtkPVFoam::convertMeshCellSets()
void Foam::vtkPVFoam::convertMeshFaceZones() void Foam::vtkPVFoam::convertMeshFaceZones()
{ {
arrayRange& range = rangeFaceZones_; const arrayRange& range = rangeFaceZones_;
const fvMesh& mesh = *meshPtr_; const fvMesh& mesh = *meshPtr_;
if (range.empty()) if (range.empty())
@ -359,28 +466,49 @@ void Foam::vtkPVFoam::convertMeshFaceZones()
} }
const auto& longName = selectedPartIds_[partId]; const auto& longName = selectedPartIds_[partId];
const word zoneName = getPartName(partId); const word zoneName = getFoamName(longName);
const label zoneId = zMesh.findZoneID(zoneName); const label zoneId = zMesh.findZoneID(zoneName);
if (zoneId < 0) if (zoneId < 0)
{ {
continue; continue;
} }
if (debug) if (debug)
{ {
Info<< "Creating VTKmesh for faceZone[" << zoneId << "] " Info<< "Creating VTKmesh for faceZone[" << zoneId << "] "
<< zoneName << endl; << zoneName << endl;
} }
vtkSmartPointer<vtkPolyData> vtkmesh = foamVtpData& vtpData = cachedVtp_(longName);
patchVTKMesh
(
zoneName,
zMesh[zoneId]()
);
cachedVtp_(longName).vtkmesh = vtkmesh; vtkSmartPointer<vtkPolyData> vtkgeom;
if (vtpData.nPoints())
{
if (meshState_ == polyMesh::UNCHANGED)
{
// Without movement is easy.
if (debug)
{
Info<<"reuse " << longName << nl;
}
vtpData.reuse();
continue;
}
else if (meshState_ == polyMesh::POINTS_MOVED)
{
// Need point maps etc - not worth it at the moment
}
}
if (!vtkgeom)
{
vtpData.clear(); // No additional ids, maps
const primitiveFacePatch& pp = zMesh[zoneId]();
vtkgeom = patchVTKMesh(pp);
}
vtpData.set(vtkgeom);
} }
if (debug) if (debug)
@ -393,7 +521,7 @@ void Foam::vtkPVFoam::convertMeshFaceZones()
void Foam::vtkPVFoam::convertMeshFaceSets() void Foam::vtkPVFoam::convertMeshFaceSets()
{ {
arrayRange& range = rangeFaceSets_; const arrayRange& range = rangeFaceSets_;
const fvMesh& mesh = *meshPtr_; const fvMesh& mesh = *meshPtr_;
if (debug) if (debug)
@ -410,35 +538,61 @@ void Foam::vtkPVFoam::convertMeshFaceSets()
} }
const auto& longName = selectedPartIds_[partId]; const auto& longName = selectedPartIds_[partId];
const word partName = getPartName(partId); const word partName = getFoamName(longName);
if (debug) if (debug)
{ {
Info<< "Creating VTK mesh for faceSet=" << partName << endl; Info<< "Creating VTK mesh for faceSet=" << partName << endl;
} }
// faces in sorted order for more reliability foamVtpData& vtpData = cachedVtp_(longName);
const labelList faceLabels = faceSet(mesh, partName).sortedToc();
uindirectPrimitivePatch p vtkSmartPointer<vtkPolyData> vtkgeom;
( if (vtpData.nPoints())
UIndirectList<face>(mesh.faces(), faceLabels),
mesh.points()
);
if (p.empty())
{ {
continue; if (meshState_ == polyMesh::UNCHANGED)
{
// Without movement is easy.
if (debug)
{
Info<<"reuse " << longName << nl;
}
vtpData.reuse();
continue;
}
else if (meshState_ == polyMesh::POINTS_MOVED)
{
// Need point maps etc - not worth it at the moment
}
} }
vtkSmartPointer<vtkPolyData> vtkmesh = if (!vtkgeom)
patchVTKMesh {
( vtpData.clear(); // No other additional ids, maps
"faceSet:" + partName,
p
);
cachedVtp_(longName).vtkmesh = vtkmesh; // Misuse cellMap for face labels - sorted order for reliability
vtpData.cellMap() = faceSet(mesh, partName).sortedToc();
if (vtpData.cellMap().size())
{
uindirectPrimitivePatch pp
(
UIndirectList<face>(mesh.faces(), vtpData.cellMap()),
mesh.points()
);
vtkgeom = patchVTKMesh(pp);
}
}
if (vtkgeom)
{
vtpData.set(vtkgeom);
}
else
{
cachedVtp_.erase(longName);
}
} }
if (debug) if (debug)
@ -451,7 +605,7 @@ void Foam::vtkPVFoam::convertMeshFaceSets()
void Foam::vtkPVFoam::convertMeshPointZones() void Foam::vtkPVFoam::convertMeshPointZones()
{ {
arrayRange& range = rangePointZones_; const arrayRange& range = rangePointZones_;
const fvMesh& mesh = *meshPtr_; const fvMesh& mesh = *meshPtr_;
if (debug) if (debug)
@ -471,7 +625,7 @@ void Foam::vtkPVFoam::convertMeshPointZones()
} }
const auto& longName = selectedPartIds_[partId]; const auto& longName = selectedPartIds_[partId];
const word zoneName = getPartName(partId); const word zoneName = getFoamName(longName);
const label zoneId = zMesh.findZoneID(zoneName); const label zoneId = zMesh.findZoneID(zoneName);
if (zoneId < 0) if (zoneId < 0)
@ -479,29 +633,50 @@ void Foam::vtkPVFoam::convertMeshPointZones()
continue; continue;
} }
const pointField& meshPoints = mesh.points(); foamVtpData& vtpData = cachedVtp_(longName);
const labelUList& pointLabels = zMesh[zoneId];
vtkSmartPointer<vtkPoints> vtkpoints = vtkSmartPointer<vtkPolyData> vtkgeom;
vtkSmartPointer<vtkPoints>::New(); if (vtpData.nPoints() && vtpData.pointMap().size())
vtkpoints->SetNumberOfPoints(pointLabels.size());
forAll(pointLabels, pointi)
{ {
vtkpoints->SetPoint if (meshState_ == polyMesh::UNCHANGED)
( {
pointi, if (debug)
meshPoints[pointLabels[pointi]].v_ {
); Info<< "reusing " << longName << nl;
}
vtpData.reuse();
continue;
}
else if (meshState_ == polyMesh::POINTS_MOVED)
{
if (debug)
{
Info<< "move points " << longName << nl;
}
vtkgeom = vtpData.getCopy();
}
} }
vtkSmartPointer<vtkPolyData> vtkmesh = if (!vtkgeom)
vtkSmartPointer<vtkPolyData>::New(); {
// First time, or topo change
vtkgeom = vtkSmartPointer<vtkPolyData>::New();
vtpData.pointMap() = zMesh[zoneId];
}
vtkmesh->SetPoints(vtkpoints); const pointField& points = mesh.points();
const labelUList& pointMap = vtpData.pointMap();
cachedVtp_(longName).vtkmesh = vtkmesh; auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkpoints->SetNumberOfPoints(pointMap.size());
forAll(pointMap, pointi)
{
vtkpoints->SetPoint(pointi, points[pointMap[pointi]].v_);
}
vtkgeom->SetPoints(vtkpoints);
vtpData.set(vtkgeom);
} }
} }
@ -515,7 +690,7 @@ void Foam::vtkPVFoam::convertMeshPointZones()
void Foam::vtkPVFoam::convertMeshPointSets() void Foam::vtkPVFoam::convertMeshPointSets()
{ {
arrayRange& range = rangePointSets_; const arrayRange& range = rangePointSets_;
const fvMesh& mesh = *meshPtr_; const fvMesh& mesh = *meshPtr_;
if (debug) if (debug)
@ -532,36 +707,52 @@ void Foam::vtkPVFoam::convertMeshPointSets()
} }
const auto& longName = selectedPartIds_[partId]; const auto& longName = selectedPartIds_[partId];
const word partName = getPartName(partId); const word partName = getFoamName(longName);
if (debug) foamVtpData& vtpData = cachedVtp_(longName);
vtkSmartPointer<vtkPolyData> vtkgeom;
if (vtpData.nPoints() && vtpData.pointMap().size())
{ {
Info<< "Creating VTK mesh for pointSet=" << partName << endl; if (meshState_ == polyMesh::UNCHANGED)
{
if (debug)
{
Info<< "reusing " << longName << nl;
}
vtpData.reuse();
continue;
}
else if (meshState_ == polyMesh::POINTS_MOVED)
{
if (debug)
{
Info<< "move points " << longName << nl;
}
vtkgeom = vtpData.getCopy();
}
} }
const pointField& meshPoints = mesh.points(); if (!vtkgeom)
const labelList pointLabels = pointSet(mesh, partName).sortedToc();
vtkSmartPointer<vtkPoints> vtkpoints =
vtkSmartPointer<vtkPoints>::New();
vtkpoints->SetNumberOfPoints(pointLabels.size());
forAll(pointLabels, pointi)
{ {
vtkpoints->SetPoint // First time, or topo change
( vtkgeom = vtkSmartPointer<vtkPolyData>::New();
pointi, vtpData.pointMap() = pointSet(mesh, partName).sortedToc();
meshPoints[pointLabels[pointi]].v_
);
} }
vtkSmartPointer<vtkPolyData> vtkmesh = const pointField& points = mesh.points();
vtkSmartPointer<vtkPolyData>::New(); const labelUList& pointMap = vtpData.pointMap();
vtkmesh->SetPoints(vtkpoints); auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
cachedVtp_(longName).vtkmesh = vtkmesh; vtkpoints->SetNumberOfPoints(pointMap.size());
forAll(pointMap, pointi)
{
vtkpoints->SetPoint(pointi, points[pointMap[pointi]].v_);
}
vtkgeom->SetPoints(vtkpoints);
vtpData.set(vtkgeom);
} }
if (debug) if (debug)

View File

@ -43,7 +43,7 @@ vtkSmartPointer<vtkPolyData> Foam::vtkPVFoam::lagrangianVTKMesh
( (
const polyMesh& mesh, const polyMesh& mesh,
const word& cloudName const word& cloudName
) ) const
{ {
vtkSmartPointer<vtkPolyData> vtkmesh; vtkSmartPointer<vtkPolyData> vtkmesh;
@ -73,29 +73,19 @@ vtkSmartPointer<vtkPolyData> Foam::vtkPVFoam::lagrangianVTKMesh
Info<< "cloud with " << parcels.size() << " parcels" << endl; Info<< "cloud with " << parcels.size() << " parcels" << endl;
} }
vtkmesh = vtkSmartPointer<vtkPolyData>::New(); auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPoints> vtkpoints =
vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkcells =
vtkSmartPointer<vtkCellArray>::New();
vtkpoints->SetNumberOfPoints(parcels.size()); vtkpoints->SetNumberOfPoints(parcels.size());
vtkcells->Allocate(2*parcels.size());
// If reusing memory, ensure insert always starts from 0
vtkcells->Reset();
vtkIdType particleId = 0; vtkIdType particleId = 0;
forAllConstIters(parcels, iter) forAllConstIters(parcels, iter)
{ {
vtkpoints->SetPoint(particleId, iter().position().v_); vtkpoints->SetPoint(particleId, iter().position().v_);
vtkcells->InsertNextCell(1, &particleId); // VTK_VERTEX ++particleId;
particleId++;
} }
vtkmesh = vtkSmartPointer<vtkPolyData>::New();
vtkmesh->SetPoints(vtkpoints); vtkmesh->SetPoints(vtkpoints);
vtkmesh->SetVerts(vtkcells); vtkmesh->SetVerts(foamPvCore::identityVertices(parcels.size()));
} }
if (debug) if (debug)

View File

@ -28,18 +28,89 @@ License
// OpenFOAM includes // OpenFOAM includes
#include "fvMesh.H" #include "fvMesh.H"
#include "fvMeshSubset.H"
#include "foamVtkAdaptors.H"
#include "foamVtuSizing.H" #include "foamVtuSizing.H"
// VTK includes // VTK includes
#include "vtkUnstructuredGrid.h" #include "vtkUnstructuredGrid.h"
#include "foamVtkAdaptors.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
vtkSmartPointer<vtkPoints> Foam::vtkPVFoam::movePoints
(
const fvMesh& mesh,
const foamVtuData& vtuData
)
{
// Convert OpenFOAM mesh vertices to VTK
auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
// Normal points
const pointField& points = mesh.points();
// Additional cell centres
const labelList& addPoints = vtuData.additionalIds();
vtkpoints->SetNumberOfPoints(points.size() + addPoints.size());
// Normal points
label pointi = 0;
forAll(points, i)
{
vtkpoints->SetPoint(pointi++, points[i].v_);
}
// Cell centres
forAll(addPoints, i)
{
vtkpoints->SetPoint(pointi++, mesh.C()[addPoints[i]].v_);
}
return vtkpoints;
}
vtkSmartPointer<vtkPoints> Foam::vtkPVFoam::movePoints
(
const fvMesh& mesh,
const foamVtuData& vtuData,
const labelUList& pointMap
)
{
// Convert OpenFOAM mesh vertices to VTK
auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
// Normal points
const pointField& points = mesh.points();
// Additional cell centres
const labelList& addPoints = vtuData.additionalIds();
vtkpoints->SetNumberOfPoints(pointMap.size() + addPoints.size());
// Normal points
label pointi = 0;
forAll(pointMap, i)
{
vtkpoints->SetPoint(pointi++, points[pointMap[i]].v_);
}
// Cell centres
forAll(addPoints, i)
{
vtkpoints->SetPoint(pointi++, mesh.C()[addPoints[i]].v_);
}
return vtkpoints;
}
vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKMesh vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKMesh
( (
const fvMesh& mesh, const fvMesh& mesh,
foamVtuData& vtuData foamVtuData& vtuData,
const bool decompPoly
) )
{ {
if (debug) if (debug)
@ -48,25 +119,15 @@ vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKMesh
printMemory(); printMemory();
} }
foamVtuSizing sizing(mesh, !reader_->GetUseVTKPolyhedron()); foamVtuSizing sizing(mesh, decompPoly);
vtkSmartPointer<vtkUnstructuredGrid> vtkmesh = auto cellTypes = vtkSmartPointer<vtkUnsignedCharArray>::New();
vtkSmartPointer<vtkUnstructuredGrid>::New();
auto cellTypes = auto cells = vtkSmartPointer<vtkCellArray>::New();
nonNullSmartPointer<vtkUnsignedCharArray>(vtkmesh->GetCellTypesArray()); auto faces = vtkSmartPointer<vtkIdTypeArray>::New();
auto cells = auto cellLocations = vtkSmartPointer<vtkIdTypeArray>::New();
nonNullSmartPointer<vtkCellArray>(vtkmesh->GetCells()); auto faceLocations = vtkSmartPointer<vtkIdTypeArray>::New();
auto faces =
nonNullSmartPointer<vtkIdTypeArray>(vtkmesh->GetFaces());
auto cellLocations =
nonNullSmartPointer<vtkIdTypeArray>(vtkmesh->GetCellLocationsArray());
auto faceLocations =
nonNullSmartPointer<vtkIdTypeArray>(vtkmesh->GetFaceLocations());
UList<uint8_t> cellTypesUL = UList<uint8_t> cellTypesUL =
vtkUList vtkUList
@ -116,33 +177,12 @@ vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKMesh
static_cast<foamVtkMeshMaps&>(vtuData) static_cast<foamVtkMeshMaps&>(vtuData)
); );
auto vtkmesh = vtkSmartPointer<vtkUnstructuredGrid>::New();
// Convert OpenFOAM mesh vertices to VTK // Convert OpenFOAM mesh vertices to VTK
// - can only do this *after* populating the decompInfo with cell-ids // - can only do this *after* populating the decompInfo with cell-ids
// for any additional points (ie, mesh cell-centres) // for any additional points (ie, mesh cell-centres)
vtkSmartPointer<vtkPoints> vtkpoints = vtkmesh->GetPoints(); vtkmesh->SetPoints(movePoints(mesh, vtuData));
if (!vtkpoints)
{
// No points previously, add an entry
vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkmesh->SetPoints(vtkpoints);
}
vtkpoints->SetNumberOfPoints(sizing.nFieldPoints());
// Normal points
const pointField& points = mesh.points();
const labelList& addPoints = vtuData.additionalIds();
label pointi = 0;
forAll(points, i)
{
vtkpoints->SetPoint(pointi++, points[i].v_);
}
forAll(addPoints, i)
{
vtkpoints->SetPoint(pointi++, mesh.C()[addPoints[i]].v_);
}
if (facesUL.size()) if (facesUL.size())
{ {
@ -177,4 +217,48 @@ vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKMesh
} }
vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKSubsetMesh
(
const fvMeshSubset& subsetter,
foamVtuData& vtuData,
const bool decompPoly
)
{
vtkSmartPointer<vtkUnstructuredGrid> vtkmesh = volumeVTKMesh
(
subsetter.subMesh(),
vtuData,
decompPoly
);
// Convert cellMap, addPointCellLabels to global cell ids
vtuData.renumberCells(subsetter.cellMap());
// Copy pointMap as well, otherwise pointFields fail
vtuData.pointMap() = subsetter.pointMap();
return vtkmesh;
}
vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKMesh
(
const fvMesh& mesh,
foamVtuData& vtuData
) const
{
return volumeVTKMesh(mesh, vtuData, this->decomposePoly_);
}
vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKSubsetMesh
(
const fvMeshSubset& subsetter,
foamVtuData& vtuData
) const
{
return volumeVTKSubsetMesh(subsetter, vtuData, this->decomposePoly_);
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -28,6 +28,7 @@ License
// OpenFOAM includes // OpenFOAM includes
#include "polyPatch.H" #include "polyPatch.H"
#include "primitivePatch.H" #include "primitivePatch.H"
#include "foamVtkAdaptors.H"
// VTK includes // VTK includes
#include "vtkCellArray.h" #include "vtkCellArray.h"
@ -35,38 +36,36 @@ License
#include "vtkPolyData.h" #include "vtkPolyData.h"
#include "vtkSmartPointer.h" #include "vtkSmartPointer.h"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class PatchType> template<class PatchType>
vtkSmartPointer<vtkPolyData> Foam::vtkPVFoam::patchVTKMesh vtkSmartPointer<vtkPoints> Foam::vtkPVFoam::movePatchPoints
( (
const string& name,
const PatchType& p const PatchType& p
) )
{ {
vtkSmartPointer<vtkPolyData> vtkmesh =
vtkSmartPointer<vtkPolyData>::New();
if (debug)
{
Info<< "<beg> patchVTKMesh - " << name << endl;
printMemory();
}
// Convert OpenFOAM mesh vertices to VTK // Convert OpenFOAM mesh vertices to VTK
const Foam::pointField& points = p.localPoints(); const pointField& points = p.localPoints();
vtkSmartPointer<vtkPoints> vtkpoints = auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPoints>::New();
vtkpoints->SetNumberOfPoints(points.size()); vtkpoints->SetNumberOfPoints(points.size());
forAll(points, i) forAll(points, i)
{ {
vtkpoints->SetPoint(i, points[i].v_); vtkpoints->SetPoint(i, points[i].v_);
} }
vtkmesh->SetPoints(vtkpoints);
// Add faces as polygons return vtkpoints;
}
template<class PatchType>
vtkSmartPointer<vtkCellArray> Foam::vtkPVFoam::patchFacesVTKCells
(
const PatchType& p
)
{
// Faces as polygons
const faceList& faces = p.localFaces(); const faceList& faces = p.localFaces();
label nAlloc = faces.size(); label nAlloc = faces.size();
@ -75,32 +74,45 @@ vtkSmartPointer<vtkPolyData> Foam::vtkPVFoam::patchVTKMesh
nAlloc += faces[facei].size(); nAlloc += faces[facei].size();
} }
vtkSmartPointer<vtkCellArray> vtkcells = auto cells = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkCellArray>::New();
vtkcells->Allocate(nAlloc); UList<vtkIdType> cellsUL =
// If reusing memory, ensure insert always starts from 0 vtkUList
vtkcells->Reset(); (
cells,
faces.size(),
nAlloc
);
// Cell connectivity for polygons
// [size, verts..., size, verts... ]
label idx = 0;
forAll(faces, facei) forAll(faces, facei)
{ {
const face& f = faces[facei]; const face& f = faces[facei];
vtkIdType nodeIds[f.size()];
cellsUL[idx++] = f.size();
forAll(f, fp) forAll(f, fp)
{ {
nodeIds[fp] = f[fp]; cellsUL[idx++] = f[fp];
} }
vtkcells->InsertNextCell(f.size(), nodeIds);
} }
vtkmesh->SetPolys(vtkcells); return cells;
}
if (debug)
{ template<class PatchType>
Info<< "<end> patchVTKMesh - " << name << endl; vtkSmartPointer<vtkPolyData> Foam::vtkPVFoam::patchVTKMesh
printMemory(); (
} const PatchType& p
)
{
auto vtkmesh = vtkSmartPointer<vtkPolyData>::New();
vtkmesh->SetPoints(movePatchPoints(p));
vtkmesh->SetPolys(patchFacesVTKCells(p));
return vtkmesh; return vtkmesh;
} }

View File

@ -163,7 +163,7 @@ void Foam::vtkPVFoam::updateInfoLagrangian
{ {
if (debug) if (debug)
{ {
Info<< "<beg> updateInfoLagrangian" << nl Info<< "<beg> " << FUNCTION_NAME << nl
<< " " << dbPtr_->timePath()/cloud::prefix << endl; << " " << dbPtr_->timePath()/cloud::prefix << endl;
} }
@ -194,7 +194,7 @@ void Foam::vtkPVFoam::updateInfoLagrangian
if (debug) if (debug)
{ {
Info<< "<end> updateInfoLagrangian" << endl; Info<< "<end> " << FUNCTION_NAME << endl;
} }
} }
@ -207,7 +207,7 @@ void Foam::vtkPVFoam::updateInfoPatches
{ {
if (debug) if (debug)
{ {
Info<< "<beg> updateInfoPatches" Info<< "<beg> " << FUNCTION_NAME
<< " [meshPtr=" << (meshPtr_ ? "set" : "null") << "]" << endl; << " [meshPtr=" << (meshPtr_ ? "set" : "null") << "]" << endl;
} }
@ -409,7 +409,7 @@ void Foam::vtkPVFoam::updateInfoPatches
if (debug) if (debug)
{ {
Info<< "<end> updateInfoPatches" << endl; Info<< "<end> " << FUNCTION_NAME << endl;
} }
} }
@ -591,7 +591,7 @@ void Foam::vtkPVFoam::updateInfoLagrangianFields
} }
// Preserve the enabled selections // Preserve the enabled selections
HashSet<string> enabledEntries = getSelectedArrayEntries(select); HashSet<string> enabled = getSelectedArraySet(select);
select->RemoveAllArrays(); select->RemoveAllArrays();
// TODO - currently only get fields from ONE cloud // TODO - currently only get fields from ONE cloud
@ -631,25 +631,7 @@ void Foam::vtkPVFoam::updateInfoLagrangianFields
addToSelection<IOField<tensor>>(select, objects); addToSelection<IOField<tensor>>(select, objects);
// Restore the enabled selections // Restore the enabled selections
setSelectedArrayEntries(select, enabledEntries); setSelectedArrayEntries(select, enabled);
if (debug > 1)
{
boolList status;
const label nElem = getSelected(status, select);
forAll(status, i)
{
Info<< " lagrangian[" << i << "] = "
<< status[i]
<< " : " << select->GetArrayName(i) << nl;
}
if (!nElem)
{
Info<< " lagrangian[none]" << nl;
}
}
if (debug) if (debug)
{ {

View File

@ -45,16 +45,16 @@ void Foam::vtkPVFoam::updateInfoFields
<< endl; << endl;
} }
HashSet<string> enabledEntries; HashSet<string> enabled;
if (!select->GetNumberOfArrays() && !meshPtr_) if (!select->GetNumberOfArrays() && !meshPtr_)
{ {
// enable 'p' and 'U' only on the first call // Enable 'p' and 'U' only on the first call
enabledEntries = { "p", "U" }; enabled = { "p", "U" };
} }
else else
{ {
// preserve the enabled selections // Preserve the enabled selections
enabledEntries = getSelectedArrayEntries(select); enabled = getSelectedArraySet(select);
} }
select->RemoveAllArrays(); select->RemoveAllArrays();
@ -127,7 +127,7 @@ void Foam::vtkPVFoam::updateInfoFields
// Restore the enabled selections // Restore the enabled selections
setSelectedArrayEntries(select, enabledEntries); setSelectedArrayEntries(select, enabled);
if (debug) if (debug)
{ {

View File

@ -40,6 +40,7 @@ License
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
// file-scope // file-scope
// Widget properties
static QWidget* setWidgetProperties static QWidget* setWidgetProperties
( (
QWidget* widget, QWidget* widget,
@ -67,6 +68,7 @@ static QWidget* setWidgetProperties
// file-scope // file-scope
// Button properties
static QAbstractButton* setButtonProperties static QAbstractButton* setButtonProperties
( (
QAbstractButton* b, QAbstractButton* b,

View File

@ -60,8 +60,7 @@ namespace Foam
const Foam::point& pt const Foam::point& pt
) )
{ {
vtkSmartPointer<vtkTextActor> txt = auto txt = vtkSmartPointer<vtkTextActor>::New();
vtkSmartPointer<vtkTextActor>::New();
txt->SetInput(s.c_str()); txt->SetInput(s.c_str());
@ -310,8 +309,8 @@ void Foam::vtkPVblockMesh::updateInfo()
HashSet<string> enabledEdges; HashSet<string> enabledEdges;
if (!firstTime) if (!firstTime)
{ {
enabledParts = getSelectedArrayEntries(blockSelection); enabledParts = getSelectedArraySet(blockSelection);
enabledEdges = getSelectedArrayEntries(edgeSelection); enabledEdges = getSelectedArraySet(edgeSelection);
} }
// Clear current mesh parts list // Clear current mesh parts list
@ -407,14 +406,6 @@ void Foam::vtkPVblockMesh::Update
{ {
reader_->UpdateProgress(0.1); reader_->UpdateProgress(0.1);
// Set up mesh parts selection(s)
getSelected(blockStatus_, reader_->GetBlockSelection());
// Set up curved edges selection(s)
getSelected(edgeStatus_, reader_->GetCurvedEdgesSelection());
reader_->UpdateProgress(0.2);
// Update the OpenFOAM mesh // Update the OpenFOAM mesh
updateFoamMesh(); updateFoamMesh();
reader_->UpdateProgress(0.5); reader_->UpdateProgress(0.5);
@ -427,7 +418,6 @@ void Foam::vtkPVblockMesh::Update
convertMeshEdges(output, blockNo); convertMeshEdges(output, blockNo);
reader_->UpdateProgress(0.8); reader_->UpdateProgress(0.8);
} }

View File

@ -25,13 +25,18 @@ Class
Foam::vtkPVblockMesh Foam::vtkPVblockMesh
Description Description
Provides a reader interface for OpenFOAM blockMesh to VTK interaction The backend for the vtkPVblockMeshReader reader module -
providing a paraview reader interface for OpenFOAM blockMesh.
The block reader module can assist when creating a blockMeshDict
for use with the blockMesh utility. As well as blocks, it can be
used to visualize edges,corners and patch names.
There is no native VTK equivalent for this functionality.
SourceFiles SourceFiles
vtkPVblockMesh.C vtkPVblockMesh.C
vtkPVblockMeshConvert.C vtkPVblockMeshConvert.C
vtkPVblockMeshUpdate.C
vtkPVblockMeshUtils.C
// Needed by VTK: // Needed by VTK:
vtkDataArrayTemplateImplicit.txx vtkDataArrayTemplateImplicit.txx
@ -95,12 +100,6 @@ class vtkPVblockMesh
//- The mesh directory for the region //- The mesh directory for the region
fileName meshDir_; fileName meshDir_;
//- Selected geometrical parts
boolList blockStatus_;
//- Selected curved edges
boolList edgeStatus_;
//- First instance and size of bleckMesh blocks //- First instance and size of bleckMesh blocks
// used to index into blockStatus_ // used to index into blockStatus_
arrayRange rangeBlocks_; arrayRange rangeBlocks_;

View File

@ -53,7 +53,11 @@ void Foam::vtkPVblockMesh::convertMeshBlocks
Info<< "<beg> convertMeshBlocks" << endl; Info<< "<beg> convertMeshBlocks" << endl;
} }
vtkDataArraySelection* selection = reader_->GetBlockSelection(); const Map<string> blockStatus = getSelectedArrayMap
(
reader_->GetBlockSelection()
);
arrayRange& range = rangeBlocks_; arrayRange& range = rangeBlocks_;
range.block(blockNo); // set output block range.block(blockNo); // set output block
label datasetNo = 0; // restart at dataset 0 label datasetNo = 0; // restart at dataset 0
@ -61,29 +65,23 @@ void Foam::vtkPVblockMesh::convertMeshBlocks
const blockMesh& blkMesh = *meshPtr_; const blockMesh& blkMesh = *meshPtr_;
const pointField blkPoints(blkMesh.vertices() * blkMesh.scaleFactor()); const pointField blkPoints(blkMesh.vertices() * blkMesh.scaleFactor());
int blockI = 0; vtkIdType nodeIds[8]; // Space for VTK_HEXAHEDRON vertices
for int blockId = -1;
( for (auto partId : range)
auto iter = range.cbegin();
iter != range.cend();
++iter, ++blockI
)
{ {
const auto partId = *iter; ++blockId; // Increment first
if (!blockStatus_[partId]) if (!blockStatus.found(partId))
{ {
continue; continue;
} }
const auto& longName = blockStatus[partId];
const blockDescriptor& blockDef = blkMesh[blockI]; const blockDescriptor& blockDef = blkMesh[blockId];
const labelList& blockLabels = blockDef.blockShape(); const labelList& blockLabels = blockDef.blockShape();
vtkSmartPointer<vtkPoints> vtkpoints = auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPoints>::New();
vtkpoints->SetNumberOfPoints(blockLabels.size()); vtkpoints->SetNumberOfPoints(blockLabels.size());
vtkIdType nodeIds[8];
forAll(blockLabels, pointi) forAll(blockLabels, pointi)
{ {
vtkpoints->SetPoint vtkpoints->SetPoint
@ -94,8 +92,7 @@ void Foam::vtkPVblockMesh::convertMeshBlocks
nodeIds[pointi] = pointi; nodeIds[pointi] = pointi;
} }
vtkSmartPointer<vtkUnstructuredGrid> vtkmesh = auto vtkmesh = vtkSmartPointer<vtkUnstructuredGrid>::New();
vtkSmartPointer<vtkUnstructuredGrid>::New();
vtkmesh->Allocate(1); vtkmesh->Allocate(1);
vtkmesh->InsertNextCell vtkmesh->InsertNextCell
@ -107,11 +104,7 @@ void Foam::vtkPVblockMesh::convertMeshBlocks
vtkmesh->SetPoints(vtkpoints); vtkmesh->SetPoints(vtkpoints);
addToBlock addToBlock(output, vtkmesh, range, datasetNo, longName);
(
output, vtkmesh, range, datasetNo,
selection->GetArrayName(partId)
);
++datasetNo; ++datasetNo;
} }
@ -135,7 +128,11 @@ void Foam::vtkPVblockMesh::convertMeshEdges
int& blockNo int& blockNo
) )
{ {
vtkDataArraySelection* selection = reader_->GetCurvedEdgesSelection(); const Map<string> edgeStatus = getSelectedArrayMap
(
reader_->GetCurvedEdgesSelection()
);
arrayRange& range = rangeEdges_; arrayRange& range = rangeEdges_;
range.block(blockNo); // set output block range.block(blockNo); // set output block
@ -145,24 +142,20 @@ void Foam::vtkPVblockMesh::convertMeshEdges
const blockEdgeList& edges = blkMesh.edges(); const blockEdgeList& edges = blkMesh.edges();
const scalar scaleFactor = blkMesh.scaleFactor(); const scalar scaleFactor = blkMesh.scaleFactor();
int edgeI = 0; int edgeId = -1;
for for (auto partId : range)
(
auto iter = range.cbegin();
iter != range.cend();
++iter, ++edgeI
)
{ {
const auto partId = *iter; ++edgeId; // Increment first
if (!edgeStatus_[partId]) if (!edgeStatus.found(partId))
{ {
continue; continue;
} }
const auto& longName = edgeStatus[partId];
// search each block // Search each block
forAll(blkMesh, blockI) forAll(blkMesh, blockId)
{ {
const blockDescriptor& blockDef = blkMesh[blockI]; const blockDescriptor& blockDef = blkMesh[blockId];
edgeList blkEdges = blockDef.blockShape().edges(); edgeList blkEdges = blockDef.blockShape().edges();
@ -175,7 +168,7 @@ void Foam::vtkPVblockMesh::convertMeshEdges
label foundEdgeI = -1; label foundEdgeI = -1;
forAll(blkEdges, blkEdgeI) forAll(blkEdges, blkEdgeI)
{ {
if (edges[edgeI].compare(blkEdges[blkEdgeI])) if (edges[edgeId].compare(blkEdges[blkEdgeI]))
{ {
foundEdgeI = blkEdgeI; foundEdgeI = blkEdgeI;
break; break;
@ -186,9 +179,7 @@ void Foam::vtkPVblockMesh::convertMeshEdges
{ {
const List<point>& edgePoints = edgesPoints[foundEdgeI]; const List<point>& edgePoints = edgesPoints[foundEdgeI];
vtkSmartPointer<vtkPoints> vtkpoints = auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPoints>::New();
vtkpoints->SetNumberOfPoints(edgePoints.size()); vtkpoints->SetNumberOfPoints(edgePoints.size());
vtkIdType pointIds[edgePoints.size()]; vtkIdType pointIds[edgePoints.size()];
@ -200,8 +191,7 @@ void Foam::vtkPVblockMesh::convertMeshEdges
pointIds[pointi] = pointi; pointIds[pointi] = pointi;
} }
vtkSmartPointer<vtkPolyData> vtkmesh = auto vtkmesh = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkPolyData>::New();
vtkmesh->Allocate(1); vtkmesh->Allocate(1);
vtkmesh->InsertNextCell vtkmesh->InsertNextCell
@ -213,11 +203,7 @@ void Foam::vtkPVblockMesh::convertMeshEdges
vtkmesh->SetPoints(vtkpoints); vtkmesh->SetPoints(vtkpoints);
addToBlock addToBlock(output, vtkmesh, range, datasetNo, longName);
(
output, vtkmesh, range, datasetNo,
selection->GetArrayName(partId)
);
++datasetNo; ++datasetNo;
break; break;
@ -253,35 +239,23 @@ void Foam::vtkPVblockMesh::convertMeshCorners
if (debug) if (debug)
{ {
Info<< "<beg> convertMeshCorners" << endl; Info<< "<beg> " << FUNCTION_NAME << endl;
} }
if (true) // or some flag or other condition if (true) // Or some flag or other condition
{ {
vtkSmartPointer<vtkPolyData> vtkmesh = auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkPoints> vtkpoints =
vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkcells =
vtkSmartPointer<vtkCellArray>::New();
vtkpoints->SetNumberOfPoints(blkPoints.size()); vtkpoints->SetNumberOfPoints(blkPoints.size());
vtkcells->Allocate(2*blkPoints.size());
// If reusing memory, ensure insert always starts from 0
vtkcells->Reset();
vtkIdType pointId = 0;
forAll(blkPoints, pointi) forAll(blkPoints, pointi)
{ {
vtkpoints->SetPoint(pointi, blkPoints[pointi].v_); vtkpoints->SetPoint(pointi, blkPoints[pointi].v_);
vtkcells->InsertNextCell(1, &pointId); // VTK_VERTEX
pointId++;
} }
auto vtkmesh = vtkSmartPointer<vtkPolyData>::New();
vtkmesh->SetPoints(vtkpoints); vtkmesh->SetPoints(vtkpoints);
vtkmesh->SetVerts(vtkcells); vtkmesh->SetVerts(foamPvCore::identityVertices(blkPoints.size()));
addToBlock(output, vtkmesh, range, datasetNo, range.name()); addToBlock(output, vtkmesh, range, datasetNo, range.name());
++datasetNo; ++datasetNo;
@ -295,7 +269,7 @@ void Foam::vtkPVblockMesh::convertMeshCorners
if (debug) if (debug)
{ {
Info<< "<end> convertMeshCorners" << endl; Info<< "<end> " << FUNCTION_NAME << endl;
} }
} }

View File

@ -34,6 +34,8 @@ License
#include "vtkInformation.h" #include "vtkInformation.h"
#include "vtkSmartPointer.h" #include "vtkSmartPointer.h"
#include "foamVtkAdaptors.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam namespace Foam
@ -82,7 +84,7 @@ void Foam::foamPvCore::addToBlock
block->SetBlock(datasetNo, dataset); block->SetBlock(datasetNo, dataset);
// name the output block when assigning dataset 0 // Name the output block when assigning dataset 0
if (datasetNo == 0) if (datasetNo == 0)
{ {
output->GetMetaData(blockNo)->Set output->GetMetaData(blockNo)->Set
@ -103,34 +105,6 @@ void Foam::foamPvCore::addToBlock
} }
int Foam::foamPvCore::getSelected
(
boolList& status,
vtkDataArraySelection* selection
)
{
const int n = selection->GetNumberOfArrays();
if (status.size() != n)
{
status.setSize(n);
status = false;
}
int count = 0;
forAll(status, i)
{
const bool setting = selection->GetArraySetting(i);
if (setting)
{
++count;
}
status[i] = setting;
}
return count;
}
Foam::hashedWordList Foam::foamPvCore::getSelected Foam::hashedWordList Foam::foamPvCore::getSelected
( (
vtkDataArraySelection* select vtkDataArraySelection* select
@ -173,54 +147,15 @@ Foam::hashedWordList Foam::foamPvCore::getSelected
Foam::HashSet<Foam::string> Foam::HashSet<Foam::string>
Foam::foamPvCore::getSelectedArrayEntries Foam::foamPvCore::getSelectedArraySet
( (
vtkDataArraySelection* select vtkDataArraySelection* select
) )
{
const int n = select->GetNumberOfArrays();
HashSet<string> selections(2*n);
for (int i=0; i < n; ++i)
{
if (select->GetArraySetting(i))
{
selections.insert(select->GetArrayName(i));
}
}
if (debug > 1)
{
const int n = select->GetNumberOfArrays();
Info<< "available(";
for (int i=0; i < n; ++i)
{
Info<< " \"" << select->GetArrayName(i) << "\"";
}
Info<< " )\nselected(";
for (auto k : selections)
{
Info<< " " << k;
}
Info<< " )\n";
}
return selections;
}
Foam::HashSet<Foam::string>
Foam::foamPvCore::getSelectedArrayEntries
(
vtkDataArraySelection* select,
const arrayRange& slice
)
{ {
const int n = select->GetNumberOfArrays(); const int n = select->GetNumberOfArrays();
HashSet<string> enabled(2*n); HashSet<string> enabled(2*n);
for (auto i : slice) for (int i=0; i < n; ++i)
{ {
if (select->GetArraySetting(i)) if (select->GetArraySetting(i))
{ {
@ -230,8 +165,9 @@ Foam::foamPvCore::getSelectedArrayEntries
if (debug > 1) if (debug > 1)
{ {
const int n = select->GetNumberOfArrays();
Info<< "available("; Info<< "available(";
for (auto i : slice) for (int i=0; i < n; ++i)
{ {
Info<< " \"" << select->GetArrayName(i) << "\""; Info<< " \"" << select->GetArrayName(i) << "\"";
} }
@ -248,25 +184,24 @@ Foam::foamPvCore::getSelectedArrayEntries
} }
void Foam::foamPvCore::setSelectedArrayEntries Foam::Map<Foam::string>
Foam::foamPvCore::getSelectedArrayMap
( (
vtkDataArraySelection* select, vtkDataArraySelection* select
const HashSet<string>& enabled
) )
{ {
const int n = select->GetNumberOfArrays(); const int n = select->GetNumberOfArrays();
// disable everything not explicitly enabled Map<string> enabled(2*n);
select->DisableAllArrays();
// Loop through entries, enabling as required
for (int i=0; i < n; ++i) for (int i=0; i < n; ++i)
{ {
const char* arrayName = select->GetArrayName(i); if (select->GetArraySetting(i))
if (enabled.found(arrayName))
{ {
select->EnableArray(arrayName); enabled.insert(i, select->GetArrayName(i));
} }
} }
return enabled;
} }
@ -312,4 +247,29 @@ void Foam::foamPvCore::printMemory()
} }
vtkSmartPointer<vtkCellArray> Foam::foamPvCore::identityVertices
(
const label size
)
{
// VTK_VERTEX
auto cells = vtkSmartPointer<vtkCellArray>::New();
UList<vtkIdType> cellsUL = vtkUList(cells, size, 2*size);
// Cell connectivity for vertex
// [size, ids.., size, ids...]
// which means
// [1, id, 1, id, ...]
label idx = 0;
for (label id=0; id < size; ++id)
{
cellsUL[idx++] = 1;
cellsUL[idx++] = id;
}
return cells;
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -40,17 +40,19 @@ SourceFiles
#include "wordList.H" #include "wordList.H"
#include "Hash.H" #include "Hash.H"
#include "HashSet.H" #include "HashSet.H"
#include "Map.H"
#include "hashedWordList.H" #include "hashedWordList.H"
#include "labelRange.H" #include "labelRange.H"
#include "vtkPoints.h"
// * * * * * * * * * * * * * Forward Declarations * * * * * * * * * * * * * // // * * * * * * * * * * * * * Forward Declarations * * * * * * * * * * * * * //
class vtkCellArray;
class vtkDataArraySelection; class vtkDataArraySelection;
class vtkDataSet; class vtkDataSet;
class vtkMultiBlockDataSet;
class vtkIndent; class vtkIndent;
class vtkMultiBlockDataSet;
class vtkPoints;
template<class T> class vtkSmartPointer;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -168,13 +170,6 @@ public:
); );
//- Retrieve the current selections into a boolList
static int getSelected
(
boolList& lst,
vtkDataArraySelection* select
);
//- Retrieve the current selections as a hashedWordList, //- Retrieve the current selections as a hashedWordList,
// while stripping off any prefix or suffix // while stripping off any prefix or suffix
static hashedWordList getSelected static hashedWordList getSelected
@ -192,25 +187,24 @@ public:
); );
//- Retrieve the currently enabled selections //- Retrieve the currently enabled selections as hashset
static HashSet<string> getSelectedArrayEntries static HashSet<string> getSelectedArraySet
( (
vtkDataArraySelection* select vtkDataArraySelection* select
); );
//- Retrieve a sub-list of the currently enabled selections //- Retrieve the currently enabled selections as id/name map
static HashSet<string> getSelectedArrayEntries static Map<string> getSelectedArrayMap
( (
vtkDataArraySelection* select, vtkDataArraySelection* select
const arrayRange& slice
); );
//- Enable the selection(s) //- Enable the selection(s)
template<class AnyValue, class AnyHasher>
static void setSelectedArrayEntries static void setSelectedArrayEntries
( (
vtkDataArraySelection* select, vtkDataArraySelection* select,
const HashSet<string>& enabled const HashTable<AnyValue, string, AnyHasher>& enabled
); );
@ -222,6 +216,13 @@ public:
static void printMemory(); static void printMemory();
//- Return an identity list of VTK_VERTEX
static vtkSmartPointer<vtkCellArray> identityVertices
(
const label size
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
}; // End class foamPvCore }; // End class foamPvCore

View File

@ -54,4 +54,27 @@ Foam::label Foam::foamPvCore::addToSelection
} }
template<class AnyValue, class AnyHasher>
void Foam::foamPvCore::setSelectedArrayEntries
(
vtkDataArraySelection* select,
const HashTable<AnyValue, string, AnyHasher>& enabled
)
{
const int n = select->GetNumberOfArrays();
// disable everything not explicitly enabled
select->DisableAllArrays();
// Loop through entries, enabling as required
for (int i=0; i < n; ++i)
{
const char* arrayName = select->GetArrayName(i);
if (enabled.found(arrayName))
{
select->EnableArray(arrayName);
}
}
}
// ************************************************************************* // // ************************************************************************* //