Merge branch 'master' into uniform_real

This commit is contained in:
Li-Ta Lo 2020-06-18 11:46:18 -06:00
commit 01a4486638
29 changed files with 777 additions and 285 deletions

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

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2bb3d36ea5ecef5e7ef1057d0dddebbc590424915083091ead3dac2928000524
size 2904465

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

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2cbdf56fd5445ddc5b6bc05507b8825fb8d74fe1ccce894bde03e5ff2ecf5fb6
size 525141

@ -72,7 +72,7 @@ using IsValidArrayHandle =
/// with C++11 type_traits.
///
template <typename T, typename StorageTag>
using IsInValidArrayHandle =
using IsInvalidArrayHandle =
std::integral_constant<bool, !IsValidArrayHandle<T, StorageTag>::value>;
/// Checks to see if the ArrayHandle allows writing, as some ArrayHandles

@ -30,6 +30,176 @@ namespace vtkm
{
namespace cont
{
/// \brief VariantArrayHandle superclass holding common operations.
///
/// `VariantArrayHandleCommon` is a superclass to all `VariantArrayHandleBase`
/// and `VariantArrayHandle` classes. It contains all operations that are
/// independent of the type lists defined for these templated class or has
/// versions of methods that allow you to specify type lists.
///
/// See the documentation of `VariantArrayHandleBase` for more information.
///
class VTKM_ALWAYS_EXPORT VariantArrayHandleCommon
{
std::shared_ptr<vtkm::cont::internal::VariantArrayHandleContainerBase> ArrayContainer;
public:
VTKM_CONT VariantArrayHandleCommon() = default;
template <typename T, typename Storage>
VTKM_CONT VariantArrayHandleCommon(const vtkm::cont::ArrayHandle<T, Storage>& array)
: ArrayContainer(std::make_shared<internal::VariantArrayHandleContainer<T>>(
vtkm::cont::ArrayHandleVirtual<T>{ array }))
{
}
template <typename T>
VTKM_CONT VariantArrayHandleCommon(
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagVirtual>& array)
: ArrayContainer(std::make_shared<internal::VariantArrayHandleContainer<T>>(array))
{
}
/// Returns true if this array matches the array handle type passed in.
///
template <typename ArrayHandleType>
VTKM_CONT bool IsType() const
{
return internal::variant::IsType<ArrayHandleType>(this->ArrayContainer.get());
}
/// Returns true if this array matches the ValueType type passed in.
///
template <typename T>
VTKM_CONT bool IsValueType() const
{
return internal::variant::IsValueType<T>(this->ArrayContainer.get());
}
/// Returns this array cast to the given \c ArrayHandle type. Throws \c
/// ErrorBadType if the cast does not work. Use \c IsType
/// to check if the cast can happen.
///
template <typename ArrayHandleType>
VTKM_CONT ArrayHandleType Cast() const
{
return internal::variant::Cast<ArrayHandleType>(this->ArrayContainer.get());
}
/// \brief Call a functor using the underlying array type.
///
/// `CastAndCall` attempts to cast the held array to a specific value type,
/// and then calls the given functor with the cast array. You must specify
/// the `TypeList` and `StorageList` as template arguments. (Note that this
/// calling differs from that of the `CastAndCall` methods of subclasses.)
///
template <typename TypeList, typename StorageList, typename Functor, typename... Args>
VTKM_CONT void CastAndCall(Functor&& functor, Args&&... args) const;
/// Returns this array cast to a `ArrayHandleVirtual` of the given type.
/// This will perform type conversions as necessary, and will log warnings
/// if the conversion is lossy.
///
/// This method internally uses `CastAndCall`. A custom storage tag list may
/// be specified in the second template parameter, which will be passed to
/// the CastAndCall. You can also specify a list of types to try as the optional
/// third template argument.
///
template <typename T,
typename StorageList = VTKM_DEFAULT_STORAGE_LIST,
typename TypeList = vtkm::List<T>>
VTKM_CONT vtkm::cont::ArrayHandleVirtual<T> AsVirtual() const
{
VTKM_IS_LIST(StorageList);
VTKM_IS_LIST(TypeList);
vtkm::cont::internal::variant::ForceCastToVirtual caster;
vtkm::cont::ArrayHandleVirtual<T> output;
this->CastAndCall<TypeList, StorageList>(caster, output);
return output;
}
/// Returns this array cast to a `ArrayHandleMultiplexer` of the given type.
/// This will attempt to cast the internal array to each supported type of
/// the multiplexer. If none are supported, an invalid ArrayHandleMultiplexer
/// is returned.
///
/// As a special case, if one of the arrays in the `ArrayHandleMultiplexer`'s
/// type list is an `ArrayHandleCast`, then the multiplexer will look for type
/// type of array being cast rather than an actual cast array.
///
///@{
template <typename... T>
VTKM_CONT void AsMultiplexer(vtkm::cont::ArrayHandleMultiplexer<T...>& result) const;
template <typename ArrayHandleMultiplexerType>
VTKM_CONT ArrayHandleMultiplexerType AsMultiplexer() const
{
ArrayHandleMultiplexerType result;
this->AsMultiplexer(result);
return result;
}
///@}
/// Given a references to an ArrayHandle object, casts this array to the
/// ArrayHandle's type and sets the given ArrayHandle to this array. Throws
/// `ErrorBadType` if the cast does not work. Use `IsType` to check
/// if the cast can happen.
///
/// Note that this is a shallow copy. The data are not copied and a change
/// in the data in one array will be reflected in the other.
///
template <typename ArrayHandleType>
VTKM_CONT void CopyTo(ArrayHandleType& array) const
{
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
array = this->Cast<ArrayHandleType>();
}
/// \brief Create a new array of the same type as this array.
///
/// This method creates a new array that is the same type as this one and
/// returns a new variant array handle for it. This method is convenient when
/// creating output arrays that should be the same type as some input array.
///
VTKM_CONT VariantArrayHandleCommon NewInstance() const
{
VariantArrayHandleCommon instance;
instance.ArrayContainer = this->ArrayContainer->NewInstance();
return instance;
}
/// Releases any resources being used in the execution environment (that are
/// not being shared by the control environment).
///
void ReleaseResourcesExecution() { return this->ArrayContainer->ReleaseResourcesExecution(); }
/// Releases all resources in both the control and execution environments.
///
void ReleaseResources() { return this->ArrayContainer->ReleaseResources(); }
/// \brief Get the number of components in each array value.
///
/// This method will query the array type for the number of components in
/// each value of the array. The number of components is determined by
/// the \c VecTraits::NUM_COMPONENTS trait class.
///
VTKM_CONT
vtkm::IdComponent GetNumberOfComponents() const
{
return this->ArrayContainer->GetNumberOfComponents();
}
/// \brief Get the number of values in the array.
///
VTKM_CONT
vtkm::Id GetNumberOfValues() const { return this->ArrayContainer->GetNumberOfValues(); }
VTKM_CONT
void PrintSummary(std::ostream& out) const { this->ArrayContainer->PrintSummary(out); }
};
/// \brief Holds an array handle without having to specify template parameters.
///
/// \c VariantArrayHandle holds an \c ArrayHandle or \c ArrayHandleVirtual
@ -61,32 +231,25 @@ namespace cont
/// component types.
///
template <typename TypeList>
class VTKM_ALWAYS_EXPORT VariantArrayHandleBase
class VTKM_ALWAYS_EXPORT VariantArrayHandleBase : public VariantArrayHandleCommon
{
VTKM_STATIC_ASSERT_MSG((!std::is_same<TypeList, vtkm::ListUniversal>::value),
"Cannot use vtkm::ListUniversal with VariantArrayHandle.");
using Superclass = VariantArrayHandleCommon;
public:
VTKM_CONT
VariantArrayHandleBase() = default;
template <typename T, typename Storage>
VTKM_CONT VariantArrayHandleBase(const vtkm::cont::ArrayHandle<T, Storage>& array)
: ArrayContainer(std::make_shared<internal::VariantArrayHandleContainer<T>>(
vtkm::cont::ArrayHandleVirtual<T>{ array }))
: Superclass(array)
{
}
template <typename T>
explicit VTKM_CONT VariantArrayHandleBase(
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagVirtual>& array)
: ArrayContainer(std::make_shared<internal::VariantArrayHandleContainer<T>>(array))
{
}
template <typename OtherTypeList>
VTKM_CONT explicit VariantArrayHandleBase(const VariantArrayHandleBase<OtherTypeList>& src)
: ArrayContainer(internal::variant::GetContainer::Extract(src))
VTKM_CONT explicit VariantArrayHandleBase(const VariantArrayHandleCommon& src)
: Superclass(src)
{
}
@ -104,32 +267,6 @@ public:
default;
/// Returns true if this array matches the array handle type passed in.
///
template <typename ArrayHandleType>
VTKM_CONT bool IsType() const
{
return internal::variant::IsType<ArrayHandleType>(this->ArrayContainer.get());
}
/// Returns true if this array matches the ValueType type passed in.
///
template <typename T>
VTKM_CONT bool IsValueType() const
{
return internal::variant::IsValueType<T>(this->ArrayContainer.get());
}
/// Returns this array cast to the given \c ArrayHandle type. Throws \c
/// ErrorBadType if the cast does not work. Use \c IsType
/// to check if the cast can happen.
///
template <typename ArrayHandleType>
VTKM_CONT ArrayHandleType Cast() const
{
return internal::variant::Cast<ArrayHandleType>(this->ArrayContainer.get());
}
/// Returns this array cast to a \c ArrayHandleVirtual of the given type.
/// This will perform type conversions as necessary, and will log warnings
/// if the conversion is lossy.
@ -138,51 +275,10 @@ public:
/// be specified in the second template parameter, which will be passed to
/// the CastAndCall.
///
template <typename T, typename StorageTagList = VTKM_DEFAULT_STORAGE_LIST>
template <typename T, typename StorageList = VTKM_DEFAULT_STORAGE_LIST>
VTKM_CONT vtkm::cont::ArrayHandleVirtual<T> AsVirtual() const
{
VTKM_IS_LIST(StorageTagList);
vtkm::cont::internal::variant::ForceCastToVirtual caster;
vtkm::cont::ArrayHandleVirtual<T> output;
this->CastAndCall(StorageTagList{}, caster, output);
return output;
}
/// Returns this array cast to a \c ArrayHandleMultiplexer of the given type.
/// This will attempt to cast the internal array to each supported type of
/// the multiplexer. If none are supported, an invalid ArrayHandleMultiplexer
/// is returned.
///
/// As a special case, if one of the arrays in the \c ArrayHandleMultiplexer's
/// type list is an \c ArrayHandleCast, then the multiplexer will look for type
/// type of array being cast rather than an actual cast array.
///
///@{
template <typename... T>
VTKM_CONT void AsMultiplexer(vtkm::cont::ArrayHandleMultiplexer<T...>& result) const;
template <typename ArrayHandleMultiplexerType>
VTKM_CONT ArrayHandleMultiplexerType AsMultiplexer() const
{
ArrayHandleMultiplexerType result;
this->AsMultiplexer(result);
return result;
}
///@}
/// Given a references to an ArrayHandle object, casts this array to the
/// ArrayHandle's type and sets the given ArrayHandle to this array. Throws
/// \c ErrorBadType if the cast does not work. Use \c
/// ArrayHandleType to check if the cast can happen.
///
/// Note that this is a shallow copy. The data are not copied and a change
/// in the data in one array will be reflected in the other.
///
template <typename ArrayHandleType>
VTKM_CONT void CopyTo(ArrayHandleType& array) const
{
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
array = this->Cast<ArrayHandleType>();
return this->Superclass::AsVirtual<T, StorageList, TypeList>();
}
/// Changes the types to try casting to when resolving this variant array,
@ -202,7 +298,7 @@ public:
//@{
/// \brief Call a functor using the underlying array type.
///
/// \c CastAndCall Attempts to cast the held array to a specific value type,
/// `CastAndCall` attempts to cast the held array to a specific value type,
/// then call the given functor with the cast array. The types
/// tried in the cast are those in the lists defined by the TypeList.
/// By default \c VariantArrayHandle set this to \c VTKM_DEFAULT_TYPE_LIST.
@ -245,59 +341,25 @@ public:
/// returns a new variant array handle for it. This method is convenient when
/// creating output arrays that should be the same type as some input array.
///
VTKM_CONT
VariantArrayHandleBase<TypeList> NewInstance() const
VTKM_CONT VariantArrayHandleBase<TypeList> NewInstance() const
{
VariantArrayHandleBase<TypeList> instance;
instance.ArrayContainer = this->ArrayContainer->NewInstance();
return instance;
return VariantArrayHandleBase<TypeList>(this->Superclass::NewInstance());
}
/// Releases any resources being used in the execution environment (that are
/// not being shared by the control environment).
///
void ReleaseResourcesExecution() { return this->ArrayContainer->ReleaseResourcesExecution(); }
/// Releases all resources in both the control and execution environments.
///
void ReleaseResources() { return this->ArrayContainer->ReleaseResources(); }
/// \brief Get the number of components in each array value.
///
/// This method will query the array type for the number of components in
/// each value of the array. The number of components is determined by
/// the \c VecTraits::NUM_COMPONENTS trait class.
///
VTKM_CONT
vtkm::IdComponent GetNumberOfComponents() const
{
return this->ArrayContainer->GetNumberOfComponents();
}
/// \brief Get the number of values in the array.
///
VTKM_CONT
vtkm::Id GetNumberOfValues() const { return this->ArrayContainer->GetNumberOfValues(); }
VTKM_CONT
void PrintSummary(std::ostream& out) const { this->ArrayContainer->PrintSummary(out); }
private:
friend struct internal::variant::GetContainer;
std::shared_ptr<vtkm::cont::internal::VariantArrayHandleContainerBase> ArrayContainer;
template <typename Functor, typename... Args>
VTKM_CONT void CastAndCallImpl(std::false_type, Functor&& f, Args&&... args) const
{
this->CastAndCallImpl(std::true_type(),
VTKM_DEFAULT_STORAGE_LIST(),
std::forward<Functor>(f),
std::forward<Args>(args)...);
this->Superclass::CastAndCall<TypeList, VTKM_DEFAULT_STORAGE_LIST>(std::forward<Functor>(f),
std::forward<Args>(args)...);
}
template <typename StorageTagList, typename Functor, typename... Args>
VTKM_CONT void CastAndCallImpl(std::true_type, StorageTagList, Functor&& f, Args&&...) const;
template <typename StorageList, typename Functor, typename... Args>
VTKM_CONT void CastAndCallImpl(std::true_type, StorageList, Functor&& f, Args&&... args) const
{
this->Superclass::CastAndCall<TypeList, StorageList>(std::forward<Functor>(f),
std::forward<Args>(args)...);
}
};
using VariantArrayHandle = vtkm::cont::VariantArrayHandleBase<VTKM_DEFAULT_TYPE_LIST>;
@ -395,7 +457,7 @@ struct IsUndefinedStorage
{
};
template <typename T, typename U>
struct IsUndefinedStorage<vtkm::List<T, U>> : vtkm::cont::internal::IsInValidArrayHandle<T, U>
struct IsUndefinedStorage<vtkm::List<T, U>> : vtkm::cont::internal::IsInvalidArrayHandle<T, U>
{
};
@ -408,12 +470,8 @@ using ListDynamicTypes =
template <typename TypeList>
template <typename StorageTagList, typename Functor, typename... Args>
VTKM_CONT void VariantArrayHandleBase<TypeList>::CastAndCallImpl(std::true_type,
StorageTagList,
Functor&& f,
Args&&... args) const
template <typename TypeList, typename StorageTagList, typename Functor, typename... Args>
VTKM_CONT void VariantArrayHandleCommon::CastAndCall(Functor&& f, Args&&... args) const
{
using crossProduct = detail::ListDynamicTypes<TypeList, StorageTagList>;
@ -448,9 +506,9 @@ namespace detail
struct VariantArrayHandleTryMultiplexer
{
template <typename T, typename Storage, typename... TypeList, typename... ArrayTypes>
template <typename T, typename Storage, typename... ArrayTypes>
VTKM_CONT void operator()(const vtkm::cont::ArrayHandle<T, Storage>&,
const vtkm::cont::VariantArrayHandleBase<TypeList...>& self,
const vtkm::cont::VariantArrayHandleCommon& self,
vtkm::cont::ArrayHandleMultiplexer<ArrayTypes...>& result) const
{
vtkm::cont::ArrayHandle<T, Storage> targetArray;
@ -464,15 +522,15 @@ struct VariantArrayHandleTryMultiplexer
}
private:
template <typename T, typename Storage, typename... TypeList>
template <typename T, typename Storage>
VTKM_CONT void FetchArrayExact(vtkm::cont::ArrayHandle<T, Storage>& targetArray,
const vtkm::cont::VariantArrayHandleBase<TypeList...>& self,
const vtkm::cont::VariantArrayHandleCommon& self,
bool& foundArray) const
{
using ArrayType = vtkm::cont::ArrayHandle<T, Storage>;
if (self.template IsType<ArrayType>())
if (self.IsType<ArrayType>())
{
targetArray = self.template Cast<ArrayType>();
targetArray = self.Cast<ArrayType>();
foundArray = true;
}
else
@ -481,9 +539,9 @@ private:
}
}
template <typename T, typename Storage, typename... TypeList>
template <typename T, typename Storage>
VTKM_CONT void FetchArray(vtkm::cont::ArrayHandle<T, Storage>& targetArray,
const vtkm::cont::VariantArrayHandleBase<TypeList...>& self,
const vtkm::cont::VariantArrayHandleCommon& self,
bool& foundArray,
bool vtkmNotUsed(foundArrayInPreviousCall)) const
{
@ -492,17 +550,13 @@ private:
// Special condition for transformed arrays. Instead of pulling out the
// transform, pull out the array that is being transformed.
template <typename T,
typename SrcArray,
typename ForwardTransform,
typename ReverseTransform,
typename... TypeList>
template <typename T, typename SrcArray, typename ForwardTransform, typename ReverseTransform>
VTKM_CONT void FetchArray(
vtkm::cont::ArrayHandle<
T,
vtkm::cont::internal::StorageTagTransform<SrcArray, ForwardTransform, ReverseTransform>>&
targetArray,
const vtkm::cont::VariantArrayHandleBase<TypeList...>& self,
const vtkm::cont::VariantArrayHandleCommon& self,
bool& foundArray,
bool foundArrayInPreviousCall) const
{
@ -526,11 +580,11 @@ private:
// Special condition for cast arrays. Instead of pulling out an ArrayHandleCast, pull out
// the array that is being cast.
template <typename TargetT, typename SourceT, typename SourceStorage, typename... TypeList>
template <typename TargetT, typename SourceT, typename SourceStorage>
VTKM_CONT void FetchArray(
vtkm::cont::ArrayHandle<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceStorage>>&
targetArray,
const vtkm::cont::VariantArrayHandleBase<TypeList...>& self,
const vtkm::cont::VariantArrayHandleCommon& self,
bool& foundArray,
bool foundArrayInPreviousCall) const
{
@ -557,9 +611,8 @@ private:
} // namespace detail
template <typename TypeList>
template <typename... T>
inline VTKM_CONT void VariantArrayHandleBase<TypeList>::AsMultiplexer(
inline VTKM_CONT void VariantArrayHandleCommon::AsMultiplexer(
vtkm::cont::ArrayHandleMultiplexer<T...>& result) const
{
// Make sure IsValid is clear

@ -80,7 +80,7 @@ template <typename Storage>
struct ArrayValidPredicate
{
template <typename T>
using Predicate = vtkm::cont::internal::IsInValidArrayHandle<T, Storage>;
using Predicate = vtkm::cont::internal::IsInvalidArrayHandle<T, Storage>;
};
template <typename TargetT, typename Storage, bool Valid>

@ -12,6 +12,8 @@
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/Pathline.h>
#include <vtkm/filter/Streamline.h>
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/io/VTKDataSetWriter.h>
namespace
{
@ -102,10 +104,95 @@ void TestPathline()
VTKM_TEST_ASSERT(dcells.GetNumberOfCells() == 3, "Wrong number of cells");
}
void TestStreamlineFile(const std::string& fname,
const std::vector<vtkm::Vec3f>& pts,
vtkm::FloatDefault stepSize,
vtkm::Id maxSteps,
const std::vector<vtkm::Vec3f>& endPts)
{
vtkm::io::VTKDataSetReader reader(fname);
vtkm::cont::DataSet ds;
try
{
ds = reader.ReadDataSet();
}
catch (vtkm::io::ErrorIO& e)
{
std::string message("Error reading: ");
message += fname;
message += ", ";
message += e.GetMessage();
VTKM_TEST_FAIL(message.c_str());
}
vtkm::Id numPoints = static_cast<vtkm::Id>(pts.size());
std::vector<vtkm::Particle> seeds;
for (vtkm::Id i = 0; i < numPoints; i++)
seeds.push_back(vtkm::Particle(pts[static_cast<std::size_t>(i)], i));
auto seedArray = vtkm::cont::make_ArrayHandle(seeds);
vtkm::filter::Streamline streamline;
streamline.SetStepSize(stepSize);
streamline.SetNumberOfSteps(maxSteps);
streamline.SetSeeds(seedArray);
streamline.SetActiveField("vec");
auto output = streamline.Execute(ds);
auto coords = output.GetCoordinateSystem().GetData();
vtkm::cont::DynamicCellSet dcells = output.GetCellSet();
VTKM_TEST_ASSERT(dcells.GetNumberOfCells() == numPoints, "Wrong number of cells");
VTKM_TEST_ASSERT(dcells.IsType<vtkm::cont::CellSetExplicit<>>(), "Wrong cell type");
auto cells = dcells.Cast<vtkm::cont::CellSetExplicit<>>();
auto cPortal = coords.ReadPortal();
const vtkm::FloatDefault eps = static_cast<vtkm::FloatDefault>(1e-3);
for (vtkm::Id i = 0; i < numPoints; i++)
{
vtkm::Id numPts = cells.GetNumberOfPointsInCell(i);
std::vector<vtkm::Id> ids(static_cast<std::size_t>(numPts));
cells.GetCellPointIds(i, ids.data());
vtkm::Vec3f e = endPts[static_cast<std::size_t>(i)];
vtkm::Vec3f pt = cPortal.Get(ids[ids.size() - 1]);
VTKM_TEST_ASSERT(vtkm::Magnitude(pt - e) <= eps, "Particle advection point is wrong");
}
}
void TestStreamlineFilters()
{
TestStreamline();
TestPathline();
std::string basePath = vtkm::cont::testing::Testing::GetTestDataBasePath();
//Fusion test.
std::vector<vtkm::Vec3f> fusionPts, fusionEndPts;
fusionPts.push_back(vtkm::Vec3f(0.8f, 0.6f, 0.6f));
fusionPts.push_back(vtkm::Vec3f(0.8f, 0.8f, 0.6f));
fusionPts.push_back(vtkm::Vec3f(0.8f, 0.8f, 0.3f));
//End point values were generated in VisIt.
fusionEndPts.push_back(vtkm::Vec3f(0.5335789918f, 0.87112802267f, 0.6723330020f));
fusionEndPts.push_back(vtkm::Vec3f(0.5601879954f, 0.91389900446f, 0.43989110522f));
fusionEndPts.push_back(vtkm::Vec3f(0.7004770041f, 0.63193398714f, 0.64524400234f));
vtkm::FloatDefault fusionStep = 0.005f;
std::string fusionFile = basePath + "/rectilinear/fusion.vtk";
TestStreamlineFile(fusionFile, fusionPts, fusionStep, 1000, fusionEndPts);
//Fishtank test.
std::vector<vtkm::Vec3f> fishPts, fishEndPts;
fishPts.push_back(vtkm::Vec3f(0.75f, 0.5f, 0.01f));
fishPts.push_back(vtkm::Vec3f(0.4f, 0.2f, 0.7f));
fishPts.push_back(vtkm::Vec3f(0.5f, 0.3f, 0.8f));
//End point values were generated in VisIt.
fishEndPts.push_back(vtkm::Vec3f(0.7734669447f, 0.4870159328f, 0.8979591727f));
fishEndPts.push_back(vtkm::Vec3f(0.7257543206f, 0.1277695596f, 0.7468645573f));
fishEndPts.push_back(vtkm::Vec3f(0.8347796798f, 0.1276152730f, 0.4985143244f));
vtkm::FloatDefault fishStep = 0.001f;
std::string fishFile = basePath + "/rectilinear/fishtank.vtk";
TestStreamlineFile(fishFile, fishPts, fishStep, 100, fishEndPts);
}
}

@ -46,27 +46,34 @@ void VTKRectilinearGridReader::Read()
this->DataFile->Stream >> dim[0] >> dim[1] >> dim[2] >> std::ws;
//Read the points.
std::string dataType;
std::string fileStorageDataType;
std::size_t numPoints[3];
vtkm::cont::VariantArrayHandle X, Y, Z;
// Always read coordinates as vtkm::FloatDefault
std::string readDataType = vtkm::io::internal::DataTypeName<vtkm::FloatDefault>::Name();
this->DataFile->Stream >> tag >> numPoints[0] >> dataType >> std::ws;
this->DataFile->Stream >> tag >> numPoints[0] >> fileStorageDataType >> std::ws;
if (tag != "X_COORDINATES")
throw vtkm::io::ErrorIO("X_COORDINATES tag not found");
X = this->DoReadArrayVariant(vtkm::cont::Field::Association::ANY, readDataType, numPoints[0], 1);
this->DataFile->Stream >> tag >> numPoints[1] >> dataType >> std::ws;
// In binary mode, we must read the data as they are stored in the file.
// In text mode we can parse as FloatDefault no matter the precision of the storage.
X = this->DoReadArrayVariant(
vtkm::cont::Field::Association::ANY, fileStorageDataType, numPoints[0], 1);
this->DataFile->Stream >> tag >> numPoints[1] >> fileStorageDataType >> std::ws;
if (tag != "Y_COORDINATES")
throw vtkm::io::ErrorIO("Y_COORDINATES tag not found");
Y = this->DoReadArrayVariant(vtkm::cont::Field::Association::ANY, readDataType, numPoints[1], 1);
this->DataFile->Stream >> tag >> numPoints[2] >> dataType >> std::ws;
Y = this->DoReadArrayVariant(
vtkm::cont::Field::Association::ANY, fileStorageDataType, numPoints[1], 1);
this->DataFile->Stream >> tag >> numPoints[2] >> fileStorageDataType >> std::ws;
if (tag != "Z_COORDINATES")
throw vtkm::io::ErrorIO("Z_COORDINATES tag not found");
Z = this->DoReadArrayVariant(vtkm::cont::Field::Association::ANY, readDataType, numPoints[2], 1);
Z = this->DoReadArrayVariant(
vtkm::cont::Field::Association::ANY, fileStorageDataType, numPoints[2], 1);
if (dim != vtkm::Id3(static_cast<vtkm::Id>(numPoints[0]),
static_cast<vtkm::Id>(numPoints[1]),
@ -78,14 +85,46 @@ void VTKRectilinearGridReader::Read()
vtkm::cont::ArrayHandle<vtkm::FloatDefault>>
coords;
// We need to store all coordinate arrays as FloatDefault.
vtkm::cont::ArrayHandle<vtkm::FloatDefault> Xc, Yc, Zc;
X.CopyTo(Xc);
Y.CopyTo(Yc);
Z.CopyTo(Zc);
// But the VariantArrayHandle has type fileStorageDataType.
// If the fileStorageDataType is the same as the storage type, no problem:
if (fileStorageDataType == vtkm::io::internal::DataTypeName<vtkm::FloatDefault>::Name())
{
X.CopyTo(Xc);
Y.CopyTo(Yc);
Z.CopyTo(Zc);
}
else
{
// Two cases if the data in the file differs from FloatDefault:
if (fileStorageDataType == "float")
{
vtkm::cont::ArrayHandle<vtkm::Float32> Xcf, Ycf, Zcf;
X.CopyTo(Xcf);
Y.CopyTo(Ycf);
Z.CopyTo(Zcf);
vtkm::cont::ArrayCopy(Xcf, Xc);
vtkm::cont::ArrayCopy(Ycf, Yc);
vtkm::cont::ArrayCopy(Zcf, Zc);
}
else
{
vtkm::cont::ArrayHandle<vtkm::Float64> Xcd, Ycd, Zcd;
X.CopyTo(Xcd);
Y.CopyTo(Ycd);
Z.CopyTo(Zcd);
vtkm::cont::ArrayCopy(Xcd, Xc);
vtkm::cont::ArrayCopy(Ycd, Yc);
vtkm::cont::ArrayCopy(Zcd, Zc);
}
}
// As a postscript to this somewhat branchy code, I thought that X.CopyTo(Xc) should be able to cast to the value_type of Xc.
// But that would break the ability to make the cast lazy, and hence if you change it you induce performance bugs.
coords = vtkm::cont::make_ArrayHandleCartesianProduct(Xc, Yc, Zc);
vtkm::cont::CoordinateSystem coordSys("coordinates", coords);
this->DataSet.AddCoordinateSystem(coordSys);
this->DataSet.SetCellSet(internal::CreateCellSetStructured(dim));
// Read points and cell attributes

@ -578,6 +578,254 @@ void TestReadingStructuredGridBin()
"Incorrect cellset type");
}
void TestReadingFishTank()
{
std::string fishtank =
vtkm::cont::testing::Testing::GetTestDataBasePath() + "/rectilinear/fishtank.vtk";
vtkm::cont::DataSet ds = readVTKDataSet(fishtank.c_str());
// This is information you can glean by running 'strings' on fishtank.vtk:
VTKM_TEST_ASSERT(ds.GetCellSet().IsType<vtkm::cont::CellSetStructured<3>>(),
"Incorrect cellset type");
VTKM_TEST_ASSERT(ds.GetNumberOfPoints() == 50 * 50 * 50, "Incorrect number of points");
VTKM_TEST_ASSERT(ds.GetCellSet().GetNumberOfPoints() == 50 * 50 * 50,
"Incorrect number of points (from cell set)");
VTKM_TEST_ASSERT(ds.GetNumberOfFields() == 2, "Incorrect number of fields");
VTKM_TEST_ASSERT(ds.HasField("vec"), "The vtk file has a field 'vec', but the dataset does not.");
VTKM_TEST_ASSERT(ds.HasField("vec_magnitude"),
"The vtk file has a field 'vec_magnitude', but the dataset does not.");
// I believe the coordinate system is implicitly given by the first element of X_COORDINATES:
VTKM_TEST_ASSERT(ds.GetNumberOfCoordinateSystems() == 1,
"Need one and only one coordinate system.");
// In order to get the data from the coordinate system, I used the following workflow:
// First, I deleted all ascii header lines just past 'X_COORDINATES 50 float'.
// Once this is done, I can get the binary data from
// $ od -tfF --endian=big fishtank_copy.vtk
// The result is:
// 0 0.020408163 ... 0.9591837 0.97959185 1
// So monotone increasing, bound [0,1].
const vtkm::cont::CoordinateSystem& coordinateSystem = ds.GetCoordinateSystem();
vtkm::Vec<vtkm::Range, 3> ranges = coordinateSystem.GetRange();
vtkm::Range xRange = ranges[0];
VTKM_TEST_ASSERT(xRange.Min == 0);
VTKM_TEST_ASSERT(xRange.Max == 1);
// Do the same past 'Y_COORDINATES 50 float'.
// You get exactly the same as the x data.
vtkm::Range yRange = ranges[1];
VTKM_TEST_ASSERT(yRange.Min == 0);
VTKM_TEST_ASSERT(yRange.Max == 1);
// And finally, do it past 'Z_COORDINATES 50 float':
vtkm::Range zRange = ranges[2];
VTKM_TEST_ASSERT(zRange.Min == 0);
VTKM_TEST_ASSERT(zRange.Max == 1);
// Now delete the text up to LOOKUP TABLE default.
// I see:
// 0 0 0 0 3.5267966 . . .
// This is a vector magnitude, so all values must be >= 0.
// A cursory glance shows that 124.95 is a large value, so we can sanity check the data with the bounds
// [0, ~130].
// And if we open the file in Paraview, we can observe the bounds [0, 156.905].
const vtkm::cont::Field& vec_magnitude = ds.GetField("vec_magnitude");
VTKM_TEST_ASSERT(vec_magnitude.GetName() == "vec_magnitude");
VTKM_TEST_ASSERT(vec_magnitude.IsFieldPoint());
vtkm::Range mag_range;
vec_magnitude.GetRange(&mag_range);
VTKM_TEST_ASSERT(mag_range.Min == 0);
VTKM_TEST_ASSERT(mag_range.Max <= 156.906);
// This info was gleaned from the Paraview Information panel:
const vtkm::cont::Field& vec = ds.GetField("vec");
VTKM_TEST_ASSERT(vec.GetName() == "vec");
VTKM_TEST_ASSERT(vec.IsFieldPoint());
// Bounds from Information panel:
// [-65.3147, 86.267], [-88.0325, 78.7217], [-67.0969, 156.867]
const vtkm::cont::ArrayHandle<vtkm::Range>& vecRanges = vec.GetRange();
VTKM_TEST_ASSERT(vecRanges.GetNumberOfValues() == 3);
auto vecRangesReadPortal = vecRanges.ReadPortal();
auto xVecRange = vecRangesReadPortal.Get(0);
VTKM_TEST_ASSERT(xVecRange.Min >= -65.3148 && xVecRange.Min <= -65.3146);
VTKM_TEST_ASSERT(xVecRange.Max >= 86.26 && xVecRange.Min <= 86.268);
auto yVecRange = vecRangesReadPortal.Get(1);
VTKM_TEST_ASSERT(yVecRange.Min >= -88.0326 && yVecRange.Min <= -88.0324);
VTKM_TEST_ASSERT(yVecRange.Max >= 78.721);
VTKM_TEST_ASSERT(yVecRange.Max <= 78.7218);
auto zVecRange = vecRangesReadPortal.Get(2);
VTKM_TEST_ASSERT(zVecRange.Min >= -67.097 && zVecRange.Min <= -67.096);
VTKM_TEST_ASSERT(zVecRange.Max >= 156.866 && zVecRange.Max <= 156.868);
}
void TestReadingDoublePrecisionFishTank()
{
std::string fishtank = vtkm::cont::testing::Testing::GetTestDataBasePath() +
"/rectilinear/fishtank_double_big_endian.vtk";
vtkm::cont::DataSet ds = readVTKDataSet(fishtank.c_str());
// This is information you can glean by running 'strings' on fishtank.vtk:
VTKM_TEST_ASSERT(ds.GetCellSet().IsType<vtkm::cont::CellSetStructured<3>>(),
"Incorrect cellset type");
VTKM_TEST_ASSERT(ds.GetNumberOfPoints() == 50 * 50 * 50, "Incorrect number of points");
VTKM_TEST_ASSERT(ds.GetCellSet().GetNumberOfPoints() == 50 * 50 * 50,
"Incorrect number of points (from cell set)");
VTKM_TEST_ASSERT(ds.HasField("vec"), "The vtk file has a field 'vec', but the dataset does not.");
VTKM_TEST_ASSERT(ds.GetNumberOfCoordinateSystems() == 1,
"fishtank has one and only one coordinate system.");
// See the single precision version for info:
const vtkm::cont::CoordinateSystem& coordinateSystem = ds.GetCoordinateSystem();
vtkm::Vec<vtkm::Range, 3> ranges = coordinateSystem.GetRange();
vtkm::Range xRange = ranges[0];
VTKM_TEST_ASSERT(xRange.Min == 0);
VTKM_TEST_ASSERT(xRange.Max == 1);
vtkm::Range yRange = ranges[1];
VTKM_TEST_ASSERT(yRange.Min == 0);
VTKM_TEST_ASSERT(yRange.Max == 1);
vtkm::Range zRange = ranges[2];
VTKM_TEST_ASSERT(zRange.Min == 0);
VTKM_TEST_ASSERT(zRange.Max == 1);
// This info was gleaned from the Paraview Information panel:
const vtkm::cont::Field& vec = ds.GetField("vec");
VTKM_TEST_ASSERT(vec.GetName() == "vec");
VTKM_TEST_ASSERT(vec.IsFieldPoint());
// Bounds from Information panel:
// [-65.3147, 86.267], [-88.0325, 78.7217], [-67.0969, 156.867]
const vtkm::cont::ArrayHandle<vtkm::Range>& vecRanges = vec.GetRange();
VTKM_TEST_ASSERT(vecRanges.GetNumberOfValues() == 3);
auto vecRangesReadPortal = vecRanges.ReadPortal();
auto xVecRange = vecRangesReadPortal.Get(0);
VTKM_TEST_ASSERT(xVecRange.Min >= -65.3148 && xVecRange.Min <= -65.3146);
VTKM_TEST_ASSERT(xVecRange.Max >= 86.26 && xVecRange.Min <= 86.268);
auto yVecRange = vecRangesReadPortal.Get(1);
VTKM_TEST_ASSERT(yVecRange.Min >= -88.0326 && yVecRange.Min <= -88.0324);
VTKM_TEST_ASSERT(yVecRange.Max >= 78.721);
VTKM_TEST_ASSERT(yVecRange.Max <= 78.7218);
auto zVecRange = vecRangesReadPortal.Get(2);
VTKM_TEST_ASSERT(zVecRange.Min >= -67.097 && zVecRange.Min <= -67.096);
VTKM_TEST_ASSERT(zVecRange.Max >= 156.866 && zVecRange.Max <= 156.868);
}
void TestReadingASCIIFishTank()
{
std::string fishtank =
vtkm::cont::testing::Testing::GetTestDataBasePath() + "/rectilinear/fishtank_double_ascii.vtk";
vtkm::cont::DataSet ds = readVTKDataSet(fishtank.c_str());
VTKM_TEST_ASSERT(ds.GetCellSet().IsType<vtkm::cont::CellSetStructured<3>>(),
"Incorrect cellset type");
VTKM_TEST_ASSERT(ds.GetNumberOfPoints() == 50 * 50 * 50, "Incorrect number of points");
VTKM_TEST_ASSERT(ds.GetCellSet().GetNumberOfPoints() == 50 * 50 * 50,
"Incorrect number of points (from cell set)");
VTKM_TEST_ASSERT(ds.HasField("vec"), "The vtk file has a field 'vec', but the dataset does not.");
VTKM_TEST_ASSERT(ds.GetNumberOfCoordinateSystems() == 1,
"fishtank has one and only one coordinate system.");
const vtkm::cont::CoordinateSystem& coordinateSystem = ds.GetCoordinateSystem();
vtkm::Vec<vtkm::Range, 3> ranges = coordinateSystem.GetRange();
vtkm::Range xRange = ranges[0];
VTKM_TEST_ASSERT(xRange.Min == 0);
VTKM_TEST_ASSERT(xRange.Max == 1);
vtkm::Range yRange = ranges[1];
VTKM_TEST_ASSERT(yRange.Min == 0);
VTKM_TEST_ASSERT(yRange.Max == 1);
vtkm::Range zRange = ranges[2];
VTKM_TEST_ASSERT(zRange.Min == 0);
VTKM_TEST_ASSERT(zRange.Max == 1);
const vtkm::cont::Field& vec = ds.GetField("vec");
VTKM_TEST_ASSERT(vec.GetName() == "vec");
VTKM_TEST_ASSERT(vec.IsFieldPoint());
// Bounds from Paraview information panel:
// [-65.3147, 86.267], [-88.0325, 78.7217], [-67.0969, 156.867]
const vtkm::cont::ArrayHandle<vtkm::Range>& vecRanges = vec.GetRange();
VTKM_TEST_ASSERT(vecRanges.GetNumberOfValues() == 3);
auto vecRangesReadPortal = vecRanges.ReadPortal();
auto xVecRange = vecRangesReadPortal.Get(0);
VTKM_TEST_ASSERT(xVecRange.Min >= -65.3148 && xVecRange.Min <= -65.3146);
VTKM_TEST_ASSERT(xVecRange.Max >= 86.26 && xVecRange.Min <= 86.268);
auto yVecRange = vecRangesReadPortal.Get(1);
VTKM_TEST_ASSERT(yVecRange.Min >= -88.0326 && yVecRange.Min <= -88.0324);
VTKM_TEST_ASSERT(yVecRange.Max >= 78.721);
VTKM_TEST_ASSERT(yVecRange.Max <= 78.7218);
auto zVecRange = vecRangesReadPortal.Get(2);
VTKM_TEST_ASSERT(zVecRange.Min >= -67.097 && zVecRange.Min <= -67.096);
VTKM_TEST_ASSERT(zVecRange.Max >= 156.866 && zVecRange.Max <= 156.868);
}
void TestReadingFusion()
{
std::string fusion =
vtkm::cont::testing::Testing::GetTestDataBasePath() + "/rectilinear/fusion.vtk";
vtkm::cont::DataSet ds = readVTKDataSet(fusion.c_str());
VTKM_TEST_ASSERT(ds.GetCellSet().IsType<vtkm::cont::CellSetStructured<3>>(),
"Incorrect cellset type");
VTKM_TEST_ASSERT(ds.GetNumberOfPoints() == 32 * 32 * 32, "Incorrect number of points");
VTKM_TEST_ASSERT(ds.GetCellSet().GetNumberOfPoints() == 32 * 32 * 32,
"Incorrect number of points (from cell set)");
VTKM_TEST_ASSERT(ds.HasField("vec_magnitude"),
"The vtk file has a field 'vec_magnitude', but the dataset does not.");
VTKM_TEST_ASSERT(ds.HasField("vec"), "The vtk file has a field 'vec', but the dataset does not.");
VTKM_TEST_ASSERT(ds.GetNumberOfCoordinateSystems() == 1,
"The vtk file has a field 'vec', but the dataset does not.");
// Taken from Paraview + clicking Data Axes Grid:
const vtkm::cont::CoordinateSystem& coordinateSystem = ds.GetCoordinateSystem();
vtkm::Vec<vtkm::Range, 3> ranges = coordinateSystem.GetRange();
vtkm::Range xRange = ranges[0];
VTKM_TEST_ASSERT(xRange.Min == 0);
VTKM_TEST_ASSERT(xRange.Max == 1);
vtkm::Range yRange = ranges[1];
VTKM_TEST_ASSERT(yRange.Min == 0);
VTKM_TEST_ASSERT(yRange.Max == 1);
vtkm::Range zRange = ranges[2];
VTKM_TEST_ASSERT(zRange.Min == 0);
VTKM_TEST_ASSERT(zRange.Max == 1);
// Paraview Information Panel of this file:
// vec_magnitude [0, 3.73778]
vtkm::cont::Field vec_magnitude = ds.GetField("vec_magnitude");
VTKM_TEST_ASSERT(vec_magnitude.GetName() == "vec_magnitude");
VTKM_TEST_ASSERT(vec_magnitude.IsFieldPoint());
vtkm::Range mag_range;
vec_magnitude.GetRange(&mag_range);
VTKM_TEST_ASSERT(mag_range.Min == 0);
VTKM_TEST_ASSERT(mag_range.Max <= 3.73779);
VTKM_TEST_ASSERT(mag_range.Max >= 3.73777);
vtkm::cont::Field vec = ds.GetField("vec");
VTKM_TEST_ASSERT(vec.GetName() == "vec");
VTKM_TEST_ASSERT(vec.IsFieldPoint());
const vtkm::cont::ArrayHandle<vtkm::Range>& vecRanges = vec.GetRange();
VTKM_TEST_ASSERT(vecRanges.GetNumberOfValues() == 3);
auto vecRangesReadPortal = vecRanges.ReadPortal();
// vec float [-3.41054, 3.40824], [-3.41018, 3.41036], [-0.689022, 0.480726]
auto xVecRange = vecRangesReadPortal.Get(0);
VTKM_TEST_ASSERT(test_equal(xVecRange.Min, -3.41054));
VTKM_TEST_ASSERT(test_equal(xVecRange.Max, 3.40824));
auto yVecRange = vecRangesReadPortal.Get(1);
VTKM_TEST_ASSERT(test_equal(yVecRange.Min, -3.41018));
VTKM_TEST_ASSERT(test_equal(yVecRange.Max, 3.41036));
auto zVecRange = vecRangesReadPortal.Get(2);
VTKM_TEST_ASSERT(test_equal(zVecRange.Min, -0.689022));
VTKM_TEST_ASSERT(test_equal(zVecRange.Max, 0.480726));
}
void TestReadingVTKDataSet()
{
std::cout << "Test reading VTK Polydata file in ASCII" << std::endl;
@ -607,6 +855,14 @@ void TestReadingVTKDataSet()
TestReadingStructuredGridASCII();
std::cout << "Test reading VTK StructuredGrid file in BINARY" << std::endl;
TestReadingStructuredGridBin();
std::cout << "Test reading float precision fishtank" << std::endl;
TestReadingFishTank();
std::cout << "Test reading double precision fishtank" << std::endl;
TestReadingDoublePrecisionFishTank();
std::cout << "Test ASCII fishtank" << std::endl;
TestReadingASCIIFishTank();
std::cout << "Test reading fusion" << std::endl;
TestReadingFusion();
}
int UnitTestVTKDataSetReader(int argc, char* argv[])

@ -10,6 +10,7 @@
#ifndef vtk_m_rendering_Mapper_h
#define vtk_m_rendering_Mapper_h
#include <vtkm/Deprecated.h>
#include <vtkm/cont/ColorTable.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DynamicCellSet.h>
@ -38,8 +39,12 @@ public:
virtual void SetActiveColorTable(const vtkm::cont::ColorTable& ct);
virtual void StartScene() = 0;
virtual void EndScene() = 0;
VTKM_DEPRECATED(1.6, "StartScene() does nothing")
void StartScene() {}
VTKM_DEPRECATED(1.6, "EndScene() does nothing")
void EndScene() {}
virtual void SetCanvas(vtkm::rendering::Canvas* canvas) = 0;
virtual vtkm::rendering::Canvas* GetCanvas() const = 0;

@ -85,16 +85,6 @@ void MapperConnectivity::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
tracerProxy.Trace(camera, CanvasRT);
}
void MapperConnectivity::StartScene()
{
// Nothing needs to be done.
}
void MapperConnectivity::EndScene()
{
// Nothing needs to be done.
}
vtkm::rendering::Mapper* MapperConnectivity::NewCopy() const
{
return new vtkm::rendering::MapperConnectivity(*this);

@ -37,9 +37,6 @@ public:
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange) override;
virtual void StartScene() override;
virtual void EndScene() override;
vtkm::rendering::Mapper* NewCopy() const override;
void CreateDefaultView();

@ -217,16 +217,6 @@ void MapperCylinder::SetCompositeBackground(bool on)
this->Internals->CompositeBackground = on;
}
void MapperCylinder::StartScene()
{
// Nothing needs to be done.
}
void MapperCylinder::EndScene()
{
// Nothing needs to be done.
}
vtkm::rendering::Mapper* MapperCylinder::NewCopy() const
{
return new vtkm::rendering::MapperCylinder(*this);

@ -68,8 +68,6 @@ public:
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange) override;
virtual void StartScene() override;
virtual void EndScene() override;
void SetCompositeBackground(bool on);
vtkm::rendering::Mapper* NewCopy() const override;

@ -216,16 +216,6 @@ void MapperPoint::SetCompositeBackground(bool on)
this->Internals->CompositeBackground = on;
}
void MapperPoint::StartScene()
{
// Nothing needs to be done.
}
void MapperPoint::EndScene()
{
// Nothing needs to be done.
}
vtkm::rendering::Mapper* MapperPoint::NewCopy() const
{
return new vtkm::rendering::MapperPoint(*this);

@ -79,8 +79,6 @@ public:
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange) override;
virtual void StartScene() override;
virtual void EndScene() override;
void SetCompositeBackground(bool on);
vtkm::rendering::Mapper* NewCopy() const override;

@ -138,16 +138,6 @@ void MapperQuad::SetCompositeBackground(bool on)
this->Internals->CompositeBackground = on;
}
void MapperQuad::StartScene()
{
// Nothing needs to be done.
}
void MapperQuad::EndScene()
{
// Nothing needs to be done.
}
vtkm::rendering::Mapper* MapperQuad::NewCopy() const
{
return new vtkm::rendering::MapperQuad(*this);

@ -44,8 +44,6 @@ public:
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange) override;
virtual void StartScene() override;
virtual void EndScene() override;
void SetCompositeBackground(bool on);
vtkm::rendering::Mapper* NewCopy() const override;

@ -151,16 +151,6 @@ void MapperRayTracer::SetShadingOn(bool on)
this->Internals->Shade = on;
}
void MapperRayTracer::StartScene()
{
// Nothing needs to be done.
}
void MapperRayTracer::EndScene()
{
// Nothing needs to be done.
}
vtkm::rendering::Mapper* MapperRayTracer::NewCopy() const
{
return new vtkm::rendering::MapperRayTracer(*this);

@ -38,8 +38,6 @@ public:
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange) override;
virtual void StartScene() override;
virtual void EndScene() override;
void SetCompositeBackground(bool on);
vtkm::rendering::Mapper* NewCopy() const override;
void SetShadingOn(bool on);

@ -137,16 +137,6 @@ void MapperVolume::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
}
}
void MapperVolume::StartScene()
{
// Nothing needs to be done.
}
void MapperVolume::EndScene()
{
// Nothing needs to be done.
}
vtkm::rendering::Mapper* MapperVolume::NewCopy() const
{
return new vtkm::rendering::MapperVolume(*this);

@ -36,9 +36,6 @@ public:
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange) override;
virtual void StartScene() override;
virtual void EndScene() override;
vtkm::rendering::Mapper* NewCopy() const override;
void SetSampleDistance(const vtkm::Float32 distance);
void SetCompositeBackground(const bool compositeBackground);

