Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for mixed element unstructured meshes #1309

Merged
merged 21 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ and this project aspires to adhere to [Semantic Versioning](https://semver.org/s
- kokkos@3.7.02

### Added
- Added support for unstructured topologies with mixed elements types (for example, hexs and tets).
- Added support for `pyramid` and `wedge` elements.
- Added a `topologies` option to the relay extract. This allows you to select which topologies are saved. This option can be used with the existing `fields` option, the result is the union of the selected topologies and fields.
- Added `near_plane` and `far_plane` to the camera details provided in Ascent::info()


## [0.9.3] - Released 2024-05-11
### Preferred dependency versions for ascent@0.9.3
- conduit@0.9.1
Expand Down
260 changes: 207 additions & 53 deletions src/libs/ascent/runtimes/ascent_vtkh_data_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,76 @@ void CopyArray(vtkm::cont::ArrayHandle<T> &vtkm_handle, const T* vals_ptr, const
vtkm_handle = vtkm::cont::make_ArrayHandle(vals_ptr, size, copy);
}


template<typename T>
void
BlueprintIndexArrayToVTKmIdArray(const conduit::Node &n,
bool zero_copy,
vtkm::cont::ArrayHandle<T> &vtkm_handle)
{
int array_size = n.dtype().number_of_elements();

if( sizeof(T) == 1 ) // uint8 is what vtk-m will use for this case.
{
if(n.is_compact() && n.dtype().is_uint8())
{
// directly compatible
const void *idx_ptr = n.data_ptr();
CopyArray(vtkm_handle, (const T*)idx_ptr, array_size,zero_copy);
}
else
{
// we need to convert to uint8 to match vtkm::Id
vtkm_handle.Allocate(array_size);
void *ptr = (void*) vtkh::GetVTKMPointer(vtkm_handle);
Node n_tmp;
n_tmp.set_external(DataType::uint8(array_size),ptr);
n.to_uint8_array(n_tmp);
}
}
else if( sizeof(T) == 2)
{
// unsupported! -- TODO ERROR!
cyrush marked this conversation as resolved.
Show resolved Hide resolved
}
else if( sizeof(T) == 4) // int32 is what vtk-m will use for this case.
{
if(n.is_compact() && n.dtype().is_int32())
{
// directly compatible
const void *idx_ptr = n.data_ptr();
CopyArray(vtkm_handle, (const T*)idx_ptr, array_size,zero_copy);
}
else
{
// we need to convert to int32 to match vtkm::Id
vtkm_handle.Allocate(array_size);
void *ptr = (void*) vtkh::GetVTKMPointer(vtkm_handle);
Node n_tmp;
n_tmp.set_external(DataType::int32(array_size),ptr);
n.to_int32_array(n_tmp);
}
}
else if( sizeof(T) == 8) // int64 is what vtk-m will use for this case.
{
if(n.is_compact() && n.dtype().is_int64())
{
// directly compatible
const void *idx_ptr = n.data_ptr();
CopyArray(vtkm_handle, (const T*)idx_ptr, array_size, zero_copy);
}
else
{
// we need to convert to int64 to match vtkm::Id
vtkm_handle.Allocate(array_size);
void *ptr = (void*) vtkh::GetVTKMPointer(vtkm_handle);
Node n_tmp;
n_tmp.set_external(DataType::int64(array_size),ptr);
n.to_int64_array(n_tmp);
}
}
}


template<typename T>
vtkm::cont::CoordinateSystem
GetExplicitCoordinateSystem(const conduit::Node &n_coords,
Expand Down Expand Up @@ -1396,64 +1466,61 @@ VTKHDataAdapter::UnstructuredBlueprintToVTKmDataSet
// shapes, number of indices, and connectivity.
// Will have to do something different if this is a "zoo"

// TODO: there is a special data set type for single cell types

const Node &n_topo_eles = n_topo["elements"];
std::string ele_shape = n_topo_eles["shape"].as_string();

// TODO: assumes int32, and contiguous
if(ele_shape == "mixed")
{
// blueprint allows mapping of shape names
// to arbitrary ids, check if shape ids match the VTK-m ids
index_t num_of_shapes = n_topo_eles["shape_map"].number_of_children();

// if(!detail::CheckShapeMapVsVTKmShapeIds(n_topo_eles["shape_map"]))
cyrush marked this conversation as resolved.
Show resolved Hide resolved
// {
// // TODO -- solve this (strategy to remap ids)
// ASCENT_ERROR("Shape Map Entries do not match VTK-m Ids");
// }

index_t num_ids = n_topo_eles["connectivity"].dtype().number_of_elements();
// number of elements is the number of shapes presented
neles = (int) n_topo_eles["shapes"].dtype().number_of_elements();

const Node &n_topo_conn = n_topo_eles["connectivity"];
vtkm::cont::ArrayHandle<vtkm::Id> vtkm_conn;
detail::BlueprintIndexArrayToVTKmIdArray(n_topo_eles["connectivity"],
zero_copy,
vtkm_conn);

vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
// shapes
vtkm::cont::ArrayHandle<vtkm::UInt8> vtkm_shapes;
detail::BlueprintIndexArrayToVTKmIdArray(n_topo_eles["shapes"],
zero_copy,
vtkm_shapes);

int conn_size = n_topo_conn.dtype().number_of_elements();

if( sizeof(vtkm::Id) == 4)
{
if(n_topo_conn.is_compact() && n_topo_conn.dtype().is_int32())
{
const void *ele_idx_ptr = n_topo_conn.data_ptr();
detail::CopyArray(connectivity, (const vtkm::Id*)ele_idx_ptr, conn_size,zero_copy);
}
else
{
// convert to int32
// std::cout << "INT32 unstructured conversion: non zero copy" << std::endl;
connectivity.Allocate(conn_size);
void *ptr = (void*) vtkh::GetVTKMPointer(connectivity);
Node n_tmp;
n_tmp.set_external(DataType::int32(conn_size),ptr);
n_topo_conn.to_int32_array(n_tmp);
}
// offsets
vtkm::cont::ArrayHandle<vtkm::Id> vtkm_offsets;
detail::BlueprintIndexArrayToVTKmIdArray(n_topo_eles["offsets"],
zero_copy,
vtkm_offsets);


vtkm::cont::CellSetExplicit<> cell_set;
cell_set.Fill(num_ids, vtkm_shapes, vtkm_conn, vtkm_offsets);
cyrush marked this conversation as resolved.
Show resolved Hide resolved
result->SetCellSet(cell_set);
// for debugging help
// result->PrintSummary(std::cout);
}
else
{
if(n_topo_conn.is_compact() && n_topo_conn.dtype().is_int64())
{
const void *ele_idx_ptr = n_topo_conn.data_ptr();
detail::CopyArray(connectivity, (const vtkm::Id*)ele_idx_ptr, conn_size, zero_copy);
}
else
{
// convert to int64
// std::cout << "INT64 unstructured conversion: non zero copy" << std::endl;
connectivity.Allocate(conn_size);
void *ptr = (void*) vtkh::GetVTKMPointer(connectivity);
Node n_tmp;
n_tmp.set_external(DataType::int64(conn_size),ptr);
n_topo_conn.to_int64_array(n_tmp);
}
vtkm::cont::ArrayHandle<vtkm::Id> vtkm_conn;
detail::BlueprintIndexArrayToVTKmIdArray(n_topo_eles["connectivity"],zero_copy,vtkm_conn);
vtkm::UInt8 shape_id;
vtkm::IdComponent indices_per;
detail::VTKmCellShape(ele_shape, shape_id, indices_per);
vtkm::cont::CellSetSingleType<> cell_set;
cell_set.Fill(nverts, shape_id, indices_per, vtkm_conn);
neles = cell_set.GetNumberOfCells();
result->SetCellSet(cell_set);
}

vtkm::UInt8 shape_id;
vtkm::IdComponent indices_per;
detail::VTKmCellShape(ele_shape, shape_id, indices_per);
vtkm::cont::CellSetSingleType<> cellset;
cellset.Fill(nverts, shape_id, indices_per, connectivity);
neles = cellset.GetNumberOfCells();
result->SetCellSet(cellset);

return result;
}

Expand Down Expand Up @@ -1887,17 +1954,59 @@ GetBlueprintCellName(vtkm::UInt8 shape_id)
{
name = "hex";
}
else if(shape_id == vtkm::CELL_SHAPE_WEDGE)
{
name = "wedge";
}
else if(shape_id == vtkm::CELL_SHAPE_PYRAMID)
{
name = "pyramid";
}
else if(shape_id == vtkm::CELL_SHAPE_WEDGE)
{
name = "wedge";
}
return name;
}


inline index_t
vtkm_shape_size(vtkm::Id shape_id)
{
switch(shape_id)
{
// point
case vtkm::CELL_SHAPE_VERTEX: return 1; break;
// line
case vtkm::CELL_SHAPE_LINE: return 2; break;
// tri
case vtkm::CELL_SHAPE_TRIANGLE: return 3; break;
// quad
case vtkm::CELL_SHAPE_QUAD: return 4; break;
// tet
case vtkm::CELL_SHAPE_TETRA: return 4; break;
// hex
case vtkm::CELL_SHAPE_HEXAHEDRON: return 8; break;
// pyramid
case vtkm::CELL_SHAPE_PYRAMID: return 5; break;
// wedge
case vtkm::CELL_SHAPE_WEDGE: return 6; break;
//
default: return 0;
}
}


void
generate_sizes_from_shapes(const conduit::Node &shapes,conduit::Node &sizes)
{
index_t num_eles = shapes.dtype().number_of_elements();
uint8_array shapes_arr = shapes.value();
index_t_array sizes_arr = sizes.value();

for(index_t i=0; i < num_eles; i++)
{
sizes_arr[i] = vtkm_shape_size(shapes_arr[i]);
}

}

bool
VTKHDataAdapter::VTKmTopologyToBlueprint(conduit::Node &output,
const vtkm::cont::DataSet &data_set,
Expand Down Expand Up @@ -2265,8 +2374,38 @@ VTKHDataAdapter::VTKmTopologyToBlueprint(conduit::Node &output,
else
{
data_set.PrintSummary(std::cout);
ASCENT_ERROR("Mixed explicit types not implemented");
//ASCENT_ERROR("Mixed explicit types not implemented");
MixedType cells = dyn_cells.AsCellSet<MixedType>();
Node &topo_ele = output
["topologies/" + topo_name + "/elements"];
topo_ele["shape"] = "mixed";

VTKmBlueprintShapeMap(topo_ele["shape_map"]);

size_t num_cells = static_cast<size_t>(cells.GetNumberOfCells());
auto vtkm_shapes = cells.GetShapesArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{});
auto vtkm_conn = cells.GetConnectivityArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{});
auto vtkm_offsets = cells.GetOffsetsArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{});


std::size_t conn_size = static_cast<std::size_t>(vtkm_conn.GetNumberOfValues());

if(zero_copy)
{
topo_ele["shapes"].set_external(vtkh::GetVTKMPointer(vtkm_shapes), num_cells);
topo_ele["connectivity"].set_external(vtkh::GetVTKMPointer(vtkm_conn), conn_size);
topo_ele["offsets"].set_external(vtkh::GetVTKMPointer(vtkm_offsets), num_cells);
}
else
{
topo_ele["shapes"].set(vtkh::GetVTKMPointer(vtkm_shapes), num_cells);
topo_ele["connectivity"].set(vtkh::GetVTKMPointer(vtkm_conn), conn_size);
topo_ele["offsets"].set(vtkh::GetVTKMPointer(vtkm_offsets), num_cells);
}

// bp requires sizes, so we have to compute them
topo_ele["sizes"].set(DataType::index_t(num_cells));
generate_sizes_from_shapes(topo_ele["shapes"],topo_ele["sizes"]);
}

}
Expand Down Expand Up @@ -2491,6 +2630,21 @@ VTKHDataAdapter::VTKmFieldToBlueprint(conduit::Node &output,
}
}


void
VTKHDataAdapter::VTKmBlueprintShapeMap(conduit::Node &output)
{
output.reset();
output["tri"] = 5;
output["quad"] = 9;
output["tet"] = 10;
output["hex"] = 12;
output["point"] = 1;
output["line"] = 3;
output["wedge"] = 13;
output["pyramid"] = 14;
}

void VTKHDataAdapter::VTKHCollectionToBlueprintDataSet(VTKHCollection *collection,
conduit::Node &node,
bool zero_copy)
Expand Down
3 changes: 3 additions & 0 deletions src/libs/ascent/runtimes/ascent_vtkh_data_adapter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ class ASCENT_API VTKHDataAdapter
const std::string &topo_name,
bool zero_copy);

static void VTKmBlueprintShapeMap(conduit::Node &output);


};

//-----------------------------------------------------------------------------
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/tests/ascent/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ set(BASIC_TESTS t_ascent_smoke
t_ascent_render_3d
t_ascent_render_2d_poly
t_ascent_render_3d_poly
t_ascent_render_2d_mixed
t_ascent_render_3d_mixed
t_ascent_render_auto_camera
t_ascent_info
t_ascent_render_bounds
Expand Down
Loading
Loading