vtk-m2/vtkm/cont/DynamicPointCoordinates.h
Kenneth Moreland 21823500c3 Change ArrayContainerControl to Storage.
After a talk with Robert Maynard, we decided to change the name
ArrayContainerControl to Storage. There are several reasons for this
change.

1. The name ArrayContainerControl is unwieldy. It is long, hard for
humans to parse, and makes for long lines and wraparound. It is also
hard to distinguish from other names like ArrayHandleFoo and
ArrayExecutionManager.

2. The word container is getting overloaded. For example, there is a
SimplePolymorphicContainer. Container is being used for an object that
literally acts like a container for data. This class really manages
data.

3. The data does not necessarily have to be on the control side.
Implicit containers store the data nowhere. Derivative containers might
have all the real data on the execution side. It is possible in the
future to have storage on the execution environment instead of the
control (think interfacing with a simulator on the GPU).

Storage is not a perfect word (what does implicit storage really mean?),
but its the best English word we came up with.
2014-06-24 09:58:32 -06:00

389 lines
14 KiB
C++

//============================================================================
// 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.
//
// Copyright 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. Los Alamos National Security
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_DynamicPointCoordinates_h
#define vtk_m_cont_DynamicPointCoordinates_h
#include <vtkm/cont/DynamicArrayHandle.h>
#include <vtkm/cont/ErrorControlBadValue.h>
#include <vtkm/cont/PointCoordinatesArray.h>
#include <vtkm/cont/PointCoordinatesListTag.h>
#include <vtkm/cont/internal/DynamicTransform.h>
#include <boost/shared_ptr.hpp>
namespace vtkm {
namespace cont {
namespace internal {
/// Behaves like (and is interchangable with) a \c DynamicPointCoordinates. The
/// difference is that the lists of point coordinates, base types, and
/// storage to try when calling \c CastAndCall is set to the class template
/// arguments.
///
template<typename PointCoordinatesList,
typename TypeList,
typename StorageList>
class DynamicPointCoordinatesCast;
} // namespace internal
/// \brief Holds point coordinates polymorphically.
///
/// The \c DynamicPointCoordinates holds a point coordinate field for a mesh.
/// Like a \c DynamicArrayHandle it contains a \c CastAndCall method that
/// allows it to interface with templated functions and will automatically be
/// converted on a worklet invoke.
///
/// \c DynamicPointCoordinates differes from \c DynamicArrayHandle in the type
/// of arrays it will check. Point coordinates are often defined as implicit
/// (uniform), semi-implicit (structured), unstructured, or some combination
/// thereof. Methods for defining point coordinates are captured in \c
/// PointCoordinates classes, and \c DynamicPointCoordinates polymorphically
/// stores one of these \c PointCoordinates objects.
///
/// By default, \c DynamicPointCoordinates will assume that the stored point
/// coordinates are of a type specified by \c
/// VTKM_DEFAULT_POINT_COORDINATES_LIST_TAG. This can be overriden by using the
/// \c ResetPointCoordinatesList method.
///
/// Internally, some \c PointCoordinates objects will reference dynamic arrays.
/// Thus, \c DynamicPointCoordinates also maintains lists of types and
/// storage that these subarrays might use. These default to \c
/// VTKM_DEFAULT_TYPE_LIST_TAG and \c VTKM_DEFAULT_STORAGE_LIST_TAG and can
/// be changed with the \c ResetTypeList and \c ResetStorageList methods.
///
class DynamicPointCoordinates
{
public:
VTKM_CONT_EXPORT
DynamicPointCoordinates() { }
/// Special constructor for the common case of using a basic array to store
/// point coordinates.
///
VTKM_CONT_EXPORT
DynamicPointCoordinates(const vtkm::cont::DynamicArrayHandle &array)
: PointCoordinatesContainer(new vtkm::cont::PointCoordinatesArray(array))
{ }
/// Special constructor for the common case of using a basic array to store
/// point coordinates.
///
template<typename Storage>
VTKM_CONT_EXPORT
DynamicPointCoordinates(
const vtkm::cont::ArrayHandle<vtkm::Vector3,Storage> &array)
: PointCoordinatesContainer(new vtkm::cont::PointCoordinatesArray(array))
{ }
/// Takes a concrete point coordinates class and stores it polymorphically.
/// Although the template will match any possible type, there is a check
/// to make sure that the type is a valid point coordinates class. If you get
/// a compile error in the check, follow the instantiation list to where the
/// constructor is called.
///
template<typename PointCoordinatesType>
VTKM_CONT_EXPORT
DynamicPointCoordinates(const PointCoordinatesType &pointCoordinates)
: PointCoordinatesContainer(new PointCoordinatesType(pointCoordinates))
{
VTKM_IS_POINT_COORDINATES(PointCoordinatesType);
}
/// Returns true if these point coordinates are stored in a \c
/// PointCoordinates class of the given type.
///
template<typename PointCoordinatesType>
VTKM_CONT_EXPORT
bool IsPointCoordinateType(PointCoordinatesType = PointCoordinatesType()) const
{
VTKM_IS_POINT_COORDINATES(PointCoordinatesType);
return (this->TryCastPointCoordinatesType<PointCoordinatesType>() != NULL);
}
/// Returns these point coordinates in a \c PointCoordinates class of the
/// given type. Throws \c ErrorControlBadValue if the cast does not work. Use
/// \c IsPointCoordinateType to check if the cast can happen.
///
template<typename PointCoordinatesType>
VTKM_CONT_EXPORT
const PointCoordinatesType &
CastToPointCoordinates(PointCoordinatesType = PointCoordinatesType()) const {
VTKM_IS_POINT_COORDINATES(PointCoordinatesType);
PointCoordinatesType *pointCoordinates =
this->TryCastPointCoordinatesType<PointCoordinatesType>();
if (pointCoordinates == NULL)
{
throw vtkm::cont::ErrorControlBadValue(
"Bad cast of dynamic point coordinates.");
}
return *pointCoordinates;
}
/// Changes the point coordinates objects to try casting to when resolving
/// dynamic arrays within the point coordinates container, which is specified
/// with a list tag like those in PointCoordinatesListTag.h. Since C++ does
/// not allow you to actually change the template arguments, this method
/// returns a new dynamic array object. This method is particularly useful to
/// narrow down (or expand) the types when using an array of particular
/// constraints.
///
template<typename NewPointCoordinatesList>
VTKM_CONT_EXPORT
internal::DynamicPointCoordinatesCast<
NewPointCoordinatesList,
VTKM_DEFAULT_TYPE_LIST_TAG,
VTKM_DEFAULT_STORAGE_LIST_TAG>
ResetPointCoordinatesList(
NewPointCoordinatesList = NewPointCoordinatesList()) const {
return internal::DynamicPointCoordinatesCast<
NewPointCoordinatesList,
VTKM_DEFAULT_TYPE_LIST_TAG,
VTKM_DEFAULT_STORAGE_LIST_TAG>(*this);
}
/// Changes the types to try casting to when resolving dynamic arrays within
/// the point coordinates container, which is specified with a list tag like
/// those in TypeListTag.h. Since C++ does not allow you to actually change
/// the template arguments, this method returns a new dynamic array object.
/// This method is particularly useful to narrow down (or expand) the types
/// when using an array of particular constraints.
///
template<typename NewTypeList>
VTKM_CONT_EXPORT
internal::DynamicPointCoordinatesCast<
VTKM_DEFAULT_POINT_COORDINATES_LIST_TAG,
NewTypeList,
VTKM_DEFAULT_STORAGE_LIST_TAG>
ResetTypeList(NewTypeList = NewTypeList()) const {
return internal::DynamicPointCoordinatesCast<
VTKM_DEFAULT_POINT_COORDINATES_LIST_TAG,
NewTypeList,
VTKM_DEFAULT_STORAGE_LIST_TAG>(*this);
}
/// Changes the array storage to try casting to when resolving dynamic
/// arrays within the point coordinates container, which is specified with a
/// list tag like those in StorageListTag.h. Since C++ does not allow you
/// to actually change the template arguments, this method returns a new
/// dynamic array object. This method is particularly useful to narrow down
/// (or expand) the types when using an array of particular constraints.
///
template<typename NewStorageList>
VTKM_CONT_EXPORT
internal::DynamicPointCoordinatesCast<
VTKM_DEFAULT_POINT_COORDINATES_LIST_TAG,
VTKM_DEFAULT_TYPE_LIST_TAG,
NewStorageList>
ResetStorageList(NewStorageList = NewStorageList()) const {
return internal::DynamicPointCoordinatesCast<
VTKM_DEFAULT_POINT_COORDINATES_LIST_TAG,
VTKM_DEFAULT_TYPE_LIST_TAG,
NewStorageList>(*this);
}
/// Attempts to cast the held point coordinates to a specific array
/// representation and then call the given functor with the cast array. This
/// is generally done in two parts. The first part finds the concrete type of
/// \c PointCoordinates object by trying all those in \c
/// VTKM_DEFAULT_POINT_COORDINATES_LIST_TAG.
///
/// The second part then asks the concrete \c PointCoordinates object to cast
/// and call to a concrete array. This second cast might rely on \c
/// VTKM_DEFAULT_TYPE_LIST_TAG and \c VTKM_DEFAULT_STORAGE_LIST_TAG.
///
template<typename Functor>
VTKM_CONT_EXPORT
void CastAndCall(const Functor &f) const
{
this->CastAndCall(f,
VTKM_DEFAULT_POINT_COORDINATES_LIST_TAG(),
VTKM_DEFAULT_TYPE_LIST_TAG(),
VTKM_DEFAULT_STORAGE_LIST_TAG());
}
/// A version of \c CastAndCall that tries specified lists of point
/// coordinates, types, and storage.
///
template<typename Functor,
typename PointCoordinatesList,
typename TypeList,
typename StorageList>
VTKM_CONT_EXPORT
void CastAndCall(const Functor &f,
PointCoordinatesList,
TypeList,
StorageList) const;
private:
boost::shared_ptr<vtkm::cont::internal::PointCoordinatesBase>
PointCoordinatesContainer;
template<typename PointCoordinatesType>
VTKM_CONT_EXPORT
PointCoordinatesType *
TryCastPointCoordinatesType() const {
VTKM_IS_POINT_COORDINATES(PointCoordinatesType);
return dynamic_cast<PointCoordinatesType *>(
this->PointCoordinatesContainer.get());
}
};
namespace detail {
template<typename Functor, typename TypeList, typename StorageList>
struct DynamicPointCoordinatesTryStorage
{
const DynamicPointCoordinates PointCoordinates;
const Functor &Function;
bool FoundCast;
VTKM_CONT_EXPORT
DynamicPointCoordinatesTryStorage(
const DynamicPointCoordinates &pointCoordinates,
const Functor &f)
: PointCoordinates(pointCoordinates), Function(f), FoundCast(false)
{ }
template<typename PointCoordinatesType>
VTKM_CONT_EXPORT
void operator()(PointCoordinatesType) {
if (!this->FoundCast &&
this->PointCoordinates.IsPointCoordinateType(PointCoordinatesType()))
{
PointCoordinatesType pointCoordinates =
this->PointCoordinates.CastToPointCoordinates(PointCoordinatesType());
pointCoordinates.CastAndCall(this->Function, TypeList(), StorageList());
this->FoundCast = true;
}
}
};
} // namespace detail
template<typename Functor,
typename PointCoordinatesList,
typename TypeList,
typename StorageList>
VTKM_CONT_EXPORT
void DynamicPointCoordinates::CastAndCall(const Functor &f,
PointCoordinatesList,
TypeList,
StorageList) const
{
typedef detail::DynamicPointCoordinatesTryStorage<
Functor, TypeList, StorageList> TryTypeType;
TryTypeType tryType = TryTypeType(*this, f);
vtkm::ListForEach(tryType, PointCoordinatesList());
if (!tryType.FoundCast)
{
throw vtkm::cont::ErrorControlBadValue(
"Could not find appropriate cast for point coordinates in CastAndCall.");
}
}
namespace internal {
template<typename PointCoordinatesList,
typename TypeList,
typename StorageList>
class DynamicPointCoordinatesCast : public vtkm::cont::DynamicPointCoordinates
{
public:
VTKM_CONT_EXPORT
DynamicPointCoordinatesCast() : DynamicPointCoordinates() { }
VTKM_CONT_EXPORT
DynamicPointCoordinatesCast(const vtkm::cont::DynamicPointCoordinates &coords)
: DynamicPointCoordinates(coords) { }
template<typename SrcPointCoordinatesList,
typename SrcTypeList,
typename SrcStorageList>
VTKM_CONT_EXPORT
DynamicPointCoordinatesCast(
const DynamicPointCoordinatesCast<SrcPointCoordinatesList,SrcTypeList,SrcStorageList> &coords)
: DynamicPointCoordinates(coords)
{ }
template<typename NewPointCoordinatesList>
VTKM_CONT_EXPORT
DynamicPointCoordinatesCast<NewPointCoordinatesList,TypeList,StorageList>
ResetPointCoordinatesList(
NewPointCoordinatesList = NewPointCoordinatesList()) const {
return DynamicPointCoordinatesCast<
NewPointCoordinatesList,TypeList,StorageList>(*this);
}
template<typename NewTypeList>
VTKM_CONT_EXPORT
DynamicPointCoordinatesCast<PointCoordinatesList,NewTypeList,StorageList>
ResetTypeList(NewTypeList = NewTypeList()) const {
return DynamicPointCoordinatesCast<
PointCoordinatesList,NewTypeList,StorageList>(*this);
}
template<typename NewStorageList>
VTKM_CONT_EXPORT
DynamicPointCoordinatesCast<PointCoordinatesList,TypeList,NewStorageList>
ResetStorageList(NewStorageList = NewStorageList()) const {
return DynamicPointCoordinatesCast<
PointCoordinatesList,TypeList,NewStorageList>(*this);
}
template<typename Functor>
VTKM_CONT_EXPORT
void CastAndCall(const Functor &f) const
{
this->CastAndCall(f, PointCoordinatesList(), TypeList(), StorageList());
}
template<typename Functor, typename PCL, typename TL, typename CL>
VTKM_CONT_EXPORT
void CastAndCall(const Functor &f, PCL, TL, CL) const
{
this->DynamicPointCoordinates::CastAndCall(f, PCL(), TL(), CL());
}
};
template<>
struct DynamicTransformTraits<vtkm::cont::DynamicPointCoordinates> {
typedef vtkm::cont::internal::DynamicTransformTagCastAndCall DynamicTag;
};
template<typename PointCoordinatesList,
typename TypeList,
typename StorageList>
struct DynamicTransformTraits<
vtkm::cont::internal::DynamicPointCoordinatesCast<
PointCoordinatesList,TypeList,StorageList> >
{
typedef vtkm::cont::internal::DynamicTransformTagCastAndCall DynamicTag;
};
} // namespace internal
}
} // namespace vtkm::cont
#endif //vtk_m_cont_DynamicPointCoordinates_h