Add helper class to build curvilinear datasets.

This commit is contained in:
Dave Pugmire 2021-06-09 13:50:01 -04:00
parent 65ad7b3721
commit 3588209562
5 changed files with 323 additions and 0 deletions

@ -75,6 +75,7 @@ set(headers
ColorTableSamples.h
CoordinateSystem.h
DataSet.h
DataSetBuilderCurvilinear.h
DataSetBuilderExplicit.h
DataSetBuilderRectilinear.h
DataSetBuilderUniform.h
@ -173,6 +174,7 @@ set(device_sources
ColorTable.cxx
CoordinateSystem.cxx
DataSet.cxx
DataSetBuilderCurvilinear.cxx
DataSetBuilderExplicit.cxx
DataSetBuilderRectilinear.cxx
DataSetBuilderUniform.cxx

@ -0,0 +1,22 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/DataSetBuilderCurvilinear.h>
namespace vtkm
{
namespace cont
{
VTKM_CONT
DataSetBuilderCurvilinear::DataSetBuilderCurvilinear() {}
}
} // end namespace vtkm::cont

@ -0,0 +1,145 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_cont_DataSetBuilderCurvilinear_h
#define vtk_m_cont_DataSetBuilderCurvilinear_h
#include <vtkm/cont/ArrayHandleSOA.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DataSet.h>
namespace vtkm
{
namespace cont
{
class VTKM_CONT_EXPORT DataSetBuilderCurvilinear
{
public:
VTKM_CONT
DataSetBuilderCurvilinear();
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(const std::vector<T>& xVals,
const std::string& coordsNm = "coords")
{
VTKM_ASSERT(xVals.size() > 0);
std::vector<T> yVals(xVals.size(), 0), zVals(xVals.size(), 0);
vtkm::Id dim = static_cast<vtkm::Id>(xVals.size());
auto coords = vtkm::cont::make_ArrayHandleSOA<vtkm::Vec<T, 3>>({ xVals, yVals, zVals });
return DataSetBuilderCurvilinear::Create(coords, { dim, 1, 1 }, 1, coordsNm);
}
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(const std::vector<T>& xVals,
const std::vector<T>& yVals,
const vtkm::Id2& dims,
const std::string& coordsNm = "coords")
{
VTKM_ASSERT(xVals.size() > 0 && xVals.size() == yVals.size());
std::vector<T> zVals(xVals.size(), 0);
auto coords = vtkm::cont::make_ArrayHandleSOA<vtkm::Vec<T, 3>>({ xVals, yVals, zVals });
return DataSetBuilderCurvilinear::Create(coords, { dims[0], dims[1], 1 }, 2, coordsNm);
}
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(const std::vector<T>& xVals,
const std::vector<T>& yVals,
const std::vector<T>& zVals,
const vtkm::Id3& dims,
const std::string& coordsNm = "coords")
{
VTKM_ASSERT(xVals.size() > 0 && xVals.size() == yVals.size());
VTKM_ASSERT(xVals.size() == zVals.size());
auto coords = vtkm::cont::make_ArrayHandleSOA<vtkm::Vec<T, 3>>({ xVals, yVals, zVals });
return DataSetBuilderCurvilinear::Create(coords, dims, 3, coordsNm);
}
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(const std::vector<vtkm::Vec<T, 3>>& points,
const vtkm::Id3& dims,
const std::string& coordsNm = "coords")
{
auto coords = vtkm::cont::make_ArrayHandle(points);
return DataSetBuilderCurvilinear::Create(coords, dims, 3, coordsNm);
}
template <typename CoordsType>
VTKM_CONT static vtkm::cont::DataSet Create(const CoordsType& coords,
const vtkm::Id3& dimensions,
const std::string& coordsNm = "coords")
{
return DataSetBuilderCurvilinear::Create(coords, dimensions, 3, coordsNm);
}
template <typename CoordsType>
VTKM_CONT static vtkm::cont::DataSet Create(const CoordsType& coords,
const vtkm::Id2& dimensions,
const std::string& coordsNm = "coords")
{
vtkm::Id3 dims(dimensions[0], dimensions[1], 1);
return DataSetBuilderCurvilinear::Create(coords, dims, 2, coordsNm);
}
template <typename CoordsType>
VTKM_CONT static vtkm::cont::DataSet Create(const CoordsType& coords,
const std::string& coordsNm = "coords")
{
return DataSetBuilderCurvilinear::Create(
coords, { coords.GetNumberOfValues(), 1, 1 }, 1, coordsNm);
}
private:
template <typename CoordsType>
VTKM_CONT static vtkm::cont::DataSet Create(const CoordsType& coords,
const vtkm::Id3& dims,
const vtkm::Id& cellSetDim,
const std::string& coordsNm = "coords")
{
VTKM_ASSERT(dims[0] >= 1 && dims[1] >= 1 && dims[2] >= 1);
VTKM_ASSERT(coords.GetNumberOfValues() == dims[0] * dims[1] * dims[2]);
vtkm::cont::DataSet ds;
ds.AddCoordinateSystem(vtkm::cont::CoordinateSystem(coordsNm, coords));
if (cellSetDim == 3)
{
vtkm::cont::CellSetStructured<3> cellSet;
cellSet.SetPointDimensions(dims);
ds.SetCellSet(cellSet);
}
else if (cellSetDim == 2)
{
vtkm::cont::CellSetStructured<2> cellSet;
cellSet.SetPointDimensions({ dims[0], dims[1] });
ds.SetCellSet(cellSet);
}
else if (cellSetDim == 1)
{
vtkm::cont::CellSetStructured<1> cellSet;
cellSet.SetPointDimensions(dims[0]);
ds.SetCellSet(cellSet);
}
else
throw vtkm::cont::ErrorBadValue("Unsupported CellSetStructured dimension.");
return ds;
}
};
} // namespace cont
} // namespace vtkm
#endif //vtk_m_cont_DataSetBuilderCurvilinear_h

@ -64,6 +64,7 @@ set(unit_tests
UnitTestCellSetExtrude.cxx
UnitTestCellSetPermutation.cxx
UnitTestContTesting.cxx
UnitTestDataSetBuilderCurvilinear.cxx
UnitTestDataSetBuilderExplicit.cxx
UnitTestDataSetBuilderRectilinear.cxx
UnitTestDataSetBuilderUniform.cxx

@ -0,0 +1,153 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/CellSetStructured.h>
#include <vtkm/cont/DataSetBuilderCurvilinear.h>
#include <vtkm/cont/DynamicCellSet.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <algorithm>
#include <random>
#include <time.h>
#include <vector>
namespace DataSetBuilderCurvilinearNamespace
{
std::mt19937 g_RandomGenerator;
void ValidateDataSet(const vtkm::cont::DataSet& ds,
int dim,
vtkm::Id numPoints,
vtkm::Id numCells,
vtkm::Bounds bounds)
{
//Verify basics..
VTKM_TEST_ASSERT(ds.GetNumberOfFields() == 2, "Wrong number of fields.");
VTKM_TEST_ASSERT(ds.GetNumberOfCoordinateSystems() == 1, "Wrong number of coordinate systems.");
VTKM_TEST_ASSERT(ds.GetNumberOfPoints() == numPoints, "Wrong number of coordinates.");
VTKM_TEST_ASSERT(ds.GetNumberOfCells() == numCells, "Wrong number of cells.");
// test various field-getting methods and associations
try
{
ds.GetCellField("cellvar");
}
catch (...)
{
VTKM_TEST_FAIL("Failed to get field 'cellvar' with Association::CELL_SET.");
}
try
{
ds.GetPointField("pointvar");
}
catch (...)
{
VTKM_TEST_FAIL("Failed to get field 'pointvar' with ASSOC_POINT_SET.");
}
//Make sure bounds are correct.
vtkm::Bounds res = ds.GetCoordinateSystem().GetBounds();
VTKM_TEST_ASSERT(test_equal(bounds, res), "Bounds of coordinates do not match");
if (dim == 1)
{
vtkm::cont::CellSetStructured<1> cellSet;
ds.GetCellSet().CopyTo(cellSet);
vtkm::IdComponent shape = cellSet.GetCellShape();
VTKM_TEST_ASSERT(shape == vtkm::CELL_SHAPE_LINE, "Wrong element type");
}
else if (dim == 2)
{
vtkm::cont::CellSetStructured<2> cellSet;
ds.GetCellSet().CopyTo(cellSet);
vtkm::IdComponent shape = cellSet.GetCellShape();
VTKM_TEST_ASSERT(shape == vtkm::CELL_SHAPE_QUAD, "Wrong element type");
}
else if (dim == 3)
{
vtkm::cont::CellSetStructured<3> cellSet;
ds.GetCellSet().CopyTo(cellSet);
vtkm::IdComponent shape = cellSet.GetCellShape();
VTKM_TEST_ASSERT(shape == vtkm::CELL_SHAPE_HEXAHEDRON, "Wrong element type");
}
}
template <typename T>
void AddFields(vtkm::cont::DataSet& ds, vtkm::Id numPoints, vtkm::Id numCells)
{
//Add some fields.
std::vector<T> cellVar(numCells, 0), pointVar(numPoints, 1);
ds.AddPointField("pointvar", pointVar);
ds.AddCellField("cellvar", cellVar);
}
template <typename T>
void CurvilinearTests()
{
constexpr T minReal = -10, maxReal = 10;
std::uniform_real_distribution<T> randomVal(minReal, maxReal);
std::uniform_int_distribution<vtkm::Id> randomDim(2, 20);
for (int i = 0; i < 10; i++)
{
vtkm::Id3 dims(
randomDim(g_RandomGenerator), randomDim(g_RandomGenerator), randomDim(g_RandomGenerator));
vtkm::Id numPoints = dims[0] * dims[1] * dims[2];
vtkm::Id numCells = (dims[0] - 1) * (dims[1] - 1) * (dims[2] - 1);
std::vector<T> x, y, z;
for (vtkm::Id j = 0; j < numPoints; j++)
{
x.push_back(randomVal(g_RandomGenerator));
y.push_back(randomVal(g_RandomGenerator));
z.push_back(randomVal(g_RandomGenerator));
}
vtkm::Bounds bounds(minReal, maxReal, minReal, maxReal, minReal, maxReal);
//test 3d
{
auto ds = vtkm::cont::DataSetBuilderCurvilinear::Create(x, y, z, dims);
AddFields<T>(ds, numPoints, numCells);
ValidateDataSet(ds, 3, numPoints, numCells, bounds);
}
//test 2d
{
auto ds = vtkm::cont::DataSetBuilderCurvilinear::Create(x, y, { dims[0], dims[1] });
AddFields<T>(ds, numPoints, numCells);
ValidateDataSet(ds, 2, numPoints, numCells, bounds);
}
//test 1d
{
auto ds = vtkm::cont::DataSetBuilderCurvilinear::Create(x);
AddFields<T>(ds, numPoints, numCells);
ValidateDataSet(ds, 1, numPoints, numCells, bounds);
}
}
}
void TestDataSetBuilderCurvilinear()
{
vtkm::UInt32 seed = static_cast<vtkm::UInt32>(time(nullptr));
g_RandomGenerator.seed(seed);
CurvilinearTests<vtkm::Float32>();
CurvilinearTests<vtkm::Float64>();
}
} // namespace DataSetBuilderCurvilinearNamespace
int UnitTestDataSetBuilderCurvilinear(int argc, char* argv[])
{
using namespace DataSetBuilderCurvilinearNamespace;
return vtkm::cont::testing::Testing::Run(TestDataSetBuilderCurvilinear, argc, argv);
}