Merge topic 'amrFilter'

11d770659 add worklet include
7139a1c8c add amr capability as filter

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Kenneth Moreland <morelandkd@ornl.gov>
Merge-request: !2646
This commit is contained in:
Roxana Bujack 2021-12-14 20:57:13 +00:00 committed by Kitware Robot
commit 557055b9cc
15 changed files with 771 additions and 13 deletions

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0994e1747beaddba1ab6e97a48e17956e64a12ebfdffac1c2ae8734f3578956f
size 20716

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6a610fe2de049c6a2402f7b19ea5a03f2e637e90d62a6df38832e62b89a691bb
size 25953

@ -102,6 +102,42 @@ struct Bounds
return (this->X.Contains(point[0]) && this->Y.Contains(point[1]) && this->Z.Contains(point[2]));
}
/// \b Returns the volume of the bounds.
///
/// \c Volume computes the product of the lengths of the ranges in each dimension. If the bounds
/// are empty, 0 is returned.
///
VTKM_EXEC_CONT
vtkm::Float64 Volume() const
{
if (this->IsNonEmpty())
{
return (this->X.Length() * this->Y.Length() * this->Z.Length());
}
else
{
return 0.0;
}
}
/// \b Returns the area of the bounds in the X-Y-plane.
///
/// \c Area computes the product of the lengths of the ranges in dimensions X and Y. If the bounds
/// are empty, 0 is returned.
///
VTKM_EXEC_CONT
vtkm::Float64 Area() const
{
if (this->IsNonEmpty())
{
return (this->X.Length() * this->Y.Length());
}
else
{
return 0.0;
}
}
/// \b Returns the center of the range.
///
/// \c Center computes the point at the middle of the bounds. If the bounds
@ -152,6 +188,16 @@ struct Bounds
return unionBounds;
}
/// \b Return the intersection of this and another range.
///
VTKM_EXEC_CONT
vtkm::Bounds Intersection(const vtkm::Bounds& otherBounds) const
{
return vtkm::Bounds(this->X.Intersection(otherBounds.X),
this->Y.Intersection(otherBounds.Y),
this->Z.Intersection(otherBounds.Z));
}
/// \b Operator for union
///
VTKM_EXEC_CONT

@ -19,7 +19,7 @@ enum CellClassification : vtkm::UInt8
GHOST = 1 << 0, //Ghost cell
INVALID = 1 << 1, //Cell is invalid
UNUSED0 = 1 << 2,
UNUSED1 = 1 << 3,
BLANKED = 1 << 3, //Blanked cell in AMR
UNUSED3 = 1 << 4,
UNUSED4 = 1 << 5,
UNUSED5 = 1 << 6,

@ -153,6 +153,14 @@ struct Range
return unionRange;
}
/// \b Return the intersection of this and another range.
///
VTKM_EXEC_CONT
vtkm::Range Intersection(const vtkm::Range& otherRange) const
{
return vtkm::Range(vtkm::Max(this->Min, otherRange.Min), vtkm::Min(this->Max, otherRange.Max));
}
/// \b Operator for union
///
VTKM_EXEC_CONT

86
vtkm/filter/AmrArrays.h Normal file

@ -0,0 +1,86 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt 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.
//============================================================================
#ifndef vtk_m_filter_AmrArrays_h
#define vtk_m_filter_AmrArrays_h
#include <vtkm/filter/FilterDataSet.h>
namespace vtkm
{
namespace filter
{
class AmrArrays : public vtkm::filter::FilterDataSet<AmrArrays>
{
public:
using SupportedTypes = vtkm::List<vtkm::UInt8>;
VTKM_CONT
AmrArrays();
template <typename DerivedPolicy>
vtkm::cont::PartitionedDataSet PrepareForExecution(
const vtkm::cont::PartitionedDataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>&);
template <typename DerivedPolicy>
VTKM_CONT bool MapFieldOntoOutput(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
{
result.AddField(field);
return true;
}
private:
/// the list of ids contains all amrIds of the level above/below that have an overlap
VTKM_CONT
void GenerateParentChildInformation();
/// the corresponding template function based on the dimension of this dataset
VTKM_CONT
template <vtkm::IdComponent Dim>
void ComputeGenerateParentChildInformation();
/// generate the vtkGhostType array based on the overlap analogously to vtk
/// blanked cells: 8 normal cells: 0
VTKM_CONT
void GenerateGhostType();
/// the corresponding template function based on the dimension of this dataset
VTKM_CONT
template <vtkm::IdComponent Dim>
void ComputeGenerateGhostType();
/// Add helper arrays like in ParaView
VTKM_CONT
void GenerateIndexArrays();
/// the input partitioned dataset
vtkm::cont::PartitionedDataSet AmrDataSet;
/// per level
/// contains the index where the PartitionIds start for each level
std::vector<std::vector<vtkm::Id>> PartitionIds;
/// per partitionId
/// contains all PartitonIds of the level above that have an overlap
std::vector<std::vector<vtkm::Id>> ParentsIdsVector;
/// per partitionId
/// contains all PartitonIds of the level below that have an overlap
std::vector<std::vector<vtkm::Id>> ChildrenIdsVector;
};
}
} // namespace vtkm::filter
#include <vtkm/filter/AmrArrays.hxx>
#endif //vtk_m_filter_AmrArrays_h

307
vtkm/filter/AmrArrays.hxx Normal file

@ -0,0 +1,307 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt 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.
//============================================================================
#ifndef vtk_m_filter_AmrArrays_hxx
#define vtk_m_filter_AmrArrays_hxx
#include <vtkm/CellClassification.h>
#include <vtkm/RangeId.h>
#include <vtkm/RangeId2.h>
#include <vtkm/RangeId3.h>
#include <vtkm/Types.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/BoundsCompute.h>
#include <vtkm/worklet/WorkletMapTopology.h>
namespace vtkm
{
namespace worklet
{
template <vtkm::IdComponent Dim>
struct GenerateGhostTypeWorklet : vtkm::worklet::WorkletVisitCellsWithPoints
{
using ControlSignature = void(CellSetIn cellSet,
FieldInPoint pointArray,
FieldInOutCell ghostArray);
using ExecutionSignature = void(PointCount, _2, _3);
using InputDomain = _1;
GenerateGhostTypeWorklet(vtkm::Bounds boundsChild)
: BoundsChild(boundsChild)
{
}
template <typename pointArrayType, typename cellArrayType>
VTKM_EXEC void operator()(vtkm::IdComponent numPoints,
const pointArrayType pointArray,
cellArrayType& ghostArray) const
{
vtkm::Bounds boundsCell = vtkm::Bounds();
for (vtkm::IdComponent pointId = 0; pointId < numPoints; pointId++)
{
boundsCell.Include(pointArray[pointId]);
}
vtkm::Bounds boundsIntersection = boundsCell.Intersection(BoundsChild);
if ((Dim == 2 && boundsIntersection.Area() > 0.5 * boundsCell.Area()) ||
(Dim == 3 && boundsIntersection.Volume() > 0.5 * boundsCell.Volume()))
{
// std::cout<<boundsCell<<" is (partly) contained in "<<BoundsChild<<" "<<boundsIntersection<<" "<<boundsIntersection.Area()<<std::endl;
ghostArray = ghostArray + vtkm::CellClassification::BLANKED;
}
}
vtkm::Bounds BoundsChild;
};
} // worklet
} // vtkm
namespace vtkm
{
namespace filter
{
inline VTKM_CONT AmrArrays::AmrArrays() {}
VTKM_CONT
void AmrArrays::GenerateParentChildInformation()
{
vtkm::Bounds bounds = vtkm::cont::BoundsCompute(this->AmrDataSet);
if (bounds.Z.Max - bounds.Z.Min < vtkm::Epsilon<vtkm::FloatDefault>())
{
ComputeGenerateParentChildInformation<2>();
}
else
{
ComputeGenerateParentChildInformation<3>();
}
}
template void AmrArrays::ComputeGenerateParentChildInformation<2>();
template void AmrArrays::ComputeGenerateParentChildInformation<3>();
VTKM_CONT
template <vtkm::IdComponent Dim>
void AmrArrays::ComputeGenerateParentChildInformation()
{
// read out spacings in decreasing order to infer levels
std::set<FloatDefault, std::greater<FloatDefault>> spacings;
for (vtkm::Id p = 0; p < this->AmrDataSet.GetNumberOfPartitions(); p++)
{
vtkm::cont::ArrayHandleUniformPointCoordinates uniformCoords =
this->AmrDataSet.GetPartition(p)
.GetCoordinateSystem()
.GetData()
.AsArrayHandle<vtkm::cont::ArrayHandleUniformPointCoordinates>();
spacings.insert(uniformCoords.GetSpacing()[0]);
}
std::set<FloatDefault, std::greater<FloatDefault>>::iterator itr;
// for (itr = spacings.begin(); itr != spacings.end(); itr++)
// {
// std::cout << *itr << "\n";
// }
/// contains the partitionIds of each level and blockId
this->PartitionIds.resize(spacings.size());
for (vtkm::Id p = 0; p < this->AmrDataSet.GetNumberOfPartitions(); p++)
{
vtkm::cont::ArrayHandleUniformPointCoordinates uniformCoords =
this->AmrDataSet.GetPartition(p)
.GetCoordinateSystem()
.GetData()
.AsArrayHandle<vtkm::cont::ArrayHandleUniformPointCoordinates>();
int index = -1;
for (itr = spacings.begin(); itr != spacings.end(); itr++)
{
index++;
if (*itr == uniformCoords.GetSpacing()[0])
{
break;
}
}
this->PartitionIds.at(index).push_back(p);
// std::cout <<p<<" "<< index << "\n";
}
// compute parent and child relations
this->ParentsIdsVector.resize(this->AmrDataSet.GetNumberOfPartitions());
this->ChildrenIdsVector.resize(this->AmrDataSet.GetNumberOfPartitions());
for (unsigned int l = 0; l < this->PartitionIds.size() - 1; l++)
{
for (unsigned int bParent = 0; bParent < this->PartitionIds.at(l).size(); bParent++)
{
// std::cout << std::endl << "level " << l << " block " << bParent << std::endl;
vtkm::Bounds boundsParent =
this->AmrDataSet.GetPartition(this->PartitionIds.at(l).at(bParent))
.GetCoordinateSystem()
.GetBounds();
// compute size of a cell to compare overlap against
auto coords = this->AmrDataSet.GetPartition(this->PartitionIds.at(l).at(bParent))
.GetCoordinateSystem()
.GetDataAsMultiplexer();
vtkm::cont::CellSetStructured<Dim> cellset;
vtkm::Id ptids[8];
this->AmrDataSet.GetPartition(this->PartitionIds.at(l).at(bParent))
.GetCellSet()
.CopyTo(cellset);
cellset.GetCellPointIds(0, ptids);
vtkm::Bounds boundsCell = vtkm::Bounds();
for (vtkm::IdComponent pointId = 0; pointId < cellset.GetNumberOfPointsInCell(0); pointId++)
{
boundsCell.Include(coords.ReadPortal().Get(ptids[pointId]));
}
// see if there is overlap of at least one half of a cell
for (unsigned int bChild = 0; bChild < this->PartitionIds.at(l + 1).size(); bChild++)
{
vtkm::Bounds boundsChild =
this->AmrDataSet.GetPartition(this->PartitionIds.at(l + 1).at(bChild))
.GetCoordinateSystem()
.GetBounds();
vtkm::Bounds boundsIntersection = boundsParent.Intersection(boundsChild);
if ((Dim == 2 && boundsIntersection.Area() > 0.5 * boundsCell.Area()) ||
(Dim == 3 && boundsIntersection.Volume() >= 0.5 * boundsCell.Volume()))
{
this->ParentsIdsVector.at(this->PartitionIds.at(l + 1).at(bChild))
.push_back(this->PartitionIds.at(l).at(bParent));
this->ChildrenIdsVector.at(this->PartitionIds.at(l).at(bParent))
.push_back(this->PartitionIds.at(l + 1).at(bChild));
// std::cout << " overlaps with level " << l + 1 << " block " << bChild << " "
// << boundsParent << " " << boundsChild << " " << boundsIntersection << " "
// << boundsIntersection.Area() << " " << boundsIntersection.Volume() << std::endl;
}
// else
// {
// std::cout << " does not overlap with level " << l + 1 << " block " << bChild << " "
// << boundsParent << " " << boundsChild << " " << boundsIntersection << " "
// << boundsIntersection.Area() << " " << boundsIntersection.Volume() << std::endl;
// }
}
}
}
}
VTKM_CONT
void AmrArrays::GenerateGhostType()
{
vtkm::Bounds bounds = vtkm::cont::BoundsCompute(this->AmrDataSet);
if (bounds.Z.Max - bounds.Z.Min < vtkm::Epsilon<vtkm::FloatDefault>())
{
ComputeGenerateGhostType<2>();
}
else
{
ComputeGenerateGhostType<3>();
}
}
template void AmrArrays::ComputeGenerateGhostType<2>();
template void AmrArrays::ComputeGenerateGhostType<3>();
VTKM_CONT
template <vtkm::IdComponent Dim>
void AmrArrays::ComputeGenerateGhostType()
{
for (unsigned int l = 0; l < this->PartitionIds.size(); l++)
{
for (unsigned int bParent = 0; bParent < this->PartitionIds.at(l).size(); bParent++)
{
// std::cout<<std::endl<<"level "<<l<<" block "<<bParent<<" has "<<this->ChildrenIdsVector.at(this->PartitionIds.at(l).at(bParent)).size()<<" children"<<std::endl;
vtkm::cont::DataSet partition =
this->AmrDataSet.GetPartition(this->PartitionIds.at(l).at(bParent));
vtkm::cont::CellSetStructured<Dim> cellset;
partition.GetCellSet().CopyTo(cellset);
vtkm::cont::ArrayHandle<vtkm::UInt8> ghostField;
if (!partition.HasField("vtkGhostType", vtkm::cont::Field::Association::CELL_SET))
{
vtkm::cont::ArrayCopy(
vtkm::cont::ArrayHandleConstant<vtkm::UInt8>(0, partition.GetNumberOfCells()),
ghostField);
}
// leave field unchanged if it is the highest level
if (l < this->PartitionIds.size() - 1)
{
auto pointField = partition.GetCoordinateSystem().GetDataAsMultiplexer();
for (unsigned int bChild = 0;
bChild < this->ChildrenIdsVector.at(this->PartitionIds.at(l).at(bParent)).size();
bChild++)
{
vtkm::Bounds boundsChild =
this->AmrDataSet
.GetPartition(
this->ChildrenIdsVector.at(this->PartitionIds.at(l).at(bParent)).at(bChild))
.GetCoordinateSystem()
.GetBounds();
// std::cout<<" is (partly) contained in level "<<l + 1<<" block "<<bChild<<" which is partition "<<this->ChildrenIdsVector.at(this->PartitionIds.at(l).at(bParent)).at(bChild)<<" with bounds "<<boundsChild<<std::endl;
vtkm::cont::Invoker invoke;
invoke(vtkm::worklet::GenerateGhostTypeWorklet<Dim>{ boundsChild },
cellset,
pointField,
ghostField);
}
}
partition.AddCellField("vtkGhostType", ghostField);
this->AmrDataSet.ReplacePartition(this->PartitionIds.at(l).at(bParent), partition);
}
}
}
// Add helper arrays like in ParaView
VTKM_CONT
void AmrArrays::GenerateIndexArrays()
{
for (unsigned int l = 0; l < this->PartitionIds.size(); l++)
{
for (unsigned int b = 0; b < this->PartitionIds.at(l).size(); b++)
{
vtkm::cont::DataSet partition = this->AmrDataSet.GetPartition(this->PartitionIds.at(l).at(b));
vtkm::cont::ArrayHandle<vtkm::Id> fieldAmrLevel;
vtkm::cont::ArrayCopy(
vtkm::cont::ArrayHandleConstant<vtkm::Id>(l, partition.GetNumberOfCells()), fieldAmrLevel);
partition.AddCellField("vtkAmrLevel", fieldAmrLevel);
vtkm::cont::ArrayHandle<vtkm::Id> fieldBlockId;
vtkm::cont::ArrayCopy(
vtkm::cont::ArrayHandleConstant<vtkm::Id>(b, partition.GetNumberOfCells()), fieldBlockId);
partition.AddCellField("vtkAmrIndex", fieldBlockId);
vtkm::cont::ArrayHandle<vtkm::Id> fieldPartitionIndex;
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleConstant<vtkm::Id>(
this->PartitionIds.at(l).at(b), partition.GetNumberOfCells()),
fieldPartitionIndex);
partition.AddCellField("vtkCompositeIndex", fieldPartitionIndex);
this->AmrDataSet.ReplacePartition(this->PartitionIds.at(l).at(b), partition);
}
}
}
template <typename DerivedPolicy>
vtkm::cont::PartitionedDataSet AmrArrays::PrepareForExecution(
const vtkm::cont::PartitionedDataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
{
this->AmrDataSet = input;
this->GenerateParentChildInformation();
this->GenerateGhostType();
this->GenerateIndexArrays();
return this->AmrDataSet;
}
}
}
#endif

@ -77,6 +77,7 @@ set(common_sources_device
)
set(extra_headers
AmrArrays.h
CellSetConnectivity.h
ClipWithField.h
ClipWithImplicitFunction.h
@ -134,6 +135,7 @@ set(extra_headers
)
set(extra_header_template_sources
AmrArrays.hxx
CellSetConnectivity.hxx
ClipWithField.hxx
ClipWithImplicitFunction.hxx

@ -98,6 +98,7 @@ if (VTKm_ENABLE_RENDERING)
list(APPEND libraries vtkm_rendering)
list(APPEND unit_tests
RegressionTestAmrArrays.cxx
RegressionTestContourFilter.cxx
RegressionTestPointTransform.cxx
RegressionTestSliceFilter.cxx

@ -0,0 +1,78 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt 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 <vtkm/cont/MergePartitionedDataSet.h>
#include <vtkm/filter/ExternalFaces.h>
#include <vtkm/filter/Threshold.h>
#include <vtkm/source/Amr.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/MapperRayTracer.h>
#include <vtkm/rendering/View3D.h>
#include <vtkm/rendering/testing/RenderTest.h>
#include <vtkm/rendering/testing/Testing.h>
namespace
{
void TestAmrArraysExecute(int dim, int numberOfLevels, int cellsPerDimension)
{
std::cout << "Generate Image for AMR" << std::endl;
using M = vtkm::rendering::MapperRayTracer;
using C = vtkm::rendering::CanvasRayTracer;
using V3 = vtkm::rendering::View3D;
// Generate AMR
vtkm::source::Amr source(dim, cellsPerDimension, numberOfLevels);
vtkm::cont::PartitionedDataSet amrDataSet = source.Execute();
// std::cout << "amr " << std::endl;
// amrDataSet.PrintSummary(std::cout);
// Remove blanked cells
vtkm::filter::Threshold threshold;
threshold.SetLowerThreshold(0);
threshold.SetUpperThreshold(1);
threshold.SetActiveField("vtkGhostType");
vtkm::cont::PartitionedDataSet derivedDataSet = threshold.Execute(amrDataSet);
// std::cout << "derived " << std::endl;
// derivedDataSet.PrintSummary(std::cout);
// Extract surface for efficient 3D pipeline
vtkm::filter::ExternalFaces surface;
surface.SetFieldsToPass("RTDataCells");
derivedDataSet = surface.Execute(derivedDataSet);
// Merge dataset
vtkm::cont::DataSet result = vtkm::cont::MergePartitionedDataSet(derivedDataSet);
// std::cout << "merged " << std::endl;
// result.PrintSummary(std::cout);
vtkm::rendering::testing::RenderAndRegressionTest<M, C, V3>(result,
"RTDataCells",
vtkm::cont::ColorTable("inferno"),
"filter/amrArrays" +
std::to_string(dim) + "D.png",
false);
}
void TestAmrArrays()
{
int numberOfLevels = 5;
int cellsPerDimension = 6;
TestAmrArraysExecute(2, numberOfLevels, cellsPerDimension);
TestAmrArraysExecute(3, numberOfLevels, cellsPerDimension);
}
} // namespace
int RegressionTestAmrArrays(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestAmrArrays, argc, argv);
}

111
vtkm/source/Amr.cxx Normal file

@ -0,0 +1,111 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt 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 <vtkm/cont/PartitionedDataSet.h>
#include <vtkm/filter/AmrArrays.h>
#include <vtkm/filter/CellAverage.h>
#include <vtkm/source/Amr.h>
#include <vtkm/source/Wavelet.h>
namespace vtkm
{
namespace source
{
Amr::Amr(vtkm::IdComponent dimension,
vtkm::IdComponent cellsPerDimension,
vtkm::IdComponent numberOfLevels)
: Dimension(dimension)
, CellsPerDimension(cellsPerDimension)
, NumberOfLevels(numberOfLevels)
{
}
Amr::~Amr() = default;
template <vtkm::IdComponent Dim>
vtkm::cont::DataSet Amr::GenerateDataSet(unsigned int level, unsigned int amrIndex) const
{
vtkm::Id3 extent = { vtkm::Id(this->CellsPerDimension / 2) };
vtkm::Id3 dimensions = { this->CellsPerDimension + 1 };
vtkm::Vec3f origin = { float(1. / pow(2, level) * amrIndex) };
vtkm::Vec3f spacing = { float(1. / this->CellsPerDimension / pow(2, level)) };
vtkm::Vec3f center = 0.5f - (origin + spacing * extent);
vtkm::Vec3f frequency = { 60.f, 30.f, 40.f };
frequency = frequency * this->CellsPerDimension;
vtkm::FloatDefault deviation = 0.5f / this->CellsPerDimension;
if (Dim == 2)
{
extent[2] = 0;
dimensions[2] = 1;
origin[2] = 0;
spacing[2] = 1;
center[2] = 0;
}
vtkm::source::Wavelet waveletSource(-extent, extent);
waveletSource.SetOrigin(origin);
waveletSource.SetSpacing(spacing);
waveletSource.SetCenter(center);
waveletSource.SetFrequency(frequency);
waveletSource.SetStandardDeviation(deviation);
vtkm::cont::DataSet wavelet = waveletSource.Execute();
vtkm::filter::CellAverage cellAverage;
cellAverage.SetActiveField("RTData", vtkm::cont::Field::Association::POINTS);
cellAverage.SetOutputFieldName("RTDataCells");
return cellAverage.Execute(wavelet);
}
vtkm::cont::PartitionedDataSet Amr::Execute() const
{
assert(this->CellsPerDimension > 1);
assert(this->CellsPerDimension % 2 == 0);
// Generate AMR
std::vector<std::vector<vtkm::Id>> blocksPerLevel(this->NumberOfLevels);
unsigned int counter = 0;
for (unsigned int l = 0; l < blocksPerLevel.size(); l++)
{
for (unsigned int b = 0; b < pow(2, l); b++)
{
blocksPerLevel.at(l).push_back(counter++);
}
}
vtkm::cont::PartitionedDataSet amrDataSet;
// Fill AMR with data from the wavelet
for (unsigned int l = 0; l < blocksPerLevel.size(); l++)
{
for (unsigned int b = 0; b < blocksPerLevel.at(l).size(); b++)
{
if (this->Dimension == 2)
{
amrDataSet.AppendPartition(this->GenerateDataSet<2>(l, b));
}
else if (this->Dimension == 3)
{
amrDataSet.AppendPartition(this->GenerateDataSet<3>(l, b));
}
}
}
// Generate helper arrays
vtkm::filter::AmrArrays amrArrays;
amrDataSet = amrArrays.Execute(amrDataSet);
return amrDataSet;
}
} // namespace source
} // namespace vtkm

81
vtkm/source/Amr.h Normal file

@ -0,0 +1,81 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt 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.
//============================================================================
#ifndef vtk_m_source_Amr_h
#define vtk_m_source_Amr_h
#include <vtkm/cont/PartitionedDataSet.h>
#include <vtkm/source/vtkm_source_export.h>
namespace vtkm
{
namespace source
{
/**
* @brief The Amr source creates a dataset similar to VTK's
* vtkRTAnalyticSource.
*
* This class generates a predictable structured dataset with a smooth yet
* interesting set of scalars, which is useful for testing and benchmarking.
*
* The Execute method creates a complete structured dataset that have a
* point field names 'scalars'
*
* The scalars are computed as:
*
* ```
* MaxVal * Gauss + MagX * sin(FrqX*x) + MagY * sin(FrqY*y) + MagZ * cos(FrqZ*z)
* ```
*
* The dataset properties are determined by:
* - `Minimum/MaximumExtent`: The logical point extents of the dataset.
* - `Spacing`: The distance between points of the dataset.
* - `Center`: The center of the dataset.
*
* The scalar functions is control via:
* - `Center`: The center of a Gaussian contribution to the scalars.
* - `StandardDeviation`: The unscaled width of a Gaussian contribution.
* - `MaximumValue`: Upper limit of the scalar range.
* - `Frequency`: The Frq[XYZ] parameters of the periodic contributions.
* - `Magnitude`: The Mag[XYZ] parameters of the periodic contributions.
*
* By default, the following parameters are used:
* - `Extents`: { -10, -10, -10 } `-->` { 10, 10, 10 }
* - `Spacing`: { 1, 1, 1 }
* - `Center`: { 0, 0, 0 }
* - `StandardDeviation`: 0.5
* - `MaximumValue`: 255
* - `Frequency`: { 60, 30, 40 }
* - `Magnitude`: { 10, 18, 5 }
*/
class VTKM_SOURCE_EXPORT Amr
{
public:
VTKM_CONT
Amr(vtkm::IdComponent dimension = 2,
vtkm::IdComponent cellsPerDimension = 6,
vtkm::IdComponent numberOfLevels = 4);
VTKM_CONT
~Amr();
vtkm::cont::PartitionedDataSet Execute() const;
private:
template <vtkm::IdComponent Dim>
vtkm::cont::DataSet GenerateDataSet(unsigned int level, unsigned int amrIndex) const;
vtkm::IdComponent Dimension;
vtkm::IdComponent CellsPerDimension;
vtkm::IdComponent NumberOfLevels;
};
} //namespace source
} //namespace vtkm
#endif //vtk_m_source_Amr_h

@ -9,6 +9,7 @@
##============================================================================
set(headers
Amr.h
Oscillator.h
Source.h
Tangle.h
@ -17,6 +18,7 @@ set(headers
)
set(device_sources
Amr.cxx
Oscillator.cxx
Source.cxx
Tangle.cxx
@ -25,11 +27,12 @@ set(device_sources
)
vtkm_library(NAME vtkm_source
SOURCES ${sources}
DEVICE_SOURCES ${device_sources}
HEADERS ${headers}
)
target_link_libraries(vtkm_source PUBLIC vtkm_cont)
target_link_libraries(vtkm_source PUBLIC vtkm_cont vtkm_filter)
#-----------------------------------------------------------------------------
if (VTKm_ENABLE_TESTING)

@ -98,6 +98,7 @@ struct WaveletField : public vtkm::worklet::WorkletVisitPointsWithCells
Wavelet::Wavelet(vtkm::Id3 minExtent, vtkm::Id3 maxExtent)
: Center{ minExtent - ((minExtent - maxExtent) / 2) }
, Origin{ minExtent }
, Spacing{ 1. }
, Frequency{ 60., 30., 40. }
, Magnitude{ 10., 18., 5. }
@ -108,17 +109,16 @@ Wavelet::Wavelet(vtkm::Id3 minExtent, vtkm::Id3 maxExtent)
{
}
vtkm::cont::DataSet Wavelet::Execute() const
template <vtkm::IdComponent Dim>
vtkm::cont::DataSet Wavelet::GenerateDataSet(vtkm::cont::CoordinateSystem coords) const
{
VTKM_LOG_SCOPE_FUNCTION(vtkm::cont::LogLevel::Perf);
// Create points:
const vtkm::Id3 dims{ this->MaximumExtent - this->MinimumExtent + vtkm::Id3{ 1 } };
const vtkm::Vec3f origin{ this->MinimumExtent };
vtkm::cont::CoordinateSystem coords{ "coordinates", dims, origin, this->Spacing };
// And cells:
vtkm::cont::CellSetStructured<3> cellSet;
vtkm::Vec<vtkm::Id, Dim> dims;
for (unsigned int d = 0; d < Dim; d++)
{
dims[d] = this->MaximumExtent[d] - this->MinimumExtent[d] + 1;
}
vtkm::cont::CellSetStructured<Dim> cellSet;
cellSet.SetPointDimensions(dims);
// Compile the dataset:
@ -133,7 +133,27 @@ vtkm::cont::DataSet Wavelet::Execute() const
return dataSet;
}
vtkm::cont::Field Wavelet::GeneratePointField(const vtkm::cont::CellSetStructured<3>& cellset,
vtkm::cont::DataSet Wavelet::Execute() const
{
VTKM_LOG_SCOPE_FUNCTION(vtkm::cont::LogLevel::Perf);
// Create points:
const vtkm::Id3 dims{ this->MaximumExtent - this->MinimumExtent + vtkm::Id3{ 1 } };
vtkm::cont::CoordinateSystem coords{ "coordinates", dims, this->Origin, this->Spacing };
// Compile the dataset:
if (this->MaximumExtent[2] - this->MinimumExtent[2] < vtkm::Epsilon<vtkm::FloatDefault>())
{
return this->GenerateDataSet<2>(coords);
}
else
{
return this->GenerateDataSet<3>(coords);
}
}
template <vtkm::IdComponent Dim>
vtkm::cont::Field Wavelet::GeneratePointField(const vtkm::cont::CellSetStructured<Dim>& cellset,
const std::string& name) const
{
const vtkm::Id3 dims{ this->MaximumExtent - this->MinimumExtent + vtkm::Id3{ 1 } };

@ -53,6 +53,8 @@ namespace source
* - `MaximumValue`: 255
* - `Frequency`: { 60, 30, 40 }
* - `Magnitude`: { 10, 18, 5 }
*
* If the extent has zero length in the z-direction, a 2D dataset is generated.
*/
class VTKM_SOURCE_EXPORT Wavelet final : public vtkm::source::Source
{
@ -62,6 +64,8 @@ public:
VTKM_CONT void SetCenter(const vtkm::Vec<FloatDefault, 3>& center) { this->Center = center; }
VTKM_CONT void SetOrigin(const vtkm::Vec<FloatDefault, 3>& origin) { this->Origin = origin; }
VTKM_CONT void SetSpacing(const vtkm::Vec<FloatDefault, 3>& spacing) { this->Spacing = spacing; }
VTKM_CONT void SetFrequency(const vtkm::Vec<FloatDefault, 3>& frequency)
@ -94,10 +98,15 @@ public:
vtkm::cont::DataSet Execute() const;
private:
vtkm::cont::Field GeneratePointField(const vtkm::cont::CellSetStructured<3>& cellset,
template <vtkm::IdComponent Dim>
vtkm::cont::Field GeneratePointField(const vtkm::cont::CellSetStructured<Dim>& cellset,
const std::string& name) const;
template <vtkm::IdComponent Dim>
vtkm::cont::DataSet GenerateDataSet(vtkm::cont::CoordinateSystem coords) const;
vtkm::Vec3f Center;
vtkm::Vec3f Origin;
vtkm::Vec3f Spacing;
vtkm::Vec3f Frequency;
vtkm::Vec3f Magnitude;