Merge topic 'add_vector_cell_gradient'

8dadf560 Add in support for vector fields to Gradient worklet.
d53f43fb CellDerivaties now support computing the derivatives of vtkm::Vec fields.
b4378c85 Allow vtkm::Matrix to support T values which are vtkm::Vec.
9caabf97 vtkm::Vec now supports +=, -=, *=, and /=.

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Kenneth Moreland <kmorel@sandia.gov>
Merge-request: !608
This commit is contained in:
Robert Maynard 2016-11-15 23:39:10 -05:00 committed by Kitware Robot
commit 8861beda4b
8 changed files with 251 additions and 18 deletions

@ -1550,6 +1550,35 @@ struct FloatLimits<vtkm::Float32>
}
};
template<int N>
struct FloatLimits< vtkm::Vec<vtkm::Float32,N> >
{
typedef vtkm::detail::IEEE754Bits32 BitsType;
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float32,N> Nan() {
BitsType nan = {VTKM_NAN_BITS_32};
return vtkm::Vec<vtkm::Float32,N>(nan.scalar);
}
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float32,N> Infinity() {
BitsType inf = {VTKM_INF_BITS_32};
return vtkm::Vec<vtkm::Float32,N>(inf.scalar);
}
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float32,N> NegativeInfinity() {
BitsType neginf = {VTKM_NEG_INF_BITS_32};
return vtkm::Vec<vtkm::Float32,N>(neginf.scalar);
}
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float32,N> Epsilon() {
return vtkm::Vec<vtkm::Float32,N>(VTKM_EPSILON_32);
}
};
template<>
struct FloatLimits<vtkm::Float64>
{
@ -1579,6 +1608,35 @@ struct FloatLimits<vtkm::Float64>
}
};
template<int N>
struct FloatLimits< vtkm::Vec<vtkm::Float64,N> >
{
typedef vtkm::detail::IEEE754Bits64 BitsType;
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float64,N> Nan() {
BitsType nan = {VTKM_NAN_BITS_64};
return vtkm::Vec<vtkm::Float64,N>(nan.scalar);
}
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float64,N> Infinity() {
BitsType inf = {VTKM_INF_BITS_64};
return vtkm::Vec<vtkm::Float64,N>(inf.scalar);
}
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float64,N> NegativeInfinity() {
BitsType neginf = {VTKM_NEG_INF_BITS_64};
return vtkm::Vec<vtkm::Float64,N>(neginf.scalar);
}
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float64,N> Epsilon() {
return vtkm::Vec<vtkm::Float64,N>(VTKM_EPSILON_64);
}
};
#undef VTKM_NAN_BITS_32
#undef VTKM_INF_BITS_32
#undef VTKM_NEG_INF_BITS_32

@ -566,6 +566,35 @@ struct FloatLimits<vtkm::Float32>
}
};
template<int N>
struct FloatLimits< vtkm::Vec<vtkm::Float32,N> >
{
typedef vtkm::detail::IEEE754Bits32 BitsType;
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float32,N> Nan() {
BitsType nan = {VTKM_NAN_BITS_32};
return vtkm::Vec<vtkm::Float32,N>(nan.scalar);
}
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float32,N> Infinity() {
BitsType inf = {VTKM_INF_BITS_32};
return vtkm::Vec<vtkm::Float32,N>(inf.scalar);
}
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float32,N> NegativeInfinity() {
BitsType neginf = {VTKM_NEG_INF_BITS_32};
return vtkm::Vec<vtkm::Float32,N>(neginf.scalar);
}
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float32,N> Epsilon() {
return vtkm::Vec<vtkm::Float32,N>(VTKM_EPSILON_32);
}
};
template<>
struct FloatLimits<vtkm::Float64>
{
@ -595,6 +624,35 @@ struct FloatLimits<vtkm::Float64>
}
};
template<int N>
struct FloatLimits< vtkm::Vec<vtkm::Float64,N> >
{
typedef vtkm::detail::IEEE754Bits64 BitsType;
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float64,N> Nan() {
BitsType nan = {VTKM_NAN_BITS_64};
return vtkm::Vec<vtkm::Float64,N>(nan.scalar);
}
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float64,N> Infinity() {
BitsType inf = {VTKM_INF_BITS_64};
return vtkm::Vec<vtkm::Float64,N>(inf.scalar);
}
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float64,N> NegativeInfinity() {
BitsType neginf = {VTKM_NEG_INF_BITS_64};
return vtkm::Vec<vtkm::Float64,N>(neginf.scalar);
}
VTKM_EXEC_CONT_EXPORT
static vtkm::Vec<vtkm::Float64,N> Epsilon() {
return vtkm::Vec<vtkm::Float64,N>(VTKM_EPSILON_64);
}
};
#undef VTKM_NAN_BITS_32
#undef VTKM_INF_BITS_32
#undef VTKM_NEG_INF_BITS_32