@ -231,16 +231,6 @@ void MapperWireframer::SetIsOverlay(bool isOverlay)
this->Internals->IsOverlay = isOverlay;
}
void MapperWireframer::StartScene()
{
// Nothing needs to be done.
}
void MapperWireframer::EndScene()
{
// Nothing needs to be done.
}
void MapperWireframer::RenderCells(const vtkm::cont::DynamicCellSet& inCellSet,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& inScalarField,

@ -42,9 +42,6 @@ public:
bool GetIsOverlay() const;
void SetIsOverlay(bool isOverlay);
virtual void StartScene() override;
virtual void EndScene() override;
virtual void RenderCells(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& scalarField,

@ -46,13 +46,11 @@ void Scene::Render(vtkm::rendering::Mapper& mapper,
vtkm::rendering::Canvas& canvas,
const vtkm::rendering::Camera& camera) const
{
mapper.StartScene();
for (vtkm::IdComponent actorIndex = 0; actorIndex < this->GetNumberOfActors(); actorIndex++)
{
const vtkm::rendering::Actor& actor = this->GetActor(actorIndex);
actor.Render(mapper, canvas, camera);
}
mapper.EndScene();
}
vtkm::Bounds Scene::GetSpatialBounds() const

@ -90,7 +90,7 @@ set(unit_tests
vtkm_unit_tests(
SOURCES ${unit_tests}
LIBRARIES vtkm_source vtkm_worklet vtkm_filter
LIBRARIES vtkm_source vtkm_worklet vtkm_filter vtkm_io
ALL_BACKENDS
USE_VTKM_JOB_POOL
)

@ -19,13 +19,13 @@ void TestSingle()
auto single_array = vtkm::cont::make_ArrayHandle(single);
auto result = vtkm::worklet::DescriptiveStatistics::Run(single_array);
VTKM_TEST_ASSERT(result.N() == 1);
VTKM_TEST_ASSERT(result.Mean() == 42);
VTKM_TEST_ASSERT(result.PopulationVariance() == 0);
VTKM_TEST_ASSERT(test_equal(result.N(), 1));
VTKM_TEST_ASSERT(test_equal(result.Mean(), 42));
VTKM_TEST_ASSERT(test_equal(result.PopulationVariance(), 0));
// A single number does not have skewness nor kurtosis
VTKM_TEST_ASSERT(result.Skewness() == 0);
VTKM_TEST_ASSERT(result.Kurtosis() == 0);
VTKM_TEST_ASSERT(test_equal(result.Skewness(), 0));
VTKM_TEST_ASSERT(test_equal(result.Kurtosis(), 0));
}
void TestConstant()
@ -33,11 +33,11 @@ void TestConstant()
auto constants = vtkm::cont::make_ArrayHandleConstant(1234.f, 10000);
auto result = vtkm::worklet::DescriptiveStatistics::Run(constants);
VTKM_TEST_ASSERT(result.N() == 10000);
VTKM_TEST_ASSERT(result.Sum() == 12340000);
VTKM_TEST_ASSERT(result.PopulationVariance() == 0);
VTKM_TEST_ASSERT(result.Skewness() == 0);
VTKM_TEST_ASSERT(result.Kurtosis() == 0);
VTKM_TEST_ASSERT(test_equal(result.N(), 10000));
VTKM_TEST_ASSERT(test_equal(result.Sum(), 12340000));
VTKM_TEST_ASSERT(test_equal(result.PopulationVariance(), 0));
VTKM_TEST_ASSERT(test_equal(result.Skewness(), 0));
VTKM_TEST_ASSERT(test_equal(result.Kurtosis(), 0));
}
void TestIntegerSequence()
@ -45,11 +45,12 @@ void TestIntegerSequence()
// We only have 23 bits for FloatInt in Float32. This limits N to 11 bits.
constexpr vtkm::Float32 N = 1000;
auto integers = vtkm::cont::ArrayHandleCounting<vtkm::Float32>(0.0f, 1.0f, vtkm::Id(N));
auto integers =
vtkm::cont::ArrayHandleCounting<vtkm::Float32>(0.0f, 1.0f, static_cast<vtkm::Id>(N));
auto result = vtkm::worklet::DescriptiveStatistics::Run(integers);
VTKM_TEST_ASSERT(result.N() == N);
VTKM_TEST_ASSERT(result.Sum() == N * (N - 1) / 2);
VTKM_TEST_ASSERT(test_equal(result.N(), N));
VTKM_TEST_ASSERT(test_equal(result.Sum(), N * (N - 1) / 2));
VTKM_TEST_ASSERT(test_equal(result.Mean(), (N - 1) / 2));
// Expected values are from Numpy/SciPy
@ -87,10 +88,10 @@ void TestCatastrophicCancellation()
auto arrayOK = vtkm::cont::make_ArrayHandle(okay);
auto resultOK = vtkm::worklet::DescriptiveStatistics::Run(arrayOK);
VTKM_TEST_ASSERT(resultOK.N() == 4);
VTKM_TEST_ASSERT(resultOK.Sum() == 4.0e8 + 40);
VTKM_TEST_ASSERT(resultOK.Min() == 1.0e8 + 4);
VTKM_TEST_ASSERT(resultOK.Max() == 1.0e8 + 16);
VTKM_TEST_ASSERT(test_equal(resultOK.N(), 4));
VTKM_TEST_ASSERT(test_equal(resultOK.Sum(), 4.0e8 + 40));
VTKM_TEST_ASSERT(test_equal(resultOK.Min(), 1.0e8 + 4));
VTKM_TEST_ASSERT(test_equal(resultOK.Max(), 1.0e8 + 16));
VTKM_TEST_ASSERT(test_equal(resultOK.SampleVariance(), 30));
VTKM_TEST_ASSERT(test_equal(resultOK.PopulationVariance(), 22.5));
@ -100,10 +101,10 @@ void TestCatastrophicCancellation()
auto arrayEvil = vtkm::cont::make_ArrayHandle(evil);
auto resultEvil = vtkm::worklet::DescriptiveStatistics::Run(arrayEvil);
VTKM_TEST_ASSERT(resultEvil.N() == 4);
VTKM_TEST_ASSERT(resultEvil.Sum() == 4.0e9 + 40);
VTKM_TEST_ASSERT(resultEvil.Min() == 1.0e9 + 4);
VTKM_TEST_ASSERT(resultEvil.Max() == 1.0e9 + 16);
VTKM_TEST_ASSERT(test_equal(resultEvil.N(), 4));
VTKM_TEST_ASSERT(test_equal(resultEvil.Sum(), 4.0e9 + 40));
VTKM_TEST_ASSERT(test_equal(resultEvil.Min(), 1.0e9 + 4));
VTKM_TEST_ASSERT(test_equal(resultEvil.Max(), 1.0e9 + 16));
VTKM_TEST_ASSERT(test_equal(resultEvil.SampleVariance(), 30));
VTKM_TEST_ASSERT(test_equal(resultEvil.PopulationVariance(), 22.5));
}
@ -220,7 +221,8 @@ void TestMomentsByKey()
{
std::vector<vtkm::UInt32> keys{ 0, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 };
auto values_array = vtkm::cont::make_ArrayHandleConstant(1.0f, vtkm::Id(keys.size()));
auto values_array =
vtkm::cont::make_ArrayHandleConstant(1.0f, static_cast<vtkm::Id>(keys.size()));
auto keys_array = vtkm::cont::make_ArrayHandle(keys);
auto results = vtkm::worklet::DescriptiveStatistics::Run(keys_array, values_array);
@ -235,9 +237,9 @@ void TestMomentsByKey()
for (vtkm::Id i = 0; i < results.GetNumberOfValues(); ++i)
{
auto result = resultsPortal.Get(i);
VTKM_TEST_ASSERT(result.first == vtkm::UInt32(i));
VTKM_TEST_ASSERT(result.second.N() == expected_ns[size_type(i)]);
VTKM_TEST_ASSERT(result.second.PopulationVariance() == 0);
VTKM_TEST_ASSERT(test_equal(result.first, i));
VTKM_TEST_ASSERT(test_equal(result.second.N(), expected_ns[static_cast<std::size_t>(i)]));
VTKM_TEST_ASSERT(test_equal(result.second.PopulationVariance(), 0));
}
}

