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

View File

@ -26,6 +26,7 @@ License
#include "pqFoamReaderControls.h"
#include <QCheckBox>
#include <QComboBox>
#include <QFrame>
#include <QGridLayout>
#include <QPushButton>
@ -42,6 +43,17 @@ License
// * * * * * * * * * * * * * 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
// Widget properties
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
(
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")),
includeSets_(lookupIntProp(group, "IncludeSets")),
includeZones_(lookupIntProp(group, "IncludeZones")),
cacheMesh_(lookupIntProp(group, "CacheMesh"))
meshCaching_(lookupIntProp(group, "MeshCaching"))
{
typedef vtkSMIntVectorProperty intProp;
QGridLayout* form = new QGridLayout(this);
const int nCols = 3;
// ROW
// ~~~
int row = 0;
@ -243,13 +317,7 @@ pqFoamReaderControls::pqFoamReaderControls
}
// LINE
// ~~~~
++row;
{
QFrame* hline = new QFrame(this);
hline->setFrameStyle(QFrame::HLine | QFrame::Sunken);
form->addWidget(hline, row, 0, 1, 4);
}
addHline(form, ++row, nCols);
// ROW
// ~~~
@ -321,13 +389,7 @@ pqFoamReaderControls::pqFoamReaderControls
}
// LINE
// ~~~~
++row;
{
QFrame* hline = new QFrame(this);
hline->setFrameStyle(QFrame::HLine | QFrame::Sunken);
form->addWidget(hline, row, 0, 1, 4);
}
addHline(form, ++row, nCols);
// ROW
// ~~~
@ -360,13 +422,7 @@ pqFoamReaderControls::pqFoamReaderControls
}
// LINE
// ~~~~
++row;
{
QFrame* hline = new QFrame(this);
hline->setFrameStyle(QFrame::HLine | QFrame::Sunken);
form->addWidget(hline, row, 0, 1, 4);
}
addHline(form, ++row, nCols);
// ROW
// ~~~
@ -398,14 +454,22 @@ pqFoamReaderControls::pqFoamReaderControls
);
}
if (cacheMesh_)
if (meshCaching_)
{
QCheckBox* b = new QCheckBox(this);
setButtonProperties(b, cacheMesh_);
QComboBox* b = new QComboBox(this);
form->addWidget(b, row, 2, Qt::AlignLeft);
setWidgetProperties(b, meshCaching_);
setComboBoxContent(b, meshCaching_);
addPropertyLink
(
b, "indexChanged", SIGNAL(currentIndexChanged(int)), meshCaching_
);
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)
vtkSMIntVectorProperty* includeZones_;
//- CacheMesh (bool property)
vtkSMIntVectorProperty* cacheMesh_;
//- MeshCaching (enum property)
vtkSMIntVectorProperty* meshCaching_;
// Private Member Functions
@ -102,7 +102,7 @@ protected slots:
// Protected Member Functions
void refreshPressed();
void cacheMesh(bool checked);
void cacheMesh(int idx);
void showPatchNames(bool checked);
void showGroupsOnly(bool checked);
void includeSets(bool checked);

View File

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

View File

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

View File

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

View File

@ -25,7 +25,25 @@ Class
Foam::vtkPVFoam
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
vtkPVFoam.C
@ -56,22 +74,22 @@ SourceFiles
#include "foamPvCore.H"
#include "foamVtkMeshMaps.H"
#include "vtkSmartPointer.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkSmartPointer.h"
#include "vtkUnstructuredGrid.h"
// * * * * * * * * * * * * * Forward Declarations * * * * * * * * * * * * * //
class vtkCellArray;
class vtkDataArraySelection;
class vtkDataSet;
class vtkFloatArray;
class vtkPoints;
class vtkIndent;
class vtkMultiBlockDataSet;
class vtkPVFoamReader;
class vtkRenderer;
class vtkTextActor;
class vtkMultiBlockDataSet;
class vtkIndent;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -104,20 +122,99 @@ class vtkPVFoam
// Private classes
//- Bookkeeping for vtkPolyData
class foamVtpData
//- Bookkeeping for internal caching.
// 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:
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
class foamVtuData : public foamVtkMeshMaps
{
public:
vtkSmartPointer<vtkUnstructuredGrid> vtkmesh;
};
class foamVtuData
:
public foamVtkCaching<vtkUnstructuredGrid>,
public foamVtkMeshMaps
{};
// Private Data
@ -140,12 +237,12 @@ class vtkPVFoam
//- The time index
int timeIndex_;
//- Previous/current decomposition request
bool decomposePoly_;
//- Track changes in mesh geometry
enum polyMesh::readUpdateState meshState_;
//- Track changes in fields
bool fieldsChanged_;
//- The index of selected parts mapped to their names
Map<string> selectedPartIds_;
@ -232,75 +329,143 @@ class vtkPVFoam
// Mesh conversion functions
//- Convert volume mesh
//- Convert InternalMesh
void convertMeshVolume();
//- Convert Lagrangian points
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();
//- Convert subsetted mesh
void convertMeshSubset
(
const fvMeshSubset& subsetter,
const string& longName
);
//- Convert cell zones
void convertMeshCellZones();
//- Convert face zones
void convertMeshFaceZones();
//- Convert point zones
void convertMeshPointZones();
//- Convert cell sets
void convertMeshCellSets();
//- Convert face zones
void convertMeshFaceZones();
//- Convert face sets
// The cellMap (cached data) contains the face-labels.
void convertMeshFaceSets();
//- Convert point zones
// The pointMap (cached data) contains the point-labels.
void convertMeshPointZones();
//- Convert point sets
// The pointMap (cached data) contains the point-labels.
void convertMeshPointSets();
// 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
(
const fvMesh& mesh,
foamVtuData& vtuData
);
) const;
//- Subsetted mesh as vtkUnstructuredGrid
vtkSmartPointer<vtkUnstructuredGrid> volumeVTKSubsetMesh
(
const fvMeshSubset& subsetter,
foamVtuData& vtuData
) const;
//- Lagrangian positions as vtkPolyData
vtkSmartPointer<vtkPolyData> lagrangianVTKMesh
(
const polyMesh& mesh,
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
template<class PatchType>
vtkSmartPointer<vtkPolyData> patchVTKMesh
static vtkSmartPointer<vtkPolyData> patchVTKMesh
(
const string& name,
const PatchType& p
);
// 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>
vtkSmartPointer<vtkFloatArray> convertFieldToVTK
(
const word& name,
const Field<Type>& fld
);
const UList<Type>& fld
) const;
//- Face set/zone field
template<class Type>
@ -308,7 +473,7 @@ class vtkPVFoam
(
const GeometricField<Type, fvPatchField, volMesh>& fld,
const labelUList& faceLabels
);
) const;
//- Volume field
template<class Type>
@ -316,7 +481,7 @@ class vtkPVFoam
(
const GeometricField<Type, fvPatchField, volMesh>& fld,
const foamVtuData& vtuData
);
) const;
//- Convert volume fields
@ -392,9 +557,8 @@ class vtkPVFoam
//- Point field
template<class Type>
void convertPointField
vtkSmartPointer<vtkFloatArray> convertPointField
(
vtkUnstructuredGrid* vtkmesh,
const GeometricField<Type, pointPatchField, pointMesh>& pfld,
const GeometricField<Type, fvPatchField, volMesh>& vfld,
const foamVtuData& vtuData
@ -403,17 +567,6 @@ class vtkPVFoam
// 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
word getReaderPartName(const int partId) const;

View File

@ -30,6 +30,7 @@ InClass
#define vtkPVFoamFieldTemplates_C
// OpenFOAM includes
#include "error.H"
#include "emptyFvPatchField.H"
#include "wallPolyPatch.H"
#include "faceSet.H"
@ -81,34 +82,51 @@ void Foam::vtkPVFoam::convertVolField
convertVolFieldBlock(fld, ptfPtr, rangeCellZones_); // cellZones
convertVolFieldBlock(fld, ptfPtr, rangeCellSets_); // cellSets
// Patches - skip field conversion for groups
// Patches - currently skip field conversion for groups
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)
|| selectedPartIds_[partId].startsWith("group/")
)
fld.name(),
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 word patchName = getPartName(partId);
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
@ -128,48 +146,42 @@ void Foam::vtkPVFoam::convertVolField
fvPatchField<Type>(p, fld).patchInternalField()
);
vtkSmartPointer<vtkFloatArray> cdata =
convertFieldToVTK
(
fld.name(),
tpptf()
);
vtkmesh->GetCellData()->AddArray(cdata);
coffset += transcribeFloatData(cdata, tpptf(), coffset);
if (patchId < patchInterpList.size())
if (allowPdata && patchId < patchInterpList.size())
{
vtkSmartPointer<vtkFloatArray> pdata = convertFieldToVTK
pdata = convertFieldToVTK
(
fld.name(),
patchInterpList[patchId].faceToPointInterpolate(tpptf)()
);
vtkmesh->GetPointData()->AddArray(pdata);
}
}
else
{
vtkSmartPointer<vtkFloatArray> cdata =
convertFieldToVTK
(
fld.name(),
ptf
);
vtkmesh->GetCellData()->AddArray(cdata);
coffset += transcribeFloatData(cdata, ptf, coffset);
if (patchId < patchInterpList.size())
if (allowPdata && patchId < patchInterpList.size())
{
vtkSmartPointer<vtkFloatArray> pdata = convertFieldToVTK
pdata = convertFieldToVTK
(
fld.name(),
patchInterpList[patchId].faceToPointInterpolate(ptf)()
);
vtkmesh->GetPointData()->AddArray(pdata);
}
}
}
if (cdata)
{
dataset->GetCellData()->AddArray(cdata);
}
if (pdata)
{
dataset->GetPointData()->AddArray(pdata);
}
}
// Face Zones
for (auto partId : rangeFaceZones_)
@ -178,15 +190,18 @@ void Foam::vtkPVFoam::convertVolField
{
continue;
}
const auto& longName = selectedPartIds_[partId];
const word zoneName = getFoamName(longName);
auto iter = cachedVtu_.find(selectedPartIds_[partId]);
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;
}
auto vtkmesh = (*iter).vtkmesh;
foamVtpData& vtpData = iter.object();
auto dataset = vtpData.dataset;
const word zoneName = getPartName(partId);
const faceZoneMesh& zMesh = mesh.faceZones();
const label zoneId = zMesh.findZoneID(zoneName);
@ -195,15 +210,16 @@ void Foam::vtkPVFoam::convertVolField
continue;
}
vtkSmartPointer<vtkFloatArray> cdata = convertFaceFieldToVTK
vtkSmartPointer<vtkFloatArray> cdata =
convertFaceFieldToVTK
(
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;
}
const auto& longName = selectedPartIds_[partId];
const word selectName = getFoamName(longName);
auto iter = cachedVtu_.find(selectedPartIds_[partId]);
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;
}
auto vtkmesh = (*iter).vtkmesh;
const word selectName = getPartName(partId);
const faceSet fSet(mesh, selectName);
foamVtpData& vtpData = iter.object();
auto dataset = vtpData.dataset;
vtkSmartPointer<vtkFloatArray> cdata = convertFaceFieldToVTK
(
fld,
fSet.sortedToc()
vtpData.cellMap()
);
vtkmesh->GetCellData()->AddArray(cdata);
dataset->GetCellData()->AddArray(cdata);
// TODO: points
// TODO: point data
}
}
@ -246,28 +263,22 @@ void Foam::vtkPVFoam::convertVolFields
const IOobjectList& objects
)
{
typedef GeometricField<Type, fvPatchField, volMesh> FieldType;
forAllConstIters(objects, iter)
{
// Restrict to GeometricField<Type, ...>
if
(
iter()->headerClassName()
!= GeometricField<Type, fvPatchField, volMesh>::typeName
)
{
continue;
}
const auto& ioobj = *(iter.object());
if (ioobj.headerClassName() == FieldType::typeName)
{
// Load field
GeometricField<Type, fvPatchField, volMesh> fld
(
*iter(),
mesh
);
FieldType fld(ioobj, mesh);
// Convert
convertVolField(patchInterpList, fld);
}
}
}
@ -279,22 +290,21 @@ void Foam::vtkPVFoam::convertDimFields
const IOobjectList& objects
)
{
typedef DimensionedField<Type, volMesh> FieldType;
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
forAllConstIters(objects, iter)
{
// Restrict to DimensionedField<Type, ...>
if
(
iter()->headerClassName()
!= DimensionedField<Type, volMesh>::typeName
)
const auto& ioobj = *(iter.object());
if (ioobj.headerClassName() != FieldType::typeName)
{
continue;
}
// Load field
DimensionedField<Type, volMesh> dimFld(*iter(), mesh);
FieldType dimFld(ioobj, mesh);
// Construct volField with zero-gradient patch fields
@ -345,25 +355,33 @@ void Foam::vtkPVFoam::convertVolFieldBlock
{
continue;
}
const auto& longName = selectedPartIds_[partId];
auto iter = cachedVtu_.find(selectedPartIds_[partId]);
if (!iter.found() || !(*iter).vtkmesh)
auto iter = cachedVtu_.find(longName);
if (!iter.found() || !iter.object().dataset)
{
// Should not happen, but for safety require a vtk geometry
continue;
}
auto vtuData = (*iter);
auto vtkmesh = (*iter).vtkmesh;
foamVtuData& vtuData = iter.object();
auto dataset = vtuData.dataset;
vtkSmartPointer<vtkFloatArray> cdata = convertVolFieldToVTK
(
fld,
vtuData
);
vtkmesh->GetCellData()->AddArray(cdata);
dataset->GetCellData()->AddArray(cdata);
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 polyBoundaryMesh& patches = mesh.boundaryMesh();
typedef GeometricField<Type, pointPatchField, pointMesh> FieldType;
forAllConstIters(objects, iter)
{
const word& fieldName = iter()->name();
// Restrict to this GeometricField<Type, ...>
if
(
iter()->headerClassName()
!= GeometricField<Type, pointPatchField, pointMesh>::typeName
)
const auto& ioobj = *(iter.object());
const word& fieldName = ioobj.name();
if (ioobj.headerClassName() != FieldType::typeName)
{
continue;
}
@ -402,15 +419,13 @@ void Foam::vtkPVFoam::convertPointFields
Info<< "convertPointFields : " << fieldName << endl;
}
GeometricField<Type, pointPatchField, pointMesh> pfld(*iter(), pMesh);
FieldType pfld(ioobj, pMesh);
convertPointFieldBlock(pfld, rangeVolume_); // internalMesh
convertPointFieldBlock(pfld, rangeCellZones_); // cellZones
convertPointFieldBlock(pfld, rangeCellSets_); // cellSets
// Patches)
// Patches - currently skip field conversion for groups
for (auto partId : rangePatches_)
{
if (!selectedPartIds_.found(partId))
@ -419,26 +434,22 @@ void Foam::vtkPVFoam::convertPointFields
}
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;
}
foamVtpData& vtpData = iter.object();
auto dataset = vtpData.dataset;
const word patchName = getPartName(partId);
const label patchId = patches.findPatchID(patchName);
if (patchId < 0)
const labelList& patchIds = vtpData.additionalIds();
if (patchIds.size() != 1)
{
continue;
}
auto iter = cachedVtp_.find(selectedPartIds_[partId]);
if (!iter.found() || !(*iter).vtkmesh)
{
continue;
}
auto vtkmesh = (*iter).vtkmesh;
const label patchId = patchIds[0];
vtkSmartPointer<vtkFloatArray> pdata = convertFieldToVTK
(
@ -446,27 +457,28 @@ void Foam::vtkPVFoam::convertPointFields
pfld.boundaryField()[patchId].patchInternalField()()
);
vtkmesh->GetPointData()->AddArray(pdata);
dataset->GetPointData()->AddArray(pdata);
}
//
// Convert (selected) faceZones
//
// Face Zones
for (auto partId : rangeFaceZones_)
{
if (!selectedPartIds_.found(partId))
{
continue;
}
const auto& longName = selectedPartIds_[partId];
const word zoneName = getFoamName(longName);
auto iter = cachedVtp_.find(selectedPartIds_[partId]);
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;
}
auto vtkmesh = (*iter).vtkmesh;
foamVtpData& vtpData = iter.object();
auto dataset = vtpData.dataset;
const word zoneName = getPartName(partId);
const label zoneId = mesh.faceZones().findZoneID(zoneName);
if (zoneId < 0)
@ -488,7 +500,7 @@ void Foam::vtkPVFoam::convertPointFields
znfld
);
vtkmesh->GetPointData()->AddArray(pdata);
dataset->GetPointData()->AddArray(pdata);
}
}
}
@ -507,63 +519,58 @@ void Foam::vtkPVFoam::convertPointFieldBlock
{
continue;
}
const auto& longName = selectedPartIds_[partId];
auto iter = cachedVtu_.find(selectedPartIds_[partId]);
if (!iter.found() || ! (*iter).vtkmesh)
auto iter = cachedVtu_.find(longName);
if (!iter.found() || !iter.object().dataset)
{
// Should not happen, but for safety require a vtk geometry
continue;
}
auto vtuData = (*iter);
auto vtkmesh = (*iter).vtkmesh;
foamVtuData& vtuData = iter.object();
auto dataset = vtuData.dataset;
convertPointField
vtkSmartPointer<vtkFloatArray> pdata = convertPointField
(
vtkmesh,
pfld,
GeometricField<Type, fvPatchField, volMesh>::null(),
vtuData
);
dataset->GetPointData()->AddArray(pdata);
}
}
template<class Type>
void Foam::vtkPVFoam::convertPointField
vtkSmartPointer<vtkFloatArray> Foam::vtkPVFoam::convertPointField
(
vtkUnstructuredGrid* vtkmesh,
const GeometricField<Type, pointPatchField, pointMesh>& pfld,
const GeometricField<Type, fvPatchField, volMesh>& vfld,
const foamVtuData& vtuData
)
{
if (!vtkmesh)
{
return;
}
const label nComp = pTraits<Type>::nComponents;
const int nComp(pTraits<Type>::nComponents);
const labelUList& addPointCellLabels = vtuData.additionalIds();
const labelUList& pointMap = vtuData.pointMap();
// Use a pointMap or address directly into mesh
const label nPoints = (pointMap.size() ? pointMap.size() : pfld.size());
vtkSmartPointer<vtkFloatArray> fldData =
vtkSmartPointer<vtkFloatArray>::New();
fldData->SetNumberOfComponents(nComp);
fldData->SetNumberOfTuples(nPoints + addPointCellLabels.size());
auto data = vtkSmartPointer<vtkFloatArray>::New();
data->SetNumberOfComponents(nComp);
data->SetNumberOfTuples(nPoints + addPointCellLabels.size());
// Note: using the name of the original volField
// 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
{
fldData->SetName(pfld.name().c_str());
data->SetName(pfld.name().c_str());
}
if (debug)
@ -589,7 +596,7 @@ void Foam::vtkPVFoam::convertPointField
}
foamPvFields::remapTuple<Type>(vec);
fldData->SetTuple(pointi++, vec);
data->SetTuple(pointi++, vec);
}
}
else
@ -603,13 +610,13 @@ void Foam::vtkPVFoam::convertPointField
}
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)
{
@ -620,7 +627,7 @@ void Foam::vtkPVFoam::convertPointField
}
foamPvFields::remapTuple<Type>(vec);
fldData->SetTuple(pointi++, vec);
data->SetTuple(pointi++, vec);
}
}
else
@ -634,11 +641,11 @@ void Foam::vtkPVFoam::convertPointField
}
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)
{
// restrict to this IOField<Type>
if (iter()->headerClassName() == IOField<Type>::typeName)
{
IOField<Type> fld(*iter());
// Restrict to IOField<Type>
const auto& ioobj = *(iter.object());
vtkSmartPointer<vtkFloatArray> fldData =
if (ioobj.headerClassName() == IOField<Type>::typeName)
{
IOField<Type> fld(ioobj);
vtkSmartPointer<vtkFloatArray> data =
convertFieldToVTK
(
fld.name(),
ioobj.name(),
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
//
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>
vtkSmartPointer<vtkFloatArray>
Foam::vtkPVFoam::convertFieldToVTK
(
const word& name,
const Field<Type>& fld
)
const UList<Type>& fld
) const
{
const int nComp(pTraits<Type>::nComponents);
if (debug)
{
Info<< "convert Field<" << pTraits<Type>::typeName << "> "
Info<< "convert UList<" << pTraits<Type>::typeName << "> "
<< name
<< " 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 =
vtkSmartPointer<vtkFloatArray>::New();
data->SetName(name.c_str());
data->SetNumberOfComponents(nComp);
data->SetNumberOfTuples(fld.size());
fldData->SetNumberOfComponents(nComp);
fldData->SetNumberOfTuples(fld.size());
fldData->SetName(name.c_str());
transcribeFloatData(data, fld);
float vec[nComp];
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;
return data;
}
@ -727,34 +809,32 @@ Foam::vtkPVFoam::convertFaceFieldToVTK
(
const GeometricField<Type, fvPatchField, volMesh>& fld,
const labelUList& faceLabels
)
) const
{
if (debug)
{
Info<< "convert face field: "
<< fld.name()
<< " size=" << faceLabels.size()
<< " nComp=" << label(pTraits<Type>::nComponents) << endl;
<< " nComp=" << int(pTraits<Type>::nComponents) << endl;
}
const fvMesh& mesh = fld.mesh();
const label nComp = pTraits<Type>::nComponents;
const int nComp(pTraits<Type>::nComponents);
const label nInternalFaces = mesh.nInternalFaces();
const labelList& faceOwner = mesh.faceOwner();
const labelList& faceNeigh = mesh.faceNeighbour();
vtkSmartPointer<vtkFloatArray> fldData =
vtkSmartPointer<vtkFloatArray>::New();
auto data = vtkSmartPointer<vtkFloatArray>::New();
data->SetName(fld.name().c_str());
data->SetNumberOfComponents(nComp);
data->SetNumberOfTuples(faceLabels.size());
fldData->SetNumberOfComponents(nComp);
fldData->SetNumberOfTuples(faceLabels.size());
fldData->SetName(fld.name().c_str());
float scratch[nComp];
float vec[nComp];
// for interior faces: average owner/neighbour
// for boundary faces: owner
// Interior faces: average owner/neighbour
// Boundary faces: the owner value
forAll(faceLabels, idx)
{
const label faceNo = faceLabels[idx];
@ -764,7 +844,7 @@ Foam::vtkPVFoam::convertFaceFieldToVTK
for (direction d=0; d<nComp; ++d)
{
vec[d] = component(t, d);
scratch[d] = component(t, d);
}
}
else
@ -772,15 +852,15 @@ Foam::vtkPVFoam::convertFaceFieldToVTK
const Type& t = fld[faceOwner[faceNo]];
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 foamVtuData& vtuData
)
) const
{
const label nComp = pTraits<Type>::nComponents;
const labelList& cellMap = vtuData.cellMap();
const int nComp(pTraits<Type>::nComponents);
const labelUList& cellMap = vtuData.cellMap();
vtkSmartPointer<vtkFloatArray> fldData =
vtkSmartPointer<vtkFloatArray>::New();
fldData->SetNumberOfComponents(nComp);
fldData->SetNumberOfTuples(cellMap.size());
fldData->SetName(fld.name().c_str());
auto data = vtkSmartPointer<vtkFloatArray>::New();
data->SetName(fld.name().c_str());
data->SetNumberOfComponents(nComp);
data->SetNumberOfTuples(cellMap.size());
if (debug)
{
@ -812,20 +890,20 @@ Foam::vtkPVFoam::convertVolFieldToVTK
<< ") nComp=" << nComp << endl;
}
float vec[nComp];
float scratch[nComp];
forAll(cellMap, idx)
{
const Type& t = fld[cellMap[idx]];
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 * * * * * * * * * * * * * //
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()
{
const fvMesh& mesh = *meshPtr_;
@ -80,7 +58,7 @@ void Foam::vtkPVFoam::convertVolFields()
// Get objects (fields) for this time - only keep selected fields
// the region name is already in the mesh db
IOobjectList objects(mesh, dbPtr_().timeName());
pruneObjectList(objects, selectedFields);
objects.filterKeys(selectedFields);
if (objects.empty())
{
@ -89,7 +67,7 @@ void Foam::vtkPVFoam::convertVolFields()
if (debug)
{
Info<< "<beg> convert volume fields" << endl;
Info<< "<beg> " << FUNCTION_NAME << endl;
forAllConstIters(objects, iter)
{
Info<< " " << iter()->name()
@ -132,7 +110,7 @@ void Foam::vtkPVFoam::convertVolFields()
if (debug)
{
Info<< "<end> convert volume fields" << endl;
Info<< "<end> " << FUNCTION_NAME << endl;
printMemory();
}
}
@ -159,7 +137,7 @@ void Foam::vtkPVFoam::convertPointFields()
// Get objects (fields) for this time - only keep selected fields
// the region name is already in the mesh db
IOobjectList objects(mesh, dbPtr_().timeName());
pruneObjectList(objects, selectedFields);
objects.filterKeys(selectedFields);
if (objects.empty())
{
@ -196,7 +174,7 @@ void Foam::vtkPVFoam::convertPointFields()
void Foam::vtkPVFoam::convertLagrangianFields()
{
arrayRange& range = rangeLagrangian_;
const arrayRange& range = rangeLagrangian_;
const fvMesh& mesh = *meshPtr_;
hashedWordList selectedFields = getSelected
@ -211,7 +189,7 @@ void Foam::vtkPVFoam::convertLagrangianFields()
if (debug)
{
Info<< "<beg> convert Lagrangian fields" << endl;
Info<< "<beg> " << FUNCTION_NAME << endl;
printMemory();
}
@ -222,14 +200,16 @@ void Foam::vtkPVFoam::convertLagrangianFields()
continue;
}
const word cloudName = getPartName(partId);
auto iter = cachedVtp_.find(selectedPartIds_[partId]);
const auto& longName = 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;
}
auto vtkmesh = (*iter).vtkmesh;
auto dataset = iter.object().dataset;
// Get the Lagrangian fields for this time and this cloud
// but only keep selected fields
@ -240,7 +220,7 @@ void Foam::vtkPVFoam::convertLagrangianFields()
dbPtr_().timeName(),
cloud::prefix/cloudName
);
pruneObjectList(objects, selectedFields);
objects.filterKeys(selectedFields);
if (objects.empty())
{
@ -257,17 +237,17 @@ void Foam::vtkPVFoam::convertLagrangianFields()
}
}
convertLagrangianFields<label>(objects, vtkmesh);
convertLagrangianFields<scalar>(objects, vtkmesh);
convertLagrangianFields<vector>(objects, vtkmesh);
convertLagrangianFields<sphericalTensor>(objects, vtkmesh);
convertLagrangianFields<symmTensor>(objects, vtkmesh);
convertLagrangianFields<tensor>(objects, vtkmesh);
convertLagrangianFields<label>(objects, dataset);
convertLagrangianFields<scalar>(objects, dataset);
convertLagrangianFields<vector>(objects, dataset);
convertLagrangianFields<sphericalTensor>(objects, dataset);
convertLagrangianFields<symmTensor>(objects, dataset);
convertLagrangianFields<tensor>(objects, dataset);
}
if (debug)
{
Info<< "<end> convert Lagrangian fields" << endl;
Info<< "<end> " << FUNCTION_NAME << endl;
printMemory();
}
}

View File

@ -44,7 +44,7 @@ License
void Foam::vtkPVFoam::convertMeshVolume()
{
arrayRange& range = rangeVolume_;
const arrayRange& range = rangeVolume_;
const fvMesh& mesh = *meshPtr_;
if (debug)
@ -60,15 +60,38 @@ void Foam::vtkPVFoam::convertMeshVolume()
if (selectedPartIds_.found(partId))
{
const auto& longName = selectedPartIds_[partId];
foamVtuData& vtuData = cachedVtu_(longName);
vtkSmartPointer<vtkUnstructuredGrid> vtkmesh =
volumeVTKMesh
(
mesh,
cachedVtu_(longName)
);
vtkSmartPointer<vtkUnstructuredGrid> vtkgeom;
if (vtuData.nPoints())
{
if (meshState_ == polyMesh::UNCHANGED)
{
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()
{
arrayRange& range = rangeLagrangian_;
const arrayRange& range = rangeLagrangian_;
const fvMesh& mesh = *meshPtr_;
if (debug)
@ -96,16 +119,13 @@ void Foam::vtkPVFoam::convertMeshLagrangian()
if (selectedPartIds_.found(partId))
{
const auto& longName = selectedPartIds_[partId];
const word cloudName = getPartName(partId);
const word cloudName = getFoamName(longName);
vtkSmartPointer<vtkPolyData> vtkmesh =
lagrangianVTKMesh
// Direct conversion, no caching for Lagrangian
cachedVtp_(longName).set
(
mesh,
cloudName
lagrangianVTKMesh(mesh, cloudName)
);
cachedVtp_(longName).vtkmesh = vtkmesh;
}
}
@ -119,7 +139,7 @@ void Foam::vtkPVFoam::convertMeshLagrangian()
void Foam::vtkPVFoam::convertMeshPatches()
{
arrayRange& range = rangePatches_;
const arrayRange& range = rangePatches_;
const fvMesh& mesh = *meshPtr_;
const polyBoundaryMesh& patches = mesh.boundaryMesh();
@ -136,14 +156,42 @@ void Foam::vtkPVFoam::convertMeshPatches()
continue;
}
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/"))
{
// Patch group. Collect patch faces.
vtpData.clear(); // Remove any old mappings
const labelList& patchIds =
patches.groupPatchIDs().lookup(partName, labelList());
@ -153,19 +201,32 @@ void Foam::vtkPVFoam::convertMeshPatches()
<< longName << endl;
}
// Store good patch ids as additionalIds
vtpData.additionalIds().reserve(patchIds.size());
label sz = 0;
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);
sz = 0;
for (auto id : patchIds)
}
Foam::sort(vtpData.additionalIds());
// 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];
forAll(pp, i)
{
faceLabels[sz++] = pp.start()+i;
faceLabels.append(pp.start()+i);
}
}
@ -177,11 +238,15 @@ void Foam::vtkPVFoam::convertMeshPatches()
mesh.points()
);
vtkmesh = patchVTKMesh(partName, pp);
vtkgeom = patchVTKMesh(pp);
}
faceLabels.clear(); // Unneeded
}
else
{
vtpData.clear(); // Remove any old mappings
const label patchId = patches.findPatchID(partName);
if (debug)
@ -192,13 +257,20 @@ void Foam::vtkPVFoam::convertMeshPatches()
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()
{
const arrayRange& range = rangeCellZones_;
@ -265,7 +307,7 @@ void Foam::vtkPVFoam::convertMeshCellZones()
}
const auto& longName = selectedPartIds_[partId];
const word zoneName = getPartName(partId);
const word zoneName = getFoamName(longName);
const label zoneId = zMesh.findZoneID(zoneName);
if (zoneId < 0)
@ -279,10 +321,43 @@ void Foam::vtkPVFoam::convertMeshCellZones()
<< zoneName << endl;
}
foamVtuData& vtuData = cachedVtu_(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]);
convertMeshSubset(subsetter, longName);
vtkgeom = volumeVTKSubsetMesh(subsetter, vtuData);
}
vtuData.set(vtkgeom);
}
if (debug)
@ -312,18 +387,50 @@ void Foam::vtkPVFoam::convertMeshCellSets()
}
const auto& longName = selectedPartIds_[partId];
const word partName = getPartName(partId);
const word partName = getFoamName(longName);
if (debug)
{
Info<< "Creating VTK mesh for cellSet=" << partName << endl;
}
const cellSet cSet(mesh, partName);
fvMeshSubset subsetter(mesh);
subsetter.setLargeCellSubset(cSet);
foamVtuData& vtuData = cachedVtu_(longName);
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)
@ -336,7 +443,7 @@ void Foam::vtkPVFoam::convertMeshCellSets()
void Foam::vtkPVFoam::convertMeshFaceZones()
{
arrayRange& range = rangeFaceZones_;
const arrayRange& range = rangeFaceZones_;
const fvMesh& mesh = *meshPtr_;
if (range.empty())
@ -359,28 +466,49 @@ void Foam::vtkPVFoam::convertMeshFaceZones()
}
const auto& longName = selectedPartIds_[partId];
const word zoneName = getPartName(partId);
const word zoneName = getFoamName(longName);
const label zoneId = zMesh.findZoneID(zoneName);
if (zoneId < 0)
{
continue;
}
if (debug)
{
Info<< "Creating VTKmesh for faceZone[" << zoneId << "] "
<< zoneName << endl;
}
vtkSmartPointer<vtkPolyData> vtkmesh =
patchVTKMesh
(
zoneName,
zMesh[zoneId]()
);
foamVtpData& vtpData = cachedVtp_(longName);
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)
@ -393,7 +521,7 @@ void Foam::vtkPVFoam::convertMeshFaceZones()
void Foam::vtkPVFoam::convertMeshFaceSets()
{
arrayRange& range = rangeFaceSets_;
const arrayRange& range = rangeFaceSets_;
const fvMesh& mesh = *meshPtr_;
if (debug)
@ -410,35 +538,61 @@ void Foam::vtkPVFoam::convertMeshFaceSets()
}
const auto& longName = selectedPartIds_[partId];
const word partName = getPartName(partId);
const word partName = getFoamName(longName);
if (debug)
{
Info<< "Creating VTK mesh for faceSet=" << partName << endl;
}
// faces in sorted order for more reliability
const labelList faceLabels = faceSet(mesh, partName).sortedToc();
foamVtpData& vtpData = cachedVtp_(longName);
uindirectPrimitivePatch p
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 other additional ids, maps
// 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(), faceLabels),
UIndirectList<face>(mesh.faces(), vtpData.cellMap()),
mesh.points()
);
if (p.empty())
{
continue;
vtkgeom = patchVTKMesh(pp);
}
}
vtkSmartPointer<vtkPolyData> vtkmesh =
patchVTKMesh
(
"faceSet:" + partName,
p
);
cachedVtp_(longName).vtkmesh = vtkmesh;
if (vtkgeom)
{
vtpData.set(vtkgeom);
}
else
{
cachedVtp_.erase(longName);
}
}
if (debug)
@ -451,7 +605,7 @@ void Foam::vtkPVFoam::convertMeshFaceSets()
void Foam::vtkPVFoam::convertMeshPointZones()
{
arrayRange& range = rangePointZones_;
const arrayRange& range = rangePointZones_;
const fvMesh& mesh = *meshPtr_;
if (debug)
@ -471,7 +625,7 @@ void Foam::vtkPVFoam::convertMeshPointZones()
}
const auto& longName = selectedPartIds_[partId];
const word zoneName = getPartName(partId);
const word zoneName = getFoamName(longName);
const label zoneId = zMesh.findZoneID(zoneName);
if (zoneId < 0)
@ -479,29 +633,50 @@ void Foam::vtkPVFoam::convertMeshPointZones()
continue;
}
const pointField& meshPoints = mesh.points();
const labelUList& pointLabels = zMesh[zoneId];
foamVtpData& vtpData = cachedVtp_(longName);
vtkSmartPointer<vtkPoints> vtkpoints =
vtkSmartPointer<vtkPoints>::New();
vtkpoints->SetNumberOfPoints(pointLabels.size());
forAll(pointLabels, pointi)
vtkSmartPointer<vtkPolyData> vtkgeom;
if (vtpData.nPoints() && vtpData.pointMap().size())
{
vtkpoints->SetPoint
(
pointi,
meshPoints[pointLabels[pointi]].v_
);
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();
}
}
vtkSmartPointer<vtkPolyData> vtkmesh =
vtkSmartPointer<vtkPolyData>::New();
if (!vtkgeom)
{
// 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()
{
arrayRange& range = rangePointSets_;
const arrayRange& range = rangePointSets_;
const fvMesh& mesh = *meshPtr_;
if (debug)
@ -532,36 +707,52 @@ void Foam::vtkPVFoam::convertMeshPointSets()
}
const auto& longName = selectedPartIds_[partId];
const word partName = getPartName(partId);
const word partName = getFoamName(longName);
foamVtpData& vtpData = cachedVtp_(longName);
vtkSmartPointer<vtkPolyData> vtkgeom;
if (vtpData.nPoints() && vtpData.pointMap().size())
{
if (meshState_ == polyMesh::UNCHANGED)
{
if (debug)
{
Info<< "Creating VTK mesh for pointSet=" << partName << endl;
Info<< "reusing " << longName << nl;
}
const pointField& meshPoints = mesh.points();
const labelList pointLabels = pointSet(mesh, partName).sortedToc();
vtkSmartPointer<vtkPoints> vtkpoints =
vtkSmartPointer<vtkPoints>::New();
vtkpoints->SetNumberOfPoints(pointLabels.size());
forAll(pointLabels, pointi)
vtpData.reuse();
continue;
}
else if (meshState_ == polyMesh::POINTS_MOVED)
{
vtkpoints->SetPoint
(
pointi,
meshPoints[pointLabels[pointi]].v_
);
if (debug)
{
Info<< "move points " << longName << nl;
}
vtkgeom = vtpData.getCopy();
}
}
vtkSmartPointer<vtkPolyData> vtkmesh =
vtkSmartPointer<vtkPolyData>::New();
if (!vtkgeom)
{
// First time, or topo change
vtkgeom = vtkSmartPointer<vtkPolyData>::New();
vtpData.pointMap() = pointSet(mesh, partName).sortedToc();
}
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);
}
if (debug)

View File

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

View File

@ -28,18 +28,89 @@ License
// OpenFOAM includes
#include "fvMesh.H"
#include "fvMeshSubset.H"
#include "foamVtkAdaptors.H"
#include "foamVtuSizing.H"
// VTK includes
#include "vtkUnstructuredGrid.h"
#include "foamVtkAdaptors.H"
// * * * * * * * * * * * * * * * 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
(
const fvMesh& mesh,
foamVtuData& vtuData
foamVtuData& vtuData,
const bool decompPoly
)
{
if (debug)
@ -48,25 +119,15 @@ vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKMesh
printMemory();
}
foamVtuSizing sizing(mesh, !reader_->GetUseVTKPolyhedron());
foamVtuSizing sizing(mesh, decompPoly);
vtkSmartPointer<vtkUnstructuredGrid> vtkmesh =
vtkSmartPointer<vtkUnstructuredGrid>::New();
auto cellTypes = vtkSmartPointer<vtkUnsignedCharArray>::New();
auto cellTypes =
nonNullSmartPointer<vtkUnsignedCharArray>(vtkmesh->GetCellTypesArray());
auto cells = vtkSmartPointer<vtkCellArray>::New();
auto faces = vtkSmartPointer<vtkIdTypeArray>::New();
auto cells =
nonNullSmartPointer<vtkCellArray>(vtkmesh->GetCells());
auto faces =
nonNullSmartPointer<vtkIdTypeArray>(vtkmesh->GetFaces());
auto cellLocations =
nonNullSmartPointer<vtkIdTypeArray>(vtkmesh->GetCellLocationsArray());
auto faceLocations =
nonNullSmartPointer<vtkIdTypeArray>(vtkmesh->GetFaceLocations());
auto cellLocations = vtkSmartPointer<vtkIdTypeArray>::New();
auto faceLocations = vtkSmartPointer<vtkIdTypeArray>::New();
UList<uint8_t> cellTypesUL =
vtkUList
@ -116,33 +177,12 @@ vtkSmartPointer<vtkUnstructuredGrid> Foam::vtkPVFoam::volumeVTKMesh
static_cast<foamVtkMeshMaps&>(vtuData)
);
auto vtkmesh = vtkSmartPointer<vtkUnstructuredGrid>::New();
// Convert OpenFOAM mesh vertices to VTK
// - can only do this *after* populating the decompInfo with cell-ids
// for any additional points (ie, mesh cell-centres)
vtkSmartPointer<vtkPoints> vtkpoints = vtkmesh->GetPoints();
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_);
}
vtkmesh->SetPoints(movePoints(mesh, vtuData));
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
#include "polyPatch.H"
#include "primitivePatch.H"
#include "foamVtkAdaptors.H"
// VTK includes
#include "vtkCellArray.h"
@ -35,38 +36,36 @@ License
#include "vtkPolyData.h"
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class PatchType>
vtkSmartPointer<vtkPolyData> Foam::vtkPVFoam::patchVTKMesh
vtkSmartPointer<vtkPoints> Foam::vtkPVFoam::movePatchPoints
(
const string& name,
const PatchType& p
)
{
vtkSmartPointer<vtkPolyData> vtkmesh =
vtkSmartPointer<vtkPolyData>::New();
if (debug)
{
Info<< "<beg> patchVTKMesh - " << name << endl;
printMemory();
}
// Convert OpenFOAM mesh vertices to VTK
const Foam::pointField& points = p.localPoints();
const pointField& points = p.localPoints();
vtkSmartPointer<vtkPoints> vtkpoints =
vtkSmartPointer<vtkPoints>::New();
auto vtkpoints = vtkSmartPointer<vtkPoints>::New();
vtkpoints->SetNumberOfPoints(points.size());
forAll(points, i)
{
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();
label nAlloc = faces.size();
@ -75,32 +74,45 @@ vtkSmartPointer<vtkPolyData> Foam::vtkPVFoam::patchVTKMesh
nAlloc += faces[facei].size();
}
vtkSmartPointer<vtkCellArray> vtkcells =
vtkSmartPointer<vtkCellArray>::New();
auto cells = vtkSmartPointer<vtkCellArray>::New();
vtkcells->Allocate(nAlloc);
// If reusing memory, ensure insert always starts from 0
vtkcells->Reset();
UList<vtkIdType> cellsUL =
vtkUList
(
cells,
faces.size(),
nAlloc
);
// Cell connectivity for polygons
// [size, verts..., size, verts... ]
label idx = 0;
forAll(faces, facei)
{
const face& f = faces[facei];
vtkIdType nodeIds[f.size()];
cellsUL[idx++] = f.size();
forAll(f, fp)
{
nodeIds[fp] = f[fp];
cellsUL[idx++] = f[fp];
}
vtkcells->InsertNextCell(f.size(), nodeIds);
}
vtkmesh->SetPolys(vtkcells);
return cells;
}
if (debug)
{
Info<< "<end> patchVTKMesh - " << name << endl;
printMemory();
}
template<class PatchType>
vtkSmartPointer<vtkPolyData> Foam::vtkPVFoam::patchVTKMesh
(
const PatchType& p
)
{
auto vtkmesh = vtkSmartPointer<vtkPolyData>::New();
vtkmesh->SetPoints(movePatchPoints(p));
vtkmesh->SetPolys(patchFacesVTKCells(p));
return vtkmesh;
}

View File

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

View File

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

View File

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

View File

@ -60,8 +60,7 @@ namespace Foam
const Foam::point& pt
)
{
vtkSmartPointer<vtkTextActor> txt =
vtkSmartPointer<vtkTextActor>::New();
auto txt = vtkSmartPointer<vtkTextActor>::New();
txt->SetInput(s.c_str());
@ -310,8 +309,8 @@ void Foam::vtkPVblockMesh::updateInfo()
HashSet<string> enabledEdges;
if (!firstTime)
{
enabledParts = getSelectedArrayEntries(blockSelection);
enabledEdges = getSelectedArrayEntries(edgeSelection);
enabledParts = getSelectedArraySet(blockSelection);
enabledEdges = getSelectedArraySet(edgeSelection);
}
// Clear current mesh parts list
@ -407,14 +406,6 @@ void Foam::vtkPVblockMesh::Update
{
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
updateFoamMesh();
reader_->UpdateProgress(0.5);
@ -427,7 +418,6 @@ void Foam::vtkPVblockMesh::Update
convertMeshEdges(output, blockNo);
reader_->UpdateProgress(0.8);
}

View File

@ -25,13 +25,18 @@ Class
Foam::vtkPVblockMesh
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
vtkPVblockMesh.C
vtkPVblockMeshConvert.C
vtkPVblockMeshUpdate.C
vtkPVblockMeshUtils.C
// Needed by VTK:
vtkDataArrayTemplateImplicit.txx
@ -95,12 +100,6 @@ class vtkPVblockMesh
//- The mesh directory for the region
fileName meshDir_;
//- Selected geometrical parts
boolList blockStatus_;
//- Selected curved edges
boolList edgeStatus_;
//- First instance and size of bleckMesh blocks
// used to index into blockStatus_
arrayRange rangeBlocks_;

View File

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

View File

@ -34,6 +34,8 @@ License
#include "vtkInformation.h"
#include "vtkSmartPointer.h"
#include "foamVtkAdaptors.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
@ -82,7 +84,7 @@ void Foam::foamPvCore::addToBlock
block->SetBlock(datasetNo, dataset);
// name the output block when assigning dataset 0
// Name the output block when assigning dataset 0
if (datasetNo == 0)
{
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
(
vtkDataArraySelection* select
@ -173,54 +147,15 @@ Foam::hashedWordList Foam::foamPvCore::getSelected
Foam::HashSet<Foam::string>
Foam::foamPvCore::getSelectedArrayEntries
Foam::foamPvCore::getSelectedArraySet
(
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();
HashSet<string> enabled(2*n);
for (auto i : slice)
for (int i=0; i < n; ++i)
{
if (select->GetArraySetting(i))
{
@ -230,8 +165,9 @@ Foam::foamPvCore::getSelectedArrayEntries
if (debug > 1)
{
const int n = select->GetNumberOfArrays();
Info<< "available(";
for (auto i : slice)
for (int i=0; i < n; ++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,
const HashSet<string>& enabled
vtkDataArraySelection* select
)
{
const int n = select->GetNumberOfArrays();
// disable everything not explicitly enabled
select->DisableAllArrays();
Map<string> enabled(2*n);
// Loop through entries, enabling as required
for (int i=0; i < n; ++i)
{
const char* arrayName = select->GetArrayName(i);
if (enabled.found(arrayName))
if (select->GetArraySetting(i))
{
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 "Hash.H"
#include "HashSet.H"
#include "Map.H"
#include "hashedWordList.H"
#include "labelRange.H"
#include "vtkPoints.h"
// * * * * * * * * * * * * * Forward Declarations * * * * * * * * * * * * * //
class vtkCellArray;
class vtkDataArraySelection;
class vtkDataSet;
class vtkMultiBlockDataSet;
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,
// while stripping off any prefix or suffix
static hashedWordList getSelected
@ -192,25 +187,24 @@ public:
);
//- Retrieve the currently enabled selections
static HashSet<string> getSelectedArrayEntries
//- Retrieve the currently enabled selections as hashset
static HashSet<string> getSelectedArraySet
(
vtkDataArraySelection* select
);
//- Retrieve a sub-list of the currently enabled selections
static HashSet<string> getSelectedArrayEntries
//- Retrieve the currently enabled selections as id/name map
static Map<string> getSelectedArrayMap
(
vtkDataArraySelection* select,
const arrayRange& slice
vtkDataArraySelection* select
);
//- Enable the selection(s)
template<class AnyValue, class AnyHasher>
static void setSelectedArrayEntries
(
vtkDataArraySelection* select,
const HashSet<string>& enabled
const HashTable<AnyValue, string, AnyHasher>& enabled
);
@ -222,6 +216,13 @@ public:
static void printMemory();
//- Return an identity list of VTK_VERTEX
static vtkSmartPointer<vtkCellArray> identityVertices
(
const label size
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
}; // 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);
}
}
}
// ************************************************************************* //