@ -387,7 +387,7 @@ void MatrixLUPFactor(vtkm::Matrix<T,Size,Size> &A,
{
permutation[index] = index;
}
inversionParity = 1;
inversionParity = T(1);
valid = true;
for (vtkm::IdComponent rowIndex = 0; rowIndex < Size; rowIndex++)

@ -491,6 +491,16 @@ public:
return result;
}
VTKM_EXEC_CONT_EXPORT
DerivedClass& operator+=(const DerivedClass& other)
{
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
this->Components[i] += other[i];
}
return *static_cast<DerivedClass*>(this);
}
VTKM_EXEC_CONT_EXPORT
DerivedClass operator-(const DerivedClass& other) const
{
@ -502,6 +512,16 @@ public:
return result;
}
VTKM_EXEC_CONT_EXPORT
DerivedClass& operator-=(const DerivedClass& other)
{
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
this->Components[i] -= other[i];
}
return *static_cast<DerivedClass*>(this);
}
VTKM_EXEC_CONT_EXPORT
DerivedClass operator*(const DerivedClass& other) const
{
@ -513,6 +533,16 @@ public:
return result;
}
VTKM_EXEC_CONT_EXPORT
DerivedClass& operator*=(const DerivedClass& other)
{
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
this->Components[i] *= other[i];
}
return *static_cast<DerivedClass*>(this);
}
VTKM_EXEC_CONT_EXPORT
DerivedClass operator/(const DerivedClass& other) const
{
@ -524,6 +554,16 @@ public:
return result;
}
VTKM_EXEC_CONT_EXPORT
DerivedClass& operator/=(const DerivedClass& other)
{
for (vtkm::IdComponent i = 0; i < Size; ++i)
{
this->Components[i] /= other[i];
}
return *static_cast<DerivedClass*>(this);
}
#if (defined(VTKM_GCC) || defined(VTKM_CLANG))
#pragma GCC diagnostic pop
#endif // gcc || clang

@ -59,9 +59,9 @@ ParametricDerivative(const FieldVecType &field,
typedef vtkm::Vec<FieldType,3> GradientType;
GradientType pc(pcoords);
GradientType rc = GradientType(1) - pc;
GradientType rc = GradientType(FieldType(1)) - pc;
GradientType parametricDerivative(0);
GradientType parametricDerivative(FieldType(0));
VTKM_ACCUM_PARAMETRIC_DERIVATIVE_3D(0, -rc[1]*rc[2], -rc[0]*rc[2], -rc[0]*rc[1]);
VTKM_ACCUM_PARAMETRIC_DERIVATIVE_3D(1, rc[1]*rc[2], -pc[0]*rc[2], -pc[0]*rc[1]);
VTKM_ACCUM_PARAMETRIC_DERIVATIVE_3D(2, pc[1]*rc[2], pc[0]*rc[2], -pc[0]*pc[1]);
@ -146,9 +146,9 @@ ParametricDerivative(const FieldVecType &field,
GradientType pc(static_cast<FieldType>(pcoords[0]),
static_cast<FieldType>(pcoords[1]));
GradientType rc = GradientType(1) - pc;
GradientType rc = GradientType(FieldType(1)) - pc;
GradientType parametricDerivative(0);
GradientType parametricDerivative(FieldType(0));
VTKM_ACCUM_PARAMETRIC_DERIVATIVE_2D(0, -rc[1], -rc[0]);
VTKM_ACCUM_PARAMETRIC_DERIVATIVE_2D(1, rc[1], -pc[0]);
VTKM_ACCUM_PARAMETRIC_DERIVATIVE_2D(2, pc[1], pc[0]);
@ -375,7 +375,7 @@ CellDerivative(const FieldVecType &field,
VTKM_ASSERT(wCoords.GetNumberOfComponents() == 1);
typedef vtkm::Vec<typename FieldVecType::ComponentType,3> GradientType;
return GradientType(0,0,0);
return vtkm::TypeTraits<GradientType>::ZeroInitialization();
}
//-----------------------------------------------------------------------------
@ -467,7 +467,7 @@ TriangleDerivative(const vtkm::Vec<ValueType, 3> &field,
vtkm::MatrixSetRow(A, 1, v1);
vtkm::MatrixSetRow(A, 2, n);
GradientType b(field[1] - field[0], field[2] - field[0], 0);
GradientType b(field[1] - field[0], field[2] - field[0], ValueType(0));
// If we want to later change this method to take the gradient of multiple
// values (for example, to find the Jacobian of a vector field), then there
@ -677,7 +677,7 @@ CellDerivative(const FieldVecType &field,
VecT pc(static_cast<T>(pcoords[0]),
static_cast<T>(pcoords[1]));
VecT rc = VecT(1) - pc;
VecT rc = VecT(T(1)) - pc;
VecT sum = field[0]*VecT(-rc[1], -rc[0]);
sum = sum + field[1]*VecT( rc[1], -pc[0]);
@ -686,7 +686,7 @@ CellDerivative(const FieldVecType &field,
return vtkm::Vec<T,3>(sum[0]/wCoords.GetSpacing()[0],
sum[1]/wCoords.GetSpacing()[1],
0);
T(0));
}
//-----------------------------------------------------------------------------
@ -813,7 +813,7 @@ CellDerivative(const FieldVecType &field,
VecT pc(static_cast<T>(pcoords[0]),
static_cast<T>(pcoords[1]),
static_cast<T>(pcoords[2]));
VecT rc = VecT(1) - pc;
VecT rc = VecT(T(1)) - pc;
VecT sum = field[0]*VecT(-rc[1]*rc[2], -rc[0]*rc[2], -rc[0]*rc[1]);
sum = sum + field[1]*VecT( rc[1]*rc[2], -pc[0]*rc[2], -pc[0]*rc[1]);

@ -194,9 +194,9 @@ void JacobianFor3DCell(const WorldCoordType &wCoords,
vtkm::CellShapeTagHexahedron)
{
vtkm::Vec<JacobianType,3> pc(pcoords);
vtkm::Vec<JacobianType,3> rc = vtkm::Vec<JacobianType,3>(1) - pc;
vtkm::Vec<JacobianType,3> rc = vtkm::Vec<JacobianType,3>(JacobianType(1)) - pc;
jacobian = vtkm::Matrix<JacobianType,3,3>(0);
jacobian = vtkm::Matrix<JacobianType,3,3>(JacobianType(0));
VTKM_DERIVATIVE_WEIGHTS_HEXAHEDRON(pc, rc, VTKM_ACCUM_JACOBIAN_3D);
}
@ -272,10 +272,10 @@ void JacobianFor2DCell(const WorldCoordType &wCoords,
{
vtkm::Vec<JacobianType,2> pc(static_cast<JacobianType>(pcoords[0]),
static_cast<JacobianType>(pcoords[1]));
vtkm::Vec<JacobianType,2> rc = vtkm::Vec<JacobianType,2>(1) - pc;
vtkm::Vec<JacobianType,2> rc = vtkm::Vec<JacobianType,2>(JacobianType(1)) - pc;
vtkm::Vec<JacobianType,2> wcoords2d;
jacobian = vtkm::Matrix<JacobianType,2,2>(0);
jacobian = vtkm::Matrix<JacobianType,2,2>(JacobianType(0));
VTKM_DERIVATIVE_WEIGHTS_QUAD(pc, rc, VTKM_ACCUM_JACOBIAN_2D);
}

@ -35,14 +35,20 @@ namespace worklet {
struct GradientOutTypes
: vtkm::ListTagBase<
vtkm::Vec<vtkm::Float32,3>,
vtkm::Vec<vtkm::Float64,3>
vtkm::Vec<vtkm::Float64,3>,
vtkm::Vec< vtkm::Vec<vtkm::Float32,2>, 3>,
vtkm::Vec< vtkm::Vec<vtkm::Float64,2>, 3>,
vtkm::Vec< vtkm::Vec<vtkm::Float32,3>, 3>,
vtkm::Vec< vtkm::Vec<vtkm::Float64,3>, 3>,
vtkm::Vec< vtkm::Vec<vtkm::Float32,4>, 3>,
vtkm::Vec< vtkm::Vec<vtkm::Float64,4>, 3>
>
{ };
struct CellGradient : vtkm::worklet::WorkletMapPointToCell
{
typedef void ControlSignature(CellSetIn,
FieldInPoint<Vec3> pointCoordinates,
FieldInPoint<Scalar> inputField,
FieldInPoint<FieldCommon> inputField,
FieldOutCell<GradientOutTypes> outputField);
typedef void ExecutionSignature(CellShape, PointCount, _2, _3, _4);
@ -64,8 +70,8 @@ struct CellGradient : vtkm::worklet::WorkletMapPointToCell
using InValueType = typename FieldInVecType::ComponentType;
using InDimensionTag = typename TypeTraits<InValueType>::DimensionalityTag;
//grad the dimension tag for the output component type
using OutValueType = typename VecTraits<typename FieldOutType::ComponentType>::ComponentType;
//grab the dimension tag for the output component type
using OutValueType = typename FieldOutType::ComponentType;
using OutDimensionTag = typename TypeTraits<OutValueType>::DimensionalityTag;
//Verify that input and output dimension tags match
@ -99,6 +105,20 @@ struct CellGradient : vtkm::worklet::WorkletMapPointToCell
std::false_type) const
{
//this is invalid
// std::cout << "calling invalid compute" << std::endl;
// using InValueType = typename FieldInVecType::ComponentType;
// using InDimensionTag = typename TypeTraits<InValueType>::DimensionalityTag;
// using OutValueType = typename VecTraits<typename FieldOutType::ComponentType>::ComponentType;
// using OutDimensionTag = typename TypeTraits<OutValueType>::DimensionalityTag;
// std::cout << typeid(InDimensionTag).name() << '\n';
// std::cout << typeid(FieldInVecType).name() << '\n';
// std::cout << typeid(OutDimensionTag).name() << '\n';
// std::cout << typeid(FieldOutType).name() << '\n';
// std::cout << std::endl;
}
};

@ -78,6 +78,62 @@ void TestCellGradientUniform3D()
test_equal(result.GetPortalConstControl().Get(i), expected[i]),
"Wrong result for CellGradient worklet on 3D uniform data");
}
}
void TestCellGradientUniform3DWithVectorField()
{
std::cout << "Testing CellGradient Worklet with a vector field on 3D strucutred data" << std::endl;
vtkm::cont::testing::MakeTestDataSet testDataSet;
vtkm::cont::DataSet dataSet = testDataSet.Make3DUniformDataSet0();
//Verify that we can compute the gradient of a 3 component vector
const int nVerts = 18;
vtkm::Float64 vars[nVerts] = {10.1, 20.1, 30.1, 40.1, 50.2,
60.2, 70.2, 80.2, 90.3, 100.3,
110.3, 120.3, 130.4, 140.4,
150.4, 160.4, 170.5, 180.5};
std::vector< vtkm::Vec<vtkm::Float64,3> > vec(18);
for(std::size_t i=0; i < vec.size(); ++i)
{
vec[i] = vtkm::make_Vec(vars[i],vars[i],vars[i]);
}
vtkm::cont::ArrayHandle< vtkm::Vec<vtkm::Float64,3> > input =
vtkm::cont::make_ArrayHandle(vec);
//we need to add Vec3 array to the dataset
vtkm::cont::ArrayHandle< vtkm::Vec< vtkm::Vec<vtkm::Float64,3>, 3> > result;
vtkm::worklet::DispatcherMapTopology<vtkm::worklet::CellGradient> dispatcher;
dispatcher.Invoke(dataSet.GetCellSet(),
dataSet.GetCoordinateSystem(),
input,
result);
vtkm::Vec< vtkm::Vec<vtkm::Float64,3>, 3> expected[4] = {
{ {10.025,10.025,10.025}, {30.075,30.075,30.075}, {60.125,60.125,60.125} },
{ {10.025,10.025,10.025}, {30.075,30.075,30.075}, {60.125,60.125,60.125} },
{ {10.025,10.025,10.025}, {30.075,30.075,30.075}, {60.175,60.175,60.175} },
{ {10.025,10.025,10.025}, {30.075,30.075,30.075}, {60.175,60.175,60.175} }
};
for (int i = 0; i < 4; ++i)
{
vtkm::Vec< vtkm::Vec<vtkm::Float64,3>, 3> e = expected[i];
vtkm::Vec< vtkm::Vec<vtkm::Float64,3>, 3> r = result.GetPortalConstControl().Get(i);
std::cout << "0: " << e[0] << " " << r[0] << std::endl;
std::cout << "1: " << e[1] << " " << r[1] << std::endl;
std::cout << "2: " << e[2] << " " << r[2] << std::endl;
VTKM_TEST_ASSERT(
test_equal(e[0],r[0]),
"Wrong result for vec field CellGradient worklet on 3D uniform data");
VTKM_TEST_ASSERT(
test_equal(e[1],r[1]),
"Wrong result for vec field CellGradient worklet on 3D uniform data");
VTKM_TEST_ASSERT(
test_equal(e[2],r[2]),
"Wrong result for vec field CellGradient worklet on 3D uniform data");
}
}
void TestCellGradientExplicit()
@ -109,6 +165,7 @@ void TestCellGradient()
{
TestCellGradientUniform2D();
TestCellGradientUniform3D();
TestCellGradientUniform3DWithVectorField();
TestCellGradientExplicit();
}