@ -16,6 +16,7 @@
#include <vtkm/cont/DataSetBuilderRectilinear.h>
#include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/worklet/ParticleAdvection.h>
#include <vtkm/worklet/particleadvection/GridEvaluators.h>
#include <vtkm/worklet/particleadvection/Integrators.h>
@ -847,6 +848,103 @@ void TestWorkletsBasic()
}
}
template <class ResultType>
void ValidateResult(const ResultType& res,
vtkm::Id maxSteps,
const std::vector<vtkm::Vec3f>& endPts)
{
const vtkm::FloatDefault eps = static_cast<vtkm::FloatDefault>(1e-3);
vtkm::Id numPts = static_cast<vtkm::Id>(endPts.size());
VTKM_TEST_ASSERT(res.Particles.GetNumberOfValues() == numPts,
"Wrong number of points in particle advection result.");
auto portal = res.Particles.ReadPortal();
for (vtkm::Id i = 0; i < 3; i++)
{
vtkm::Vec3f p = portal.Get(i).Pos;
vtkm::Vec3f e = endPts[static_cast<std::size_t>(i)];
VTKM_TEST_ASSERT(vtkm::Magnitude(p - e) <= eps, "Particle advection point is wrong");
VTKM_TEST_ASSERT(portal.Get(i).NumSteps == maxSteps, "Particle advection NumSteps is wrong");
VTKM_TEST_ASSERT(portal.Get(i).Status.CheckOk(), "Particle advection Status is wrong");
VTKM_TEST_ASSERT(portal.Get(i).Status.CheckTerminate(),
"Particle advection particle did not terminate");
}
}
void TestParticleAdvectionFile(const std::string& fname,
const std::vector<vtkm::Vec3f>& pts,
vtkm::FloatDefault stepSize,
vtkm::Id maxSteps,
const std::vector<vtkm::Vec3f>& endPts)
{
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Testing particle advection on file " << fname);
vtkm::io::VTKDataSetReader reader(fname);
vtkm::cont::DataSet ds;
try
{
ds = reader.ReadDataSet();
}
catch (vtkm::io::ErrorIO& e)
{
std::string message("Error reading: ");
message += fname;
message += ", ";
message += e.GetMessage();
VTKM_TEST_FAIL(message.c_str());
}
using FieldHandle = vtkm::cont::ArrayHandle<vtkm::Vec3f_32>;
using GridEvalType = vtkm::worklet::particleadvection::GridEvaluator<FieldHandle>;
using RK4Type = vtkm::worklet::particleadvection::RK4Integrator<GridEvalType>;
VTKM_TEST_ASSERT(ds.HasField("vec"));
vtkm::cont::Field& field = ds.GetField("vec");
auto fieldData = field.GetData();
if (!fieldData.IsType<FieldHandle>())
{
VTKM_LOG_S(vtkm::cont::LogLevel::Error,
"The field data is of type "
<< vtkm::cont::TypeToString<decltype(fieldData)>()
<< ", but we expect type vtkm::cont::ArrayHandle<vtkm::Vec3f>");
VTKM_TEST_FAIL("No field with correct type found.");
}
FieldHandle fieldArray = fieldData.Cast<FieldHandle>();
GridEvalType eval(ds.GetCoordinateSystem(), ds.GetCellSet(), fieldArray);
RK4Type rk4(eval, stepSize);
for (int i = 0; i < 2; i++)
{
std::vector<vtkm::Particle> seeds;
for (size_t j = 0; j < pts.size(); j++)
seeds.push_back(vtkm::Particle(pts[j], static_cast<vtkm::Id>(j)));
auto seedArray = vtkm::cont::make_ArrayHandle(seeds);
if (i == 0)
{
vtkm::worklet::ParticleAdvection pa;
vtkm::worklet::ParticleAdvectionResult res;
res = pa.Run(rk4, seedArray, maxSteps);
ValidateResult(res, maxSteps, endPts);
}
else if (i == 1)
{
vtkm::worklet::Streamline s;
vtkm::worklet::StreamlineResult res;
res = s.Run(rk4, seedArray, maxSteps);
ValidateResult(res, maxSteps, endPts);
}
}
}
void TestParticleAdvection()
{
TestIntegrators();
@ -854,6 +952,35 @@ void TestParticleAdvection()
TestParticleStatus();
TestWorkletsBasic();
TestParticleWorkletsWithDataSetTypes();
std::string basePath = vtkm::cont::testing::Testing::GetTestDataBasePath();
//Fusion test.
std::vector<vtkm::Vec3f> fusionPts, fusionEndPts;
fusionPts.push_back(vtkm::Vec3f(0.8f, 0.6f, 0.6f));
fusionPts.push_back(vtkm::Vec3f(0.8f, 0.8f, 0.6f));
fusionPts.push_back(vtkm::Vec3f(0.8f, 0.8f, 0.3f));
//End point values were generated in VisIt.
fusionEndPts.push_back(vtkm::Vec3f(0.5335789918f, 0.87112802267f, 0.6723330020f));
fusionEndPts.push_back(vtkm::Vec3f(0.5601879954f, 0.91389900446f, 0.43989110522f));
fusionEndPts.push_back(vtkm::Vec3f(0.7004770041f, 0.63193398714f, 0.64524400234f));
vtkm::FloatDefault fusionStep = 0.005f;
std::string fusionFile = basePath + "/rectilinear/fusion.vtk";
TestParticleAdvectionFile(fusionFile, fusionPts, fusionStep, 1000, fusionEndPts);
//Fishtank test.
std::vector<vtkm::Vec3f> fishPts, fishEndPts;
fishPts.push_back(vtkm::Vec3f(0.75f, 0.5f, 0.01f));
fishPts.push_back(vtkm::Vec3f(0.4f, 0.2f, 0.7f));
fishPts.push_back(vtkm::Vec3f(0.5f, 0.3f, 0.8f));
//End point values were generated in VisIt.
fishEndPts.push_back(vtkm::Vec3f(0.7734669447f, 0.4870159328f, 0.8979591727f));
fishEndPts.push_back(vtkm::Vec3f(0.7257543206f, 0.1277695596f, 0.7468645573f));
fishEndPts.push_back(vtkm::Vec3f(0.8347796798f, 0.1276152730f, 0.4985143244f));
vtkm::FloatDefault fishStep = 0.001f;
std::string fishFile = basePath + "/rectilinear/fishtank.vtk";
TestParticleAdvectionFile(fishFile, fishPts, fishStep, 100, fishEndPts);
}
int UnitTestParticleAdvection(int argc, char* argv[])