Commits (31)
......@@ -178,6 +178,7 @@ if ("$ENV{CMAKE_CONFIGURATION}" MATCHES "stdthread") # They failed also on OpenM
# Need investigations https://gitlab.kitware.com/vtk/vtk/-/issues/18222
"^VTK::FiltersExtractionCxx-TestExtractSelectionUsingDataAssembly$"
"^VTK::FiltersGeneralCxx-TestAnimateModes$"
"^VTK::FiltersHybridCxx-TestTemporalInterpolator$"
"^VTK::FiltersParallelDIY2Cxx-TestRedistributeDataSetFilterOnIOSS$"
"^VTK::IOIOSSCxx-TestIOSSExodus$"
"^VTK::IOIOSSCxx-TestIOSSSuperelements$"
......
# VTK version number components.
set(VTK_MAJOR_VERSION 9)
set(VTK_MINOR_VERSION 0)
set(VTK_BUILD_VERSION 20210920)
set(VTK_BUILD_VERSION 20210922)
if (NOT VTK_MINOR_VERSION LESS 100)
message(FATAL_ERROR
......
......@@ -401,6 +401,23 @@ endif()
include(TestBigEndian)
test_big_endian(VTK_WORDS_BIGENDIAN)
# vtkSMP header information.
set(smp_backends
OpenMP
Sequential
STDThread
TBB)
foreach (smp_backend IN LISTS smp_backends)
string(TOLOWER "${smp_backend}" smp_backend_lower)
string(TOUPPER "${smp_backend}" smp_backend_upper)
set("VTK_SMP_ENABLE_${smp_backend_upper}" "${vtk_smp_enable_${smp_backend_lower}}")
if (VTK_SMP_IMPLEMENTATION_TYPE STREQUAL smp_backend)
set("VTK_SMP_DEFAULT_IMPLEMENTATION_${smp_backend_upper}" 1)
else ()
set("VTK_SMP_DEFAULT_IMPLEMENTATION_${smp_backend_upper}" 0)
endif ()
endforeach ()
set(nowrap_headers
vtkMathPrivate.hxx
${vtk_smp_nowrap_headers})
......@@ -554,14 +571,3 @@ vtk_module_link(VTK::CommonCore
vtk_module_compile_features(VTK::CommonCore
PUBLIC
cxx_std_11)
vtk_module_definitions(VTK::CommonCore
PUBLIC
"VTK_SMP_ENABLE_SEQUENTIAL=${vtk_smp_enable_sequential}"
"VTK_SMP_ENABLE_STDTHREAD=${vtk_smp_enable_stdthread}"
"VTK_SMP_ENABLE_TBB=${vtk_smp_enable_tbb}"
"VTK_SMP_ENABLE_OPENMP=${vtk_smp_enable_openmp}"
"VTK_SMP_DEFAULT_IMPLEMENTATION_SEQUENTIAL=$<STREQUAL:${VTK_SMP_IMPLEMENTATION_TYPE},Sequential>"
"VTK_SMP_DEFAULT_IMPLEMENTATION_STDTHREAD=$<STREQUAL:${VTK_SMP_IMPLEMENTATION_TYPE},STDThread>"
"VTK_SMP_DEFAULT_IMPLEMENTATION_TBB=$<STREQUAL:${VTK_SMP_IMPLEMENTATION_TYPE},TBB>"
"VTK_SMP_DEFAULT_IMPLEMENTATION_OPENMP=$<STREQUAL:${VTK_SMP_IMPLEMENTATION_TYPE},OpenMP>")
......@@ -22,6 +22,7 @@
#include "SMP/Common/vtkSMPThreadLocalImplAbstract.h"
#include "SMP/Common/vtkSMPToolsAPI.h" // For GetBackendType(), DefaultBackend
#include "vtkSMP.h"
#include "vtkSystemIncludes.h"
#if VTK_SMP_ENABLE_SEQUENTIAL
......
......@@ -14,6 +14,7 @@
=========================================================================*/
#include "SMP/Common/vtkSMPToolsAPI.h"
#include "vtkSMP.h" // For SMP preprocessor information
#include "vtkSetGet.h" // For vtkWarningMacro
#include <algorithm> // For std::toupper
......
......@@ -19,6 +19,7 @@
#include "vtkCommonCoreModule.h" // For export macro
#include "vtkNew.h"
#include "vtkObject.h"
#include "vtkSMP.h"
#include <memory>
......
......@@ -18,6 +18,7 @@
#include "vtkCommonCoreModule.h" // For export macro
#include "vtkObject.h"
#include "vtkSMP.h"
#define VTK_SMP_MAX_BACKENDS_NB 4
......
......@@ -19,4 +19,16 @@
#define VTK_SMP_@VTK_SMP_IMPLEMENTATION_TYPE@
#define VTK_SMP_BACKEND "@VTK_SMP_IMPLEMENTATION_TYPE@"
// Preprocessor symbols which indicate the availability of backends.
#cmakedefine01 VTK_SMP_ENABLE_OPENMP
#cmakedefine01 VTK_SMP_ENABLE_SEQUENTIAL
#cmakedefine01 VTK_SMP_ENABLE_STDTHREAD
#cmakedefine01 VTK_SMP_ENABLE_TBB
// Defines which indicate whether the default is a specific backend.
#cmakedefine01 VTK_SMP_DEFAULT_IMPLEMENTATION_OPENMP
#cmakedefine01 VTK_SMP_DEFAULT_IMPLEMENTATION_SEQUENTIAL
#cmakedefine01 VTK_SMP_DEFAULT_IMPLEMENTATION_STDTHREAD
#cmakedefine01 VTK_SMP_DEFAULT_IMPLEMENTATION_TBB
#endif
## Interpolate input dataset's field variables to vortex cores
`vtkVortexCore`'s output points now include the interpolated variables of the input points.
To accomplish that, `vtkParallelVectors`, which is called inside `vtkVortexCore`, calculates the
interpolation weights while visiting the triangles of each cell, and later on, uses the weights to
calculate the interpolation values for each variable.
## Backward time support in vtkTemporalPathLineFilter
The temporal path line filter is now able to manage backward time.
You can use `SetBackwardTime` method to switch from forward time to backward time.
Backward time means that for each call to vtkTemporalPathLineFilter::RequestData then the time step from vtkDataObject::DATA_TIME_STEP() is smaller than the time step from the previous call.
......@@ -18,6 +18,7 @@
#include "vtkCell3D.h"
#include "vtkDataSet.h"
#include "vtkDoubleArray.h"
#include "vtkIdList.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkLogger.h"
......@@ -28,6 +29,7 @@
#include "vtkPolyLine.h"
#include "vtkPolygon.h"
#include "vtkSMPTools.h"
#include "vtkTriangle.h"
#include "vtk_eigen.h"
#include VTK_EIGEN(Eigenvalues)
......@@ -454,11 +456,17 @@ namespace detail
*/
struct SurfaceTrianglePoint
{
std::array<vtkIdType, 3> TrianglePointIds;
std::array<double, 3> Coordinates;
std::array<double, 3> InterpolationWeights;
std::vector<double> Criteria;
SurfaceTrianglePoint(const std::array<double, 3>& point, std::vector<double>& criteria)
: Coordinates(point)
SurfaceTrianglePoint(const std::array<vtkIdType, 3>& trianglePointIds,
const std::array<double, 3>& point, const std::array<double, 3>& interpolationWeights,
const std::vector<double>& criteria)
: TrianglePointIds(trianglePointIds)
, Coordinates(point)
, InterpolationWeights(interpolationWeights)
, Criteria(criteria)
{
}
......@@ -479,6 +487,8 @@ class CollectValidCellSurfacePointsFunctor
vtkSMPThreadLocal<vtkSmartPointer<vtkGenericCell>> Cell;
vtkSMPThreadLocal<vtkSmartPointer<vtkPolygon>> Polygon;
vtkSMPThreadLocal<vtkSmartPointer<vtkIdList>> OutTris;
vtkSMPThreadLocal<std::vector<double>> CriterionArrayValues;
vtkSMPThreadLocal<std::array<double, 3>> Weights;
public:
CollectValidCellSurfacePointsFunctor(VArrayType* vField, WArrayType* wField, vtkDataSet* input,
......@@ -501,6 +511,9 @@ public:
tlPolygon = vtkSmartPointer<vtkPolygon>::New();
auto& tlOutTris = this->OutTris.Local();
tlOutTris = vtkSmartPointer<vtkIdList>::New();
auto& tlCriterionArrayValues = this->CriterionArrayValues.Local();
tlCriterionArrayValues.resize(this->ParallelVectors->CriteriaArrays.size());
this->Weights.Local();
}
void operator()(vtkIdType begin, vtkIdType end)
......@@ -508,8 +521,9 @@ public:
auto& tlCell = this->Cell.Local();
auto& tlPolygon = this->Polygon.Local();
auto& tlOutTris = this->OutTris.Local();
auto& tlCriterionArrayValues = this->CriterionArrayValues.Local();
auto& tlWeights = this->Weights.Local();
std::vector<std::array<vtkIdType, 3>> surfaceTriangles;
std::vector<double> criterionArrayValues(this->ParallelVectors->CriteriaArrays.size());
for (vtkIdType cellId = begin; cellId < end; ++cellId)
{
......@@ -533,22 +547,22 @@ public:
int counter = 0;
// For each triangle comprising the cell's surface...
for (const std::array<vtkIdType, 3>& triangle : surfaceTriangles)
for (const std::array<vtkIdType, 3>& trianglePointIds : surfaceTriangles)
{
if (!this->ParallelVectors->AcceptSurfaceTriangle(triangle.data()))
if (!this->ParallelVectors->AcceptSurfaceTriangle(trianglePointIds.data()))
{
continue;
}
// ...access the vector values at the vertices
int triangleId;
int trianglePointId;
for (int i = 0; i < 3; i++)
{
triangleId = triangle[i];
trianglePointId = trianglePointIds[i];
for (int j = 0; j < 3; ++j)
{
v[i][j] = static_cast<double>(this->VRange[triangleId][j]);
w[i][j] = static_cast<double>(this->WRange[triangleId][j]);
v[i][j] = static_cast<double>(this->VRange[trianglePointId][j]);
w[i][j] = static_cast<double>(this->WRange[trianglePointId][j]);
}
}
......@@ -564,16 +578,19 @@ public:
const double& t = st[1];
if (!this->ParallelVectors->ComputeAdditionalCriteria(
triangle.data(), s, t, criterionArrayValues))
trianglePointIds.data(), s, t, tlCriterionArrayValues))
{
continue;
}
double pCoords[3] = { s, t, 0.0 };
vtkTriangle::InterpolationFunctions(pCoords, tlWeights.data());
// Convert the parametric location to an absolute location
double p[3][3];
for (int i = 0; i < 3; i++)
{
this->Input->GetPoint(triangle[i], p[i]);
this->Input->GetPoint(trianglePointIds[i], p[i]);
}
std::array<double, 3> pOut;
......@@ -583,7 +600,7 @@ public:
}
this->CellSurfaceTrianglePoints[cellId].push_back(
SurfaceTrianglePoint(pOut, criterionArrayValues));
SurfaceTrianglePoint(trianglePointIds, pOut, tlWeights, tlCriterionArrayValues));
if (counter == 2)
{
......@@ -653,10 +670,16 @@ int vtkParallelVectors::RequestData(
}
// Access the two vector fields
vtkDataSetAttributes* inDA =
vtkDataSetAttributes::SafeDownCast(input->GetAttributesAsFieldData(vtkDataObject::POINT));
vtkDataSetAttributes* outDA =
vtkDataSetAttributes::SafeDownCast(output->GetAttributesAsFieldData(vtkDataObject::POINT));
outDA->InterpolateAllocate(inDA);
vtkDataArray* vField =
vtkDataArray::SafeDownCast(input->GetPointData()->GetAbstractArray(this->FirstVectorFieldName));
vtkDataArray* wField = vtkDataArray::SafeDownCast(
input->GetPointData()->GetAbstractArray(this->SecondVectorFieldName));
vtkDataArray::SafeDownCast(inDA->GetAbstractArray(this->FirstVectorFieldName));
vtkDataArray* wField =
vtkDataArray::SafeDownCast(inDA->GetAbstractArray(this->SecondVectorFieldName));
// Check that the two fields are, in fact, vector fields
{
......@@ -727,12 +750,15 @@ int vtkParallelVectors::RequestData(
polyLineBuilder.MergeLimit = static_cast<std::size_t>(std::cbrt(input->GetNumberOfCells()));
}
for (const auto& points : cellSurfaceTrianglePoints)
vtkNew<vtkIdList> trianglePointIds;
trianglePointIds->SetNumberOfIds(3);
for (auto& points : cellSurfaceTrianglePoints)
{
vtkIdType pIndex[2] = { -1, -1 };
int counter = 0;
// For each surface triangle point comprising the cell's surface...
for (const auto& point : points)
for (auto& point : points)
{
if (counter == 2)
{
......@@ -748,6 +774,14 @@ int vtkParallelVectors::RequestData(
vtkIdType pIdx;
locator->InsertUniquePoint(point.Coordinates.data(), pIdx);
// interpolate output points based on input points
for (int i = 0; i < 3; ++i)
{
trianglePointIds->SetId(i, point.TrianglePointIds[i]);
}
outDA->InterpolatePoint(inDA, pIdx, trianglePointIds, point.InterpolationWeights.data());
// Add criteria values to their arrays
for (size_t i = 0; i < this->CriteriaArrays.size(); ++i)
{
this->CriteriaArrays[i]->InsertTypedTuple(pIdx, (&(point.Criteria[i])));
......@@ -793,6 +827,7 @@ int vtkParallelVectors::RequestData(
// Populate our output polydata.
output->SetPoints(outputPoints);
output->SetLines(outputLines);
outDA->Squeeze();
this->Postfilter(info, inputVector, outputVector);
......
......@@ -45,6 +45,7 @@ vtk_add_test_cxx(vtkFiltersGeneralCxxTests tests
TestSplitByCellScalarFilter.cxx,NO_VALID
TestTableFFT.cxx,NO_VALID
TestTableSplitColumnComponents.cxx,NO_VALID
TestTemporalPathLineFilter.cxx,NO_VALID
TestTessellator.cxx,NO_VALID
TestTransformFilter.cxx,NO_VALID
TestTransformPolyDataFilter.cxx,NO_VALID
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestTemporalPathLineFilter.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkTemporalPathLineFilter.h"
#include "vtkInformation.h"
#include "vtkLogger.h"
#include "vtkNew.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkTimeSourceExample.h"
bool TestForwardTime()
{
vtkNew<vtkTimeSourceExample> timeSource;
timeSource->SetXAmplitude(10);
timeSource->SetYAmplitude(0);
timeSource->UpdateInformation();
vtkInformation* sourceInformation = timeSource->GetOutputInformation(0);
if (!sourceInformation)
{
vtkLog(ERROR, "Invalid source information.");
return false;
}
double* timeSteps = sourceInformation->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
int timeStepsNumber = sourceInformation->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
vtkNew<vtkTemporalPathLineFilter> temporalPathLineFilter;
temporalPathLineFilter->SetInputConnection(0, timeSource->GetOutputPort());
temporalPathLineFilter->SetMaxTrackLength(100);
temporalPathLineFilter->SetMaxStepDistance(100, 100, 100);
for (int timeStep = 0; timeStep < timeStepsNumber; ++timeStep)
{
temporalPathLineFilter->UpdateTimeStep(timeSteps[timeStep]);
}
auto* resultPolyData = temporalPathLineFilter->GetOutput();
if (!resultPolyData)
{
vtkLog(ERROR, "Invalid result poly data.");
return false;
}
if (resultPolyData->GetNumberOfPoints() != 10)
{
vtkLog(
ERROR, "Wrong number of points in result poly data: " << resultPolyData->GetNumberOfPoints());
return false;
}
auto* lines = resultPolyData->GetLines();
if (!lines)
{
vtkLog(ERROR, "Invalid lines in result poly data.");
return false;
}
if (lines->GetNumberOfCells() != 1)
{
vtkLog(
ERROR, "Wrong number of cells in lines from result poly data: " << lines->GetNumberOfCells());
return false;
}
vtkNew<vtkIdList> pointIDs;
lines->GetCellAtId(0, pointIDs);
if (pointIDs->GetNumberOfIds() != 10)
{
vtkLog(ERROR, "Wrong number of points in result poly data.");
return false;
}
return true;
}
bool TestBackwardTime()
{
vtkNew<vtkTimeSourceExample> timeSource;
timeSource->SetXAmplitude(10);
timeSource->SetYAmplitude(0);
timeSource->UpdateInformation();
vtkInformation* sourceInformation = timeSource->GetOutputInformation(0);
if (!sourceInformation)
{
vtkLog(ERROR, "Invalid source information.");
return false;
}
double* timeSteps = sourceInformation->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
int timeStepsNumber = sourceInformation->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
vtkNew<vtkTemporalPathLineFilter> temporalPathLineFilter;
temporalPathLineFilter->SetInputConnection(0, timeSource->GetOutputPort());
temporalPathLineFilter->SetMaxTrackLength(100);
temporalPathLineFilter->SetMaxStepDistance(100, 100, 100);
temporalPathLineFilter->SetBackwardTime(true);
for (int timeStep = timeStepsNumber - 1; timeStep >= 0; --timeStep)
{
temporalPathLineFilter->UpdateTimeStep(timeSteps[timeStep]);
}
auto* resultPolyData = temporalPathLineFilter->GetOutput();
if (!resultPolyData)
{
vtkLog(ERROR, "Invalid result poly data.");
return false;
}
if (resultPolyData->GetNumberOfPoints() != 10)
{
vtkLog(
ERROR, "Wrong number of points in result poly data: " << resultPolyData->GetNumberOfPoints());
return false;
}
auto* lines = resultPolyData->GetLines();
if (!lines)
{
vtkLog(ERROR, "Invalid lines in result poly data.");
return false;
}
if (lines->GetNumberOfCells() != 1)
{
vtkLog(
ERROR, "Wrong number of cells in lines from result poly data: " << lines->GetNumberOfCells());
return false;
}
vtkNew<vtkIdList> pointIDs;
lines->GetCellAtId(0, pointIDs);
if (pointIDs->GetNumberOfIds() != 10)
{
vtkLog(ERROR, "Wrong number of points in result poly data.");
return false;
}
return true;
}
int TestTemporalPathLineFilter(int, char*[])
{
if (!TestForwardTime() || !TestBackwardTime())
{
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
......@@ -103,29 +103,19 @@ public:
vtkStandardNewMacro(vtkTemporalPathLineFilterInternals);
typedef std::map<int, double>::iterator TimeStepIterator;
static constexpr double LATEST_TIME_MAX = VTK_DOUBLE_MAX;
//------------------------------------------------------------------------------
vtkTemporalPathLineFilter::vtkTemporalPathLineFilter()
{
this->NumberOfTimeSteps = 0;
this->MaskPoints = 200;
this->MaxTrackLength = 10;
this->LastTrackLength = 10;
this->FirstTime = 1;
this->IdChannelArray = nullptr;
this->LatestTime = 01E10;
this->MaxStepDistance[0] = 0.0001;
this->MaxStepDistance[1] = 0.0001;
this->MaxStepDistance[2] = 0.0001;
this->MaxStepDistance[0] = 1;
this->MaxStepDistance[1] = 1;
this->MaxStepDistance[2] = 1;
this->KeepDeadTrails = 0;
this->Vertices = vtkSmartPointer<vtkCellArray>::New();
this->LatestTime = LATEST_TIME_MAX;
this->PolyLines = vtkSmartPointer<vtkCellArray>::New();
this->Vertices = vtkSmartPointer<vtkCellArray>::New();
this->LineCoordinates = vtkSmartPointer<vtkPoints>::New();
this->VertexCoordinates = vtkSmartPointer<vtkPoints>::New();
this->TrailId = vtkSmartPointer<vtkFloatArray>::New();
this->Internals = vtkSmartPointer<vtkTemporalPathLineFilterInternals>::New();
this->SetNumberOfInputPorts(2);
this->SetNumberOfOutputPorts(2); // Lines and points
}
......@@ -163,6 +153,18 @@ int vtkTemporalPathLineFilter::FillOutputPortInformation(int port, vtkInformatio
}
return 1;
}
//------------------------------------------------------------------------------
void vtkTemporalPathLineFilter::SetBackwardTime(bool backward)
{
if (this->BackwardTime != backward)
{
this->LatestTime = backward ? 0 : LATEST_TIME_MAX;
this->BackwardTime = backward;
this->Modified();
}
}
//------------------------------------------------------------------------------
void vtkTemporalPathLineFilter::SetSelectionConnection(vtkAlgorithmOutput* algOutput)
{
......@@ -393,10 +395,15 @@ int vtkTemporalPathLineFilter::RequestData(vtkInformation* vtkNotUsed(informatio
//
// Check time and Track length
//
if (CurrentTimeStep < this->LatestTime)
if ((!this->BackwardTime && (CurrentTimeStep < this->LatestTime)) ||
(this->BackwardTime && (CurrentTimeStep > this->LatestTime)))
{
this->FirstTime = 1;
}
if (this->LastTrackLength != this->MaxTrackLength)
{
this->FirstTime = 1;
}
//
// Reset everything if we are starting afresh
......@@ -448,10 +455,10 @@ int vtkTemporalPathLineFilter::RequestData(vtkInformation* vtkNotUsed(informatio
//
// If a selection input was provided, Build a list of selected Ids
//
this->UsingSelection = 0;
this->UsingSelection = false;
if (selection && Ids)
{
this->UsingSelection = 1;
this->UsingSelection = true;
this->SelectionIds.clear();
vtkDataArray* selectionIds;
if (this->IdChannelArray)
......
......@@ -117,8 +117,22 @@ public:
* until the next time the list is cleared. Use carefully as it may cause
* excessive memory consumption if left on by mistake.
*/
vtkSetMacro(KeepDeadTrails, int);
vtkGetMacro(KeepDeadTrails, int);
vtkSetMacro(KeepDeadTrails, bool);
vtkGetMacro(KeepDeadTrails, bool);
///@}
///@{
/**
* Set / Get if the filter is configured to work in backward time going mode.
* Default is false (time should go forward).
*
* Time going forward means that for each call to RequestData, then the time
* step from vtkDataObject::DATA_TIME_STEP() is greater than the time step
* from the previous call. Time going backward means that the current time
* step is smaller than the previous one.
*/
virtual void SetBackwardTime(bool backward);
vtkGetMacro(BackwardTime, bool);
///@}
/**
......@@ -165,16 +179,17 @@ protected:
void IncrementTrail(TrailPointer trail, vtkDataSet* input, vtkIdType i);
// internal data variables
int NumberOfTimeSteps;
int MaskPoints;
unsigned int MaxTrackLength;
unsigned int LastTrackLength;
int FirstTime;
char* IdChannelArray;
double MaxStepDistance[3];
int NumberOfTimeSteps = 0;
int MaskPoints = 200;
unsigned int MaxTrackLength = 10;
unsigned int LastTrackLength = 10;
int FirstTime = 1;
char* IdChannelArray = nullptr;
double MaxStepDistance[3] = { 1, 1, 1 };
double LatestTime;
int KeepDeadTrails;
int UsingSelection;
bool KeepDeadTrails = false;
bool UsingSelection = false;
bool BackwardTime = false;
//
vtkSmartPointer<vtkCellArray> PolyLines;
......
......@@ -33,6 +33,8 @@
#include "vtkIdTypeArray.h"
#include "vtkImageData.h"
#include "vtkLogger.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkMultiPieceDataSet.h"
#include "vtkMultiProcessController.h"
#include "vtkNew.h"
#include "vtkPartitionedDataSet.h"
......@@ -334,6 +336,31 @@ bool TestGhostCellsTagging(
return true;
}
//----------------------------------------------------------------------------
// Testing multiblock input with more than one depth
bool TestDeepMultiBlock()
{
vtkNew<vtkMultiBlockDataSet> multiBlock;
vtkNew<vtkMultiPieceDataSet> multiPiece;
vtkNew<vtkUnstructuredGrid> ug;
multiBlock->SetNumberOfBlocks(1);
multiBlock->SetBlock(0, multiPiece);
multiPiece->SetNumberOfPieces(1);
multiPiece->SetPiece(0, ug);
vtkNew<vtkGhostCellsGenerator> generator;
generator->SetNumberOfGhostLayers(1);
generator->BuildIfRequiredOff();
generator->SetInputData(multiBlock);
// We are just checking if the output structure is generated without crashing.
// This will crash if the structure of the output doesn't take deep multi blocks into account.
generator->Update();
return true;
}
//----------------------------------------------------------------------------
bool TestMixedTypes(int myrank)
{
......@@ -2672,6 +2699,11 @@ int TestGhostCellsGenerator(int argc, char* argv[])
int myrank = contr->GetLocalProcessId();
int numberOfGhostLayers = 2;
if (!TestDeepMultiBlock())
{
retVal = EXIT_FAILURE;
}
if (!TestMixedTypes(myrank))
{
retVal = EXIT_FAILURE;
......
......@@ -130,8 +130,8 @@ int vtkGhostCellsGenerator::RequestData(
{
using Opts = vtk::DataObjectTreeOptions;
outputCDS->CopyStructure(inputCDS);
auto outputs = vtk::Range(outputCDS, Opts::None);
auto inputs = vtk::Range(inputCDS, Opts::None);
auto outputs = vtk::Range(outputCDS, Opts::VisitOnlyLeaves | Opts::TraverseSubTree);
auto inputs = vtk::Range(inputCDS, Opts::VisitOnlyLeaves | Opts::TraverseSubTree);
for (auto inIt = inputs.begin(), outIt = outputs.begin(); inIt != inputs.end();
++inIt, ++outIt)
{
......
......@@ -343,9 +343,8 @@ void vtkAMReXGridReader::SetUpDataArraySelections()
{
return;
}
int numberOfVariables = this->Internal->Header->variableNamesSize;
for (int i = 0; i < numberOfVariables; ++i)
for (const auto& variable : this->Internal->Header->parsedVariableNames)
{
this->CellDataArraySelection->AddArray(this->Internal->Header->variableNames[i].c_str());
this->CellDataArraySelection->AddArray(variable.first.c_str());
}
}
......@@ -222,6 +222,55 @@ bool vtkAMReXGridHeader::Parse(const std::string& headerData)
return true;
}
void vtkAMReXGridHeader::SetVectorNamePrefix(const std::string& prefix)
{
this->vectorNamePrefix = prefix;
}
void vtkAMReXGridHeader::SetNameDelimiter(const char delim)
{
this->nameDelim = delim;
}
std::string vtkAMReXGridHeader::GetBaseVariableName(const std::string& name)
{
std::string baseName = name;
const std::size_t pos = baseName.find_first_of(this->nameDelim);
const std::string prefix = baseName.substr(0, pos);
if (prefix == this->vectorNamePrefix)
{
baseName = baseName.substr(pos + 1);
std::size_t posSuffix = baseName.find_last_of(this->nameDelim);
baseName = baseName.substr(0, posSuffix);
}
return baseName;
}
int vtkAMReXGridHeader::CheckComponent(const std::string& name)
{
const std::size_t pos = name.find_last_of(this->nameDelim);
// we expect to use the character just past pos
// so we don't want to accidentially jump outside the string
if (pos > name.size() - 1)
{
return -1;
}
const std::string suffix = name.substr(pos + 1);
if (suffix == "x")
{
return 0;
}
if (suffix == "y")
{
return 1;
}
if (suffix == "z")
{
return 2;
}
return -1;
}
bool vtkAMReXGridHeader::ParseGenericHeader(const std::string& headerData)
{
char c;
......@@ -237,6 +286,14 @@ bool vtkAMReXGridHeader::ParseGenericHeader(const std::string& headerData)
for (int cc = 0; cc < this->variableNamesSize; ++cc)
{
hstream >> this->variableNames[cc];
// build vector name map
std::string baseName = this->GetBaseVariableName(this->variableNames[cc]);
int component = this->CheckComponent(this->variableNames[cc]);
// resize variable map for scalar or vector
parsedVariableNames[baseName].resize(component < 0 ? 1 : 3);
component = (component < 0) ? 0 : component;
parsedVariableNames[baseName][component] = cc;
}
hstream >> this->dim;
if (this->dim != 1 && this->dim != 2 && this->dim != 3)
......@@ -853,7 +910,6 @@ void vtkAMReXGridReaderInternal::GetBlockAttribute(
// - Patrick O'Leary
//
int linefeed = is.tellg();
is.seekg((linefeed + 1) + (offsetOfAttribute * (numberOfPoints * ird->numBytes())));
if (debugReader)
{
......@@ -862,37 +918,41 @@ void vtkAMReXGridReaderInternal::GetBlockAttribute(
std::cout << std::endl;
}
// read every component of the variable into the buffers vector
std::string attributeName(attribute);
int nComps = this->Header->parsedVariableNames[attributeName].size();
std::vector<std::vector<char>> buffers(nComps);
for (int i = 0; i < nComps; ++i)
{
int compIndex = this->Header->parsedVariableNames[attributeName][i];
std::string compName = this->Header->variableNames[compIndex];
int offsetOfAttribute = this->GetOffsetOfAttribute(compName.c_str());
is.seekg((linefeed + 1) + (offsetOfAttribute * (numberOfPoints * ird->numBytes())));
buffers[i].resize(numberOfPoints * ird->numBytes());
this->ReadBlockAttribute(is, numberOfPoints, ird->numBytes(), buffers[i].data());
}
RealDescriptor* ord = nullptr;
// copy buffers into vtkSOADataArray
if (ird->numBytes() == 4)
{
vtkNew<vtkFloatArray> dataArray;
dataArray->SetName(attribute);
dataArray->SetNumberOfTuples(numberOfPoints);
float* arrayPtr = static_cast<float*>(dataArray->GetPointer(0));
std::vector<char> buffer(numberOfPoints * ird->numBytes());
this->ReadBlockAttribute(is, numberOfPoints, ird->numBytes(), buffer.data());
RealDescriptor* ord =
new RealDescriptor(ieee_float, little_float_order, 4); // we desire ieee little endian
this->Convert(arrayPtr, buffer.data(), numberOfPoints, *ord, *ird);
vtkNew<vtkSOADataArrayTemplate<float>> dataArray;
ord = new RealDescriptor(ieee_float, little_float_order, 4);
this->CreateVTKAttributeArray(
dataArray.Get(), ord, ird, buffers, numberOfPoints, attributeName);
pDataSet->GetCellData()->AddArray(dataArray);
delete ird;
delete ord;
}
else
{
vtkNew<vtkDoubleArray> dataArray;
dataArray->SetName(attribute);
dataArray->SetNumberOfTuples(numberOfPoints);
double* arrayPtr = static_cast<double*>(dataArray->GetPointer(0));
std::vector<char> buffer(numberOfPoints * ird->numBytes());
this->ReadBlockAttribute(is, numberOfPoints, ird->numBytes(), buffer.data());
RealDescriptor* ord =
new RealDescriptor(ieee_double, little_double_order, 8); // we desire ieee little endian
this->Convert(arrayPtr, buffer.data(), numberOfPoints, *ord, *ird);
vtkNew<vtkSOADataArrayTemplate<double>> dataArray;
ord = new RealDescriptor(ieee_double, little_double_order, 8);
this->CreateVTKAttributeArray(
dataArray.Get(), ord, ird, buffers, numberOfPoints, attributeName);
pDataSet->GetCellData()->AddArray(dataArray);
arrayPtr = nullptr;
delete ird;
delete ord;
}
delete ord;
delete ird;
if (debugReader)
{
std::cout << is.tellg() << " "
......
......@@ -24,10 +24,12 @@
#define vtkAMReXGridReaderInternal_h
#ifndef __VTK_WRAP__
#include <map>
#include <string>
#include <vector>
#include "vtkDataSet.h"
#include "vtkSOADataArrayTemplate.h"
class vtkIndent;
......@@ -91,6 +93,19 @@ public:
std::string versionName;
int variableNamesSize;
std::vector<std::string> variableNames;
// prefix string indicating a variable is a vector component
// Note: this prefix will be removed from any variable name
// whether or not the variable name is a properly formed
// vector variable name (contains a proper postfix)
std::string vectorNamePrefix = "amrexvec";
// delimeter must be the same after prefix and before postfix
char nameDelim = '_';
// variableNames map to (potentially a collection of) variableNames indices
std::map<std::string, std::vector<int>> parsedVariableNames;
int dim;
double time;
int finestLevel;
......@@ -114,6 +129,21 @@ public:
void PrintSelfGenericHeader(std::ostream& os, vtkIndent indent);
bool Parse(const std::string& headerData);
bool ParseGenericHeader(const std::string& headerData);
void SetVectorNamePrefix(const std::string& prefix);
void SetNameDelimiter(const char delim);
private:
// if the vectorNamePrefix is detected at the beginning of the name,
// remove it along with the expected x/y/z postfix. Otherwise, return
// the original string
std::string GetBaseVariableName(const std::string& name);
// returns 0 if postfix is x, 1 for y and 2 for z. returns -1 otherwise
int CheckComponent(const std::string& name);
// check if name has the vectorNamePrefix
bool HasVectorPrefix(const std::string& name);
};
// ----------------------------------------------------------------------------
......@@ -216,6 +246,11 @@ public:
void PermuteOrder(
void* out, const void* in, long nitems, const int* outord, const int* inord, int REALSIZE);
template <typename T>
void CreateVTKAttributeArray(vtkSOADataArrayTemplate<T>* dataArray, const RealDescriptor* ord,
const RealDescriptor* ird, const std::vector<std::vector<char>>& buffers,
const int numberOfPoints, const std::string& attribute);
bool headersAreRead;
bool debugReader;
std::string FileName;
......@@ -225,6 +260,23 @@ public:
friend class vtkAMReXGridLeveHeader;
};
template <typename T>
void vtkAMReXGridReaderInternal::CreateVTKAttributeArray(vtkSOADataArrayTemplate<T>* dataArray,
const RealDescriptor* ord, const RealDescriptor* ird,
const std::vector<std::vector<char>>& buffers, const int numberOfPoints,
const std::string& attribute)
{
const int nComps = this->Header->parsedVariableNames[attribute].size();
dataArray->SetName(attribute.c_str());
dataArray->SetNumberOfComponents(nComps);
dataArray->SetNumberOfTuples(numberOfPoints);
for (int i = 0; i < nComps; ++i)
{
T* arrayPtr = dataArray->GetComponentArrayPointer(i);
this->Convert(arrayPtr, buffers[i].data(), numberOfPoints, *ord, *ird);
}
}
// ----------------------------------------------------------------------------
// Class vtkAMReXGridReaderInternal ( end )
// ----------------------------------------------------------------------------
......