Commit 7533f90d authored by Robert Maynard's avatar Robert Maynard Committed by Kitware Robot

Merge topic 'improve_vtkm_sources'

3ef234ef Move Oscillator to the sources directory
5c69f1ba Update Wavelet to use WorkletVisitPointsWithCells
62357dea Tangle source has better runtime performance
eb3d8665 Add a test explicitly for vtkm::source::Tangle
63f24380 Add vtkm::source::Wavelet as a new source
257dc1f8 Sources have a more consistent API and internal style.
2d455bbe Document what the Tangle source will generate
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !1850
parents 9775e223 3ef234ef
......@@ -46,8 +46,8 @@
#include <vtkm/io/reader/VTKDataSetReader.h>
#include <vtkm/source/Wavelet.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WaveletGenerator.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <cctype> // for std::tolower
......@@ -1357,10 +1357,10 @@ int BenchmarkBody(int argc, char** argv, const vtkm::cont::InitializeResult& con
{
std::cout << "Generating " << waveletDim << "x" << waveletDim << "x" << waveletDim
<< " wavelet...\n";
vtkm::worklet::WaveletGenerator gen;
gen.SetExtent({ 0 }, { waveletDim });
vtkm::source::Wavelet source;
source.SetExtent({ 0 }, { waveletDim });
InputDataSet = gen.GenerateDataSet(config.Device);
InputDataSet = source.Execute();
}
if (tetra)
......
......@@ -42,7 +42,7 @@ set(benchmarks
)
foreach (benchmark ${benchmarks})
add_benchmark(NAME ${benchmark} FILE ${benchmark}.cxx LIBS vtkm_filter)
add_benchmark(NAME ${benchmark} FILE ${benchmark}.cxx LIBS vtkm_source vtkm_filter)
endforeach ()
if(TARGET vtkm_rendering)
......
......@@ -14,7 +14,7 @@ project(Oscillator CXX)
find_package(VTKm REQUIRED QUIET)
add_executable(Oscillator Oscillator.cxx)
target_link_libraries(Oscillator PRIVATE vtkm_filter)
target_link_libraries(Oscillator PRIVATE vtkm_source)
vtkm_add_target_information(Oscillator
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES Oscillator.cxx)
......@@ -22,7 +22,7 @@
#include <vtkm/cont/TryExecute.h>
#include <vtkm/filter/OscillatorSource.h>
#include <vtkm/source/Oscillator.h>
#if !defined(_WIN32) || defined(__CYGWIN__)
#include <unistd.h> /* unlink */
......@@ -58,7 +58,7 @@ static inline std::string& trim(std::string& s)
// ----------------------------------------------------------------------------
void read_oscillators(std::string filePath, vtkm::filter::OscillatorSource& filter)
void read_oscillators(std::string filePath, vtkm::source::Oscillator& source)
{
std::ifstream in(filePath);
if (!in)
......@@ -87,15 +87,15 @@ void read_oscillators(std::string filePath, vtkm::filter::OscillatorSource& filt
if (stype == "damped")
{
filter.AddDamped(x, y, z, r, omega0, zeta);
source.AddDamped(x, y, z, r, omega0, zeta);
}
else if (stype == "decaying")
{
filter.AddDecaying(x, y, z, r, omega0, zeta);
source.AddDecaying(x, y, z, r, omega0, zeta);
}
else if (stype == "periodic")
{
filter.AddPeriodic(x, y, z, r, omega0, zeta);
source.AddPeriodic(x, y, z, r, omega0, zeta);
}
}
}
......@@ -303,22 +303,19 @@ int main(int argc, char** argv)
std::cout << " - end: " << endTime << std::endl;
std::cout << "=======================================\n" << std::endl;
vtkm::cont::DataSetBuilderUniform builder;
vtkm::cont::DataSet dataset = builder.Create(vtkm::Id3(sizeX, sizeY, sizeZ));
vtkm::filter::OscillatorSource filter;
read_oscillators(oscillatorConfigFile, filter);
vtkm::source::Oscillator source(vtkm::Id3{ sizeX, sizeY, sizeZ });
read_oscillators(oscillatorConfigFile, source);
std::cout << "=========== start computation ============" << std::endl;
int count = 0;
while (currentTime < endTime)
{
filter.SetTime(currentTime);
vtkm::cont::DataSet rdata = filter.Execute(dataset);
source.SetTime(currentTime);
vtkm::cont::DataSet rdata = source.Execute();
if (generateOutput)
{
vtkm::cont::ArrayHandle<vtkm::Float64> tmp;
rdata.GetField("oscillation", vtkm::cont::Field::Association::POINTS).GetData().CopyTo(tmp);
rdata.GetField("scalars", vtkm::cont::Field::Association::POINTS).GetData().CopyTo(tmp);
double* values = tmp.GetStorage().GetArray();
writeData(outputDirectory, count++, sizeX, sizeY, sizeZ, values);
}
......
......@@ -49,7 +49,6 @@ set(headers
MeshQuality.h
NDEntropy.h
NDHistogram.h
OscillatorSource.h
Pathline.h
PointAverage.h
PointElevation.h
......@@ -115,7 +114,6 @@ set(header_template_sources
MeshQuality.hxx
NDEntropy.hxx
NDHistogram.hxx
OscillatorSource.hxx
Pathline.hxx
PointAverage.hxx
PointElevation.hxx
......
......@@ -15,7 +15,7 @@
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/worklet/WaveletGenerator.h>
#include <vtkm/source/Wavelet.h>
namespace
{
......@@ -115,13 +115,11 @@ vtkm::cont::DataSet Make3DExplicitSimpleCube()
vtkm::cont::DataSet Make3DWavelet()
{
vtkm::worklet::WaveletGenerator wavelet;
wavelet.SetMinimumExtent({ -25 });
wavelet.SetMaximumExtent({ 25 });
vtkm::source::Wavelet wavelet({ -25 }, { 25 });
wavelet.SetFrequency({ 60, 30, 40 });
wavelet.SetMagnitude({ 5 });
vtkm::cont::DataSet result = wavelet.GenerateDataSet();
vtkm::cont::DataSet result = wavelet.Execute();
return result;
}
......
......@@ -9,12 +9,17 @@
##============================================================================
set(headers
Oscillator.h
Source.h
Tangle.h
Wavelet.h
)
set(device_sources
Oscillator.cxx
Source.cxx
Tangle.cxx
Wavelet.cxx
)
vtkm_library(NAME vtkm_source
......@@ -22,4 +27,7 @@ vtkm_library(NAME vtkm_source
HEADERS ${headers}
)
target_link_libraries(vtkm_source PUBLIC vtkm_worklet)
target_link_libraries(vtkm_source PUBLIC vtkm_cont)
#-----------------------------------------------------------------------------
add_subdirectory(testing)
......@@ -7,75 +7,88 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/source/Oscillator.h>
namespace vtkm
{
namespace filter
namespace source
{
//-----------------------------------------------------------------------------
inline VTKM_CONT OscillatorSource::OscillatorSource()
: Worklet()
Oscillator::Oscillator(vtkm::Id3 dims)
: Dims(dims)
, Worklet()
{
this->SetUseCoordinateSystemAsField(true);
this->SetOutputFieldName("oscillation");
}
//-----------------------------------------------------------------------------
inline VTKM_CONT void OscillatorSource::SetTime(vtkm::Float64 time)
void Oscillator::SetTime(vtkm::Float64 time)
{
this->Worklet.SetTime(time);
}
//-----------------------------------------------------------------------------
inline VTKM_CONT void OscillatorSource::AddPeriodic(vtkm::Float64 x,
vtkm::Float64 y,
vtkm::Float64 z,
vtkm::Float64 radius,
vtkm::Float64 omega,
vtkm::Float64 zeta)
void Oscillator::AddPeriodic(vtkm::Float64 x,
vtkm::Float64 y,
vtkm::Float64 z,
vtkm::Float64 radius,
vtkm::Float64 omega,
vtkm::Float64 zeta)
{
this->Worklet.AddPeriodic(x, y, z, radius, omega, zeta);
}
//-----------------------------------------------------------------------------
inline VTKM_CONT void OscillatorSource::AddDamped(vtkm::Float64 x,
vtkm::Float64 y,
vtkm::Float64 z,
vtkm::Float64 radius,
vtkm::Float64 omega,
vtkm::Float64 zeta)
void Oscillator::AddDamped(vtkm::Float64 x,
vtkm::Float64 y,
vtkm::Float64 z,
vtkm::Float64 radius,
vtkm::Float64 omega,
vtkm::Float64 zeta)
{
this->Worklet.AddDamped(x, y, z, radius, omega, zeta);
}
//-----------------------------------------------------------------------------
inline VTKM_CONT void OscillatorSource::AddDecaying(vtkm::Float64 x,
vtkm::Float64 y,
vtkm::Float64 z,
vtkm::Float64 radius,
vtkm::Float64 omega,
vtkm::Float64 zeta)
void Oscillator::AddDecaying(vtkm::Float64 x,
vtkm::Float64 y,
vtkm::Float64 z,
vtkm::Float64 radius,
vtkm::Float64 omega,
vtkm::Float64 zeta)
{
this->Worklet.AddDecaying(x, y, z, radius, omega, zeta);
}
//-----------------------------------------------------------------------------
template <typename T, typename StorageType, typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::DataSet OscillatorSource::DoExecute(
const vtkm::cont::DataSet& inDataSet,
const vtkm::cont::ArrayHandle<T, StorageType>& field,
const vtkm::filter::FieldMetadata& fieldMetadata,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
vtkm::cont::DataSet Oscillator::Execute() const
{
VTKM_LOG_SCOPE_FUNCTION(vtkm::cont::LogLevel::Perf);
vtkm::cont::DataSet dataSet;
vtkm::cont::CellSetStructured<3> cellSet;
cellSet.SetPointDimensions(this->Dims);
dataSet.SetCellSet(cellSet);
const vtkm::Vec3f origin(0.0f, 0.0f, 0.0f);
const vtkm::Vec3f spacing(1.0f / static_cast<vtkm::FloatDefault>(this->Dims[0]),
1.0f / static_cast<vtkm::FloatDefault>(this->Dims[1]),
1.0f / static_cast<vtkm::FloatDefault>(this->Dims[2]));
const vtkm::Id3 pdims{ this->Dims + vtkm::Id3{ 1, 1, 1 } };
vtkm::cont::ArrayHandleUniformPointCoordinates coordinates(pdims, origin, spacing);
dataSet.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", coordinates));
vtkm::cont::ArrayHandle<vtkm::Float64> outArray;
//todo, we need to use the policy to determine the valid conversions
//that the dispatcher should do
this->Invoke(this->Worklet, field, outArray);
this->Invoke(this->Worklet, coordinates, outArray);
dataSet.AddField(vtkm::cont::make_FieldPoint("scalars", outArray));
return CreateResult(inDataSet, outArray, this->GetOutputFieldName(), fieldMetadata);
return dataSet;
}
}
} // namespace vtkm::filter
......@@ -7,30 +7,31 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_filter_OscillatorSource_h
#define vtk_m_filter_OscillatorSource_h
#ifndef vtk_m_source_OscillatorSource_h
#define vtk_m_source_OscillatorSource_h
#include <vtkm/filter/FilterField.h>
#include <vtkm/source/Source.h>
#include <vtkm/worklet/OscillatorSource.h>
namespace vtkm
{
namespace filter
namespace source
{
/**\brief An analytical, time-varying array-source filter.
*
* This filter will create a new array (named "oscillation" by default)
* that evaluates to a sum of time-varying Gaussian exponentials
* specified in its configuration.
*/
class OscillatorSource : public vtkm::filter::FilterField<OscillatorSource>
/**\brief An analytical, time-varying uniform dataset with a point based array
*
* The Execute method creates a complete structured dataset that have a
* point field names 'scalars'
*
* This array is based on the coordinates and evaluates to a sum of time-varying
* Gaussian exponentials specified in its configuration.
*/
class VTKM_SOURCE_EXPORT Oscillator final : public vtkm::source::Source
{
public:
using SupportedTypes = vtkm::TypeListTagFieldVec3;
///Construct a Oscillator with Cell Dimensions
VTKM_CONT
OscillatorSource();
Oscillator(vtkm::Id3 dims);
VTKM_CONT
void SetTime(vtkm::Float64 time);
......@@ -59,18 +60,13 @@ public:
vtkm::Float64 omega,
vtkm::Float64 zeta);
template <typename T, typename StorageType, typename DerivedPolicy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input,
const vtkm::cont::ArrayHandle<T, StorageType>& field,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
VTKM_CONT vtkm::cont::DataSet Execute() const;
private:
vtkm::Id3 Dims;
vtkm::worklet::OscillatorSource Worklet;
};
}
}
#include <vtkm/filter/OscillatorSource.hxx>
#endif // vtk_m_filter_OscillatorSource_h
#endif // vtk_m_source_Oscillator_h
//============================================================================
// 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/source/Source.h>
namespace vtkm
{
namespace source
{
//Fix the vtable for Source to be in the vtkm_source library
Source::Source() = default;
Source::~Source() = default;
} // namespace source
} // namespace vtkm
......@@ -12,21 +12,26 @@
#define vtk_m_source_Source_h
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/Invoker.h>
#include <vtkm/source/vtkm_source_export.h>
namespace vtkm
{
namespace source
{
class Source
class VTKM_SOURCE_EXPORT Source
{
public:
VTKM_CONT
Source() {}
Source();
VTKM_CONT
~Source() {}
virtual ~Source();
virtual vtkm::cont::DataSet Execute() const = 0;
protected:
vtkm::cont::Invoker Invoke;
};
} // namespace source
......
......@@ -8,8 +8,8 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/source/Tangle.h>
#include <vtkm/worklet/WorkletMapField.h>
namespace vtkm
{
......@@ -17,51 +17,39 @@ namespace source
{
namespace tangle
{
class TangleField : public vtkm::worklet::WorkletMapField
class TangleField : public vtkm::worklet::WorkletVisitPointsWithCells
{
public:
using ControlSignature = void(FieldIn vertexId, FieldOut v);
using ExecutionSignature = void(_1, _2);
using ControlSignature = void(CellSetIn, FieldOut v);
using ExecutionSignature = void(ThreadIndices, _2);
using InputDomain = _1;
const vtkm::Id xdim, ydim, zdim;
const vtkm::FloatDefault xmin, ymin, zmin, xmax, ymax, zmax;
const vtkm::Id cellsPerLayer;
const vtkm::Vec3f CellDimsf;
const vtkm::Vec3f Mins;
const vtkm::Vec3f Maxs;
VTKM_CONT
TangleField(const vtkm::Id3 dims,
const vtkm::FloatDefault mins[3],
const vtkm::FloatDefault maxs[3])
: xdim(dims[0])
, ydim(dims[1])
, zdim(dims[2])
, xmin(mins[0])
, ymin(mins[1])
, zmin(mins[2])
, xmax(maxs[0])
, ymax(maxs[1])
, zmax(maxs[2])
, cellsPerLayer((xdim) * (ydim))
TangleField(const vtkm::Id3& cdims, const vtkm::Vec3f& mins, const vtkm::Vec3f& maxs)
: CellDimsf(static_cast<vtkm::FloatDefault>(cdims[0]),
static_cast<vtkm::FloatDefault>(cdims[1]),
static_cast<vtkm::FloatDefault>(cdims[2]))
, Mins(mins)
, Maxs(maxs)
{
}
VTKM_EXEC
void operator()(const vtkm::Id& vertexId, vtkm::Float32& v) const
template <typename ThreadIndexType>
VTKM_EXEC void operator()(const ThreadIndexType& threadIndex, vtkm::Float32& v) const
{
const vtkm::Id x = vertexId % (xdim);
const vtkm::Id y = (vertexId / (xdim)) % (ydim);
const vtkm::Id z = vertexId / cellsPerLayer;
//We are operating on a 3d structured grid. This means that the threadIndex has
//efficiently computed the i,j,k of the point current point for us
const vtkm::Id3 ijk = threadIndex.GetInputIndex3D();
const vtkm::Vec3f xyzf = static_cast<vtkm::Vec3f>(ijk) / this->CellDimsf;
const vtkm::FloatDefault fx =
static_cast<vtkm::FloatDefault>(x) / static_cast<vtkm::FloatDefault>(xdim - 1);
const vtkm::FloatDefault fy =
static_cast<vtkm::FloatDefault>(y) / static_cast<vtkm::FloatDefault>(xdim - 1);
const vtkm::FloatDefault fz =
static_cast<vtkm::FloatDefault>(z) / static_cast<vtkm::FloatDefault>(xdim - 1);
const vtkm::Float32 xx = 3.0f * vtkm::Float32(xmin + (xmax - xmin) * (fx));
const vtkm::Float32 yy = 3.0f * vtkm::Float32(ymin + (ymax - ymin) * (fy));
const vtkm::Float32 zz = 3.0f * vtkm::Float32(zmin + (zmax - zmin) * (fz));
const vtkm::Vec3f_32 values = 3.0f * vtkm::Vec3f_32(Mins + (Maxs - Mins) * xyzf);
const vtkm::Float32& xx = values[0];
const vtkm::Float32& yy = values[1];
const vtkm::Float32& zz = values[2];
v = (xx * xx * xx * xx - 5.0f * xx * xx + yy * yy * yy * yy - 5.0f * yy * yy +
zz * zz * zz * zz - 5.0f * zz * zz + 11.8f) *
......@@ -71,40 +59,35 @@ public:
};
} // namespace tangle
VTKM_SOURCE_EXPORT
vtkm::cont::DataSet Tangle::Execute() const
{
VTKM_LOG_SCOPE_FUNCTION(vtkm::cont::LogLevel::Perf);
vtkm::cont::DataSet dataSet;
const vtkm::Id3 vdims{ this->Dims + vtkm::Id3{ 1, 1, 1 } };
const vtkm::Id3 pdims{ this->Dims + vtkm::Id3{ 1, 1, 1 } };
const vtkm::Vec3f mins = { -1.0f, -1.0f, -1.0f };
const vtkm::Vec3f maxs = { 1.0f, 1.0f, 1.0f };
vtkm::FloatDefault mins[3] = { -1.0f, -1.0f, -1.0f };
vtkm::FloatDefault maxs[3] = { 1.0f, 1.0f, 1.0f };
vtkm::cont::CellSetStructured<3> cellSet;
cellSet.SetPointDimensions(pdims);
dataSet.SetCellSet(cellSet);
vtkm::cont::ArrayHandle<vtkm::Float32> pointFieldArray;
vtkm::cont::ArrayHandleIndex vertexCountImplicitArray(vdims[0] * vdims[1] * vdims[2]);
vtkm::worklet::DispatcherMapField<tangle::TangleField> tangleFieldDispatcher(
tangle::TangleField(vdims, mins, maxs));
tangleFieldDispatcher.Invoke(vertexCountImplicitArray, pointFieldArray);
this->Invoke(tangle::TangleField{ this->Dims, mins, maxs }, cellSet, pointFieldArray);
vtkm::Id numCells = Dims[0] * Dims[1] * Dims[2];
vtkm::cont::ArrayHandle<vtkm::FloatDefault> cellFieldArray;
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(0, 1, numCells),
cellFieldArray);
vtkm::cont::ArrayCopy(
vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(0, 1, cellSet.GetNumberOfCells()),
cellFieldArray);
vtkm::Vec3f origin(0.0f, 0.0f, 0.0f);
vtkm::Vec3f spacing(1.0f / static_cast<vtkm::FloatDefault>(Dims[0]),
1.0f / static_cast<vtkm::FloatDefault>(Dims[1]),
1.0f / static_cast<vtkm::FloatDefault>(Dims[2]));
const vtkm::Vec3f origin(0.0f, 0.0f, 0.0f);
const vtkm::Vec3f spacing(1.0f / static_cast<vtkm::FloatDefault>(this->Dims[0]),
1.0f / static_cast<vtkm::FloatDefault>(this->Dims[1]),
1.0f / static_cast<vtkm::FloatDefault>(this->Dims[2]));
vtkm::cont::ArrayHandleUniformPointCoordinates coordinates(vdims, origin, spacing);
vtkm::cont::ArrayHandleUniformPointCoordinates coordinates(pdims, origin, spacing);
dataSet.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", coordinates));
static constexpr vtkm::IdComponent ndim = 3;
vtkm::cont::CellSetStructured<ndim> cellSet;
cellSet.SetPointDimensions(vdims);
dataSet.SetCellSet(cellSet);
dataSet.AddField(vtkm::cont::make_FieldPoint("nodevar", pointFieldArray));
dataSet.AddField(vtkm::cont::make_FieldCell("cellvar", cellFieldArray));
......
......@@ -17,16 +17,27 @@ namespace vtkm
{
namespace source
{
class Tangle : public vtkm::source::Source
/**
* @brief The Tangle source creates a uniform dataset.
*
* This class generates a predictable uniform grid dataset with an
* interesting set of point and cell scalar arrays, which is useful
* for testing and benchmarking.
*
* The Execute method creates a complete structured dataset that have a
* point field named 'nodevar', and a cell field named 'cellvar'.
*
**/
class VTKM_SOURCE_EXPORT Tangle final : public vtkm::source::Source
{
public:
///Construct a Tangle with Cell Dimensions
VTKM_CONT
Tangle(vtkm::Id3 dims)
: Dims(dims)
{
}
VTKM_SOURCE_EXPORT
vtkm::cont::DataSet Execute() const;
private:
......@@ -35,4 +46,4 @@ private:
} //namespace source
} //namespace vtkm
#endif //VTKM_TANGLE_H
#endif //vtk_m_source_Tangle_h
//============================================================================
// 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/source/Wavelet.h>
#include <vtkm/worklet/WorkletMapField.h>
namespace
{
inline vtkm::FloatDefault computeScaleFactor(vtkm::Id min, vtkm::Id max)
{
return (min < max) ? (1.f / static_cast<vtkm::FloatDefault>(max - min))
: static_cast<vtkm::FloatDefault>(1.);
}
}
namespace vtkm
{
namespace source
{
namespace wavelet
{
struct WaveletField : public vtkm::worklet::WorkletVisitPointsWithCells
{
using ControlSignature = void(CellSetIn, FieldOut v);
using ExecutionSignature = void(ThreadIndices, _2);
using InputDomain = _1;
using Vec3F = vtkm::Vec3f;
Vec3F Center;
Vec3F Spacing;
Vec3F Frequency;
Vec3F Magnitude;
Vec3F MinimumPoint;
Vec3F Scale;
vtkm::Id3 Offset;
vtkm::Id3 Dims;
vtkm::FloatDefault MaximumValue;
vtkm::FloatDefault Temp2;
WaveletField(const Vec3F& center,
const Vec3F& spacing,
const Vec3F& frequency,
const Vec3F& magnitude,
const Vec3F& minimumPoint,
const Vec3F& scale,
const vtkm::Id3& offset,
const vtkm::Id3& dims,
vtkm::FloatDefault maximumValue,
vtkm::FloatDefault temp2)
: Center(center)
, Spacing(spacing)
, Frequency(frequency)
, Magnitude(magnitude)
, MinimumPoint(minimumPoint)
, Scale(scale)
, Offset(offset)
, Dims(dims)
, MaximumValue(maximumValue)
, Temp2(temp2)
{
}
template <typename ThreadIndexType>
VTKM_EXEC void operator()(const ThreadIndexType& threadIndex, vtkm::FloatDefault& scalar) const
{
const vtkm::Id3 ijk = threadIndex.GetInputIndex3D();
// map ijk to the point location, accounting for spacing:
const Vec3F loc = Vec3F(ijk + this->Offset) * this->Spacing;
// Compute the distance from the center of the gaussian:
const Vec3F scaledLoc = (this->Center - loc) * this->Scale;
vtkm::FloatDefault gaussSum = vtkm::Dot(scaledLoc, scaledLoc);
const Vec3F periodicContribs{
this->Magnitude[0] * vtkm::Sin(this->Frequency[0] * scaledLoc[0]),
this->Magnitude[1] * vtkm::Sin(this->Frequency[1] * scaledLoc[1]),
this->Magnitude[2] * vtkm::Cos(this->Frequency[2] * scaledLoc[2]),
};
// The vtkRTAnalyticSource documentation says the periodic contributions
// should be multiplied in, but the implementation adds them. We'll do as
// they do, not as they say.
scalar =
this->MaximumValue * vtkm::Exp(-gaussSum * this->Temp2) + vtkm::ReduceSum(periodicContribs);
}
};
} // namespace wavelet
Wavelet::Wavelet(vtkm::Id3 minExtent, vtkm::Id3 maxExtent)
: Center{ minExtent - ((minExtent - maxExtent) / 2) }
, Spacing{ 1. }
, Frequency{ 60., 30., 40. }
, Magnitude{ 10., 18., 5. }
, MinimumExtent{ minExtent }
, MaximumExtent{ maxExtent }
, MaximumValue{ 255. }
, StandardDeviation{ 0.5 }
{
}
vtkm::cont::DataSet Wavelet::Execute() const
{