#pragma once #include "memory.h" #include "call_tag.h" #include "operator.h" #include "propagate.h" #include "kernel/initialize.h" #include "kernel/executor.h" template class Lattice { private: const descriptor::Cuboid _cuboid; CyclicPopulationBuffer _population; public: Lattice(descriptor::Cuboid cuboid): _cuboid(cuboid), _population(cuboid) { } descriptor::Cuboid cuboid() const { return _cuboid; } void stream() { _population.stream(); } template void apply(OPERATOR... ops) { const auto block_size = 32; const auto block_count = (_cuboid.volume + block_size - 1) / block_size; kernel::call_operators<<>>( _population.view(), ops... ); } template void apply(ARGS&&... args) { call_operator(typename OPERATOR::call_tag{}, std::forward(args)...); } template void call_operator(tag::call_by_cell_id, DeviceBuffer& cells, ARGS... args) { const auto block_size = 32; const auto block_count = (cells.size() + block_size - 1) / block_size; kernel::call_operator<<>>( _population.view(), cells.device(), cells.size(), std::forward(args)... ); } template void call_operator(tag::call_by_cell_id, DeviceBuffer& mask, ARGS... args) { const auto block_size = 32; const auto block_count = (_cuboid.volume + block_size - 1) / block_size; kernel::call_operator<<>>( _population.view(), mask.device(), std::forward(args)... ); } template void call_operator(tag::call_by_list_index, std::size_t count, ARGS... args) { const auto block_size = 32; const auto block_count = (count + block_size - 1) / block_size; kernel::call_operator_using_list<<>>( _population.view(), count, std::forward(args)... ); } template void inspect(ARGS&&... args) { call_functor(typename FUNCTOR::call_tag{}, std::forward(args)...); } template void call_functor(tag::call_by_cell_id, DeviceBuffer& cells, ARGS... args) { const auto block_size = 32; const auto block_count = (cells.size() + block_size - 1) / block_size; kernel::call_functor<<>>( _population.view(), cells.device(), cells.size(), std::forward(args)... ); } template void call_functor(tag::call_by_cell_id, DeviceBuffer& mask, ARGS... args) { const auto block_size = 32; const auto block_count = (_cuboid.volume + block_size - 1) / block_size; kernel::call_functor<<>>( _population.view(), mask.device(), std::forward(args)... ); } template void call_functor(tag::call_by_spatial_cell_mask, DeviceBuffer& mask, ARGS... args) { const dim3 block(32,8,4); const dim3 grid((_cuboid.nX + block.x - 1) / block.x, (_cuboid.nY + block.y - 1) / block.y, (_cuboid.nZ + block.z - 1) / block.z); kernel::call_spatial_functor<<>>( _population.view(), mask.device(), std::forward(args)... ); } template void helper(ARGS&&... args) { tagged_helper(typename OPERATOR::call_tag{}, std::forward(args)...); } template void tagged_helper(tag::post_process_by_list_index, std::size_t count, ARGS... args) { const auto block_size = 32; const auto block_count = (count + block_size - 1) / block_size; kernel::call_operator_using_list<<>>( DESCRIPTOR(), count, std::forward(args)... ); } template void tagged_helper(tag::post_process_by_spatial_cell_mask, DeviceBuffer& mask, ARGS... args) { const dim3 block(32,8,4); const dim3 grid((_cuboid.nX + block.x - 1) / block.x, (_cuboid.nY + block.y - 1) / block.y, (_cuboid.nZ + block.z - 1) / block.z); kernel::call_spatial_operator<<>>( _cuboid, mask.device(), std::forward(args)... ); } };