diff --git a/experimental/CMakeLists.txt b/experimental/CMakeLists.txt index 1f0f9bdace1448f50e9b3756e4c3af2876003be5..64ac4c5bdf3f24d4bfcb21931cfbded1d707fec3 100644 --- a/experimental/CMakeLists.txt +++ b/experimental/CMakeLists.txt @@ -2,7 +2,7 @@ # # Project Declaration #-------------------- -project(scalfmm3 CXX) +project(scalfmm3 CXX C) # check if compiling into source directories string(COMPARE EQUAL "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" insource) if(insource) diff --git a/experimental/cmake/dependencies.cmake b/experimental/cmake/dependencies.cmake index 7b5e7d08a7358c99b010cb6aa8fe991b97f42970..c916bb5aee410684600ce5d78b599b5baf1e2648 100644 --- a/experimental/cmake/dependencies.cmake +++ b/experimental/cmake/dependencies.cmake @@ -8,3 +8,11 @@ include(cmake/dependencies/blas.cmake) include(cmake/dependencies/fftw.cmake) include(cmake/dependencies/starpu.cmake) +if(SCALFMM_USE_CATALYST) + find_package(catalyst REQUIRED) + if(catalyst_FOUND) + message(STATUS "Catalyst found.") + target_link_libraries(${CMAKE_PROJECT_NAME} INTERFACE catalyst::catalyst catalyst::conduit_headers catalyst::conduit catalyst::blueprint) + endif() +endif() + diff --git a/experimental/examples/catalyst_related.hpp b/experimental/examples/catalyst_related.hpp new file mode 100644 index 0000000000000000000000000000000000000000..67a79551d6412bc590f3b4c10a4927fb72eae897 --- /dev/null +++ b/experimental/examples/catalyst_related.hpp @@ -0,0 +1,89 @@ +// -------------------------------- +// See LICENCE file at project root +// File : group_tree.hpp +// -------------------------------- +#ifndef CATALYST_RELATED_HPP +#define CATALYST_RELATED_HPP + +#include "scalfmm/meta/const_functions.hpp" +#include "scalfmm/meta/utils.hpp" +#include "scalfmm/utils/parallel_manager.hpp" +#include <catalyst.h> +#include <conduit.hpp> +#include <conduit_blueprint_mesh.h> +#include <conduit_blueprint_exports.h> +#include <conduit_cpp_to_c.hpp> +#include <inria/tcli/tcli.hpp> +//#include <iostream> + +// catalyst +namespace catalyst_adaptor +{ + template<typename... Parameters> + auto initialize(inria::tcli::parser<Parameters...> const& parser) -> void + { + parallel_manager m; + m.init(); + // here goes scrpits of mpi init communicator + conduit::Node node; + //node["catalyst/scripts/script" + std::to_string(0)].set_string("/home/p13ro/dev/cpp/build/scalfmm/gcc-10.2/catalyst_pipeline.py"); + node["catalyst/mpi_comm"].set(0); + catalyst_initialize(conduit::c_node(&node)); + } + + template<typename GroupTree> + auto execute(std::size_t step, GroupTree const& tree) + { + conduit::Node exec_params; + + //// add time/cycle information + auto& state = exec_params["catalyst/state"]; + state["timestep"].set(step); + state["time"].set(step); + + // Add channels. + // We only have 1 channel here. Let's name it 'grid'. + //auto particles_channel = exec_params["catalyst/channels/particles"]; + auto& box_channel = exec_params["catalyst/channels/box"]; + + // Since this example is using Conduit Mesh Blueprint to define the mesh, + // we set the channel's type to "mesh". + box_channel["type"].set("mesh"); + + const auto n_corners = scalfmm::meta::pow(2,GroupTree::dimension); + + // now create the mesh. + auto& box_mesh = box_channel["data"]; + box_mesh["coordsets/coords/type"].set("explicit"); + box_mesh["coordsets/coords/values/x"].set(conduit::DataType::float64(n_corners)); + box_mesh["coordsets/coords/values/y"].set(conduit::DataType::float64(n_corners)); + + auto const& box = tree.box(); + + conduit::float64* box_sim_x = box_mesh["coordsets/coords/values/x"].value(); + conduit::float64* box_sim_y = box_mesh["coordsets/coords/values/x"].value(); + + for(std::size_t n{0}; n<n_corners; ++n) + { + box_sim_x[n] = scalfmm::meta::get<0>(box.corner(n)); + box_sim_y[n] = scalfmm::meta::get<1>(box.corner(n)); + std::cout << box.corner(n) << '\n'; + } + + // Next, add topology + box_mesh["topologies/mesh/type"].set("line"); + box_mesh["topologies/mesh/coordset"].set("coords"); + //box_mesh["topologies/mesh/elements/shape"].set("box"); + box_mesh["topologies/mesh/elements/connectivity"].set_int32_vector({0,1,2,3}); + + catalyst_execute(conduit::c_node(&exec_params)); + } + + auto finalize() -> void + { + conduit::Node node; + catalyst_finalize(conduit::c_node(&node)); + } +} + +#endif // CATALYST_RELATED_HPP diff --git a/experimental/examples/test-time-loop.cpp b/experimental/examples/test-time-loop.cpp index 80f656f77d82da5d3eaacd2082a35e446ceea2b9..ebde79f67095a211c445fc3c057bf95bb9973f91 100644 --- a/experimental/examples/test-time-loop.cpp +++ b/experimental/examples/test-time-loop.cpp @@ -1,25 +1,20 @@ - -#include "parameters.hpp" -#include "scalfmm/algorithms/common.hpp" -#include "scalfmm/container/particle.hpp" +#include "scalfmm/container/particle.hpp" #include "scalfmm/container/particle_container.hpp" #include "scalfmm/container/point.hpp" #include "scalfmm/interpolation/uniform.hpp" #include "scalfmm/operators/fmmOperators.hpp" - +#include "scalfmm/operators/laplace_operators.hpp" #include "scalfmm/matrix_kernels/laplace.hpp" #include "scalfmm/matrix_kernels/scalar_kernels.hpp" -//#include "scalfmm/operators/generic/l2p.hpp" +#include "scalfmm/algorithms/common.hpp" #include "scalfmm/algorithms/sequential/sequential.hpp" - -#include "scalfmm/tools/colorized.hpp" -#include "scalfmm/tools/tikz_writer.hpp" #include "scalfmm/tree/box.hpp" #include "scalfmm/tree/cell.hpp" +#include "scalfmm/tree/for_each.hpp" #include "scalfmm/tree/group_tree.hpp" #include "scalfmm/tree/leaf.hpp" #include "scalfmm/utils/sort.hpp" - +#include "scalfmm/tools/colorized.hpp" #include "scalfmm/tools/fma_loader.hpp" #include "scalfmm/tools/vtk_writer.hpp" #include "scalfmm/utils/accurater.hpp" @@ -31,7 +26,9 @@ #include <chrono> #include <cstdio> #include <inria/tcli/tcli.hpp> +#include <inria/tcli/help_descriptor.hpp> #include <iostream> +#include <limits> #include <sstream> #include <string> #include <sys/types.h> @@ -40,6 +37,13 @@ #include <unistd.h> #include <utility> #include <vector> + +//#define USE_CATALYST + +#ifdef USE_CATALYST +#include "catalyst_related.hpp" +#endif + // example: // ./examples/RelWithDebInfo/test-time-loop --tree-height 4 -gs 2 --order 4 --dimension 2... namespace local_args @@ -90,7 +94,7 @@ namespace local_args using type = int; type def = 250; }; - struct dimension + struct dimension : inria::tcli::required_tag { inria::tcli::str_vec flags = {"--dimension", "--d"}; const char* description = "Dimension : \n 2 for dimension 2, 3 for dimension 3"; @@ -99,13 +103,28 @@ namespace local_args }; struct time_steps { - inria::tcli::str_vec flags = {"--time-step", "--ts"}; + inria::tcli::str_vec flags = {"--time-steps", "--ts"}; const char* description = "Number of time steps"; using type = std::size_t; type def = 1; }; + struct delta + { + inria::tcli::str_vec flags = {"--delta"}; + const char* description = "Delta to apply on forces"; + using type = double; + type def = 0.1; + }; + struct catalyst + { + inria::tcli::str_vec flags = {"--catalyst"}; + const char* description = "Enable catalist"; + using type = bool; + type def = false; + }; } // namespace local_args + template<std::size_t Dimension, typename ContainerType, typename ValueType> void read_data(const std::string& filename, ContainerType*& container, scalfmm::container::point<ValueType, Dimension>& Centre, ValueType& width) @@ -141,6 +160,58 @@ void read_data(const std::string& filename, ContainerType*& container, } } +template<typename GroupTree, typename ValueType> +auto update_particles(GroupTree& tree, ValueType delta) -> void +{ + scalfmm::component::for_each_leaf(tree.begin(), tree.end(), [delta](auto& leaf) + { + auto& particles{leaf.particles()}; + scalfmm::container::point<ValueType, GroupTree::dimension> force{}; + + for(std::size_t i{0}; i<particles.size(); ++i) + { + auto proxy = particles.at(i); + force = -delta*proxy.position(); + proxy.position() += force; + } + }); +} + +template<typename GroupTree> +auto get_new_box(GroupTree const& tree) -> typename GroupTree::box_type +{ + using value_type = typename GroupTree::leaf_type::particle_type::position_type::value_type; + using box_type = typename GroupTree::box_type; + auto const old_center = tree.box().center(); + + std::vector<value_type> max(GroupTree::dimension, 0); + std::vector<value_type> min(GroupTree::dimension, 0); + + scalfmm::component::for_each_leaf(tree.begin(), tree.end(), [&min, &max, &old_center](auto const& leaf) + { + auto& particles{leaf.particles()}; + for(std::size_t i{0}; i<particles.size(); ++i) + { + const auto position = particles.at(i).position(); + //std::cout << particles.at(i).inputs(0) << '\n'; + for(std::size_t d{0}; d<GroupTree::dimension; ++d) + { + min.at(d) = std::min(position.at(d), min.at(d)); + max.at(d) = std::max(position.at(d), max.at(d)); + //std::cout << particles.at(i).outputs(d) << ' '; + } + //std::cout << '\n'; + } + }); + value_type width{0}; + for(std::size_t i{0}; i < GroupTree::dimension; ++i) + { + width = std::max(std::abs(min.at(i)), max.at(i)); + } + + return box_type(width + std::numeric_limits<value_type>::epsilon(), old_center); +} + template<std::size_t Dimension, typename FmmOperatorType, typename... Parameters> auto run(inria::tcli::parser<Parameters...> const& parser) -> int { @@ -148,6 +219,8 @@ auto run(inria::tcli::parser<Parameters...> const& parser) -> int // timer scalfmm::utils::timer time{}; + static constexpr auto dimension{Dimension}; + using value_type = double; // --------------------------------------- using near_matrix_kernel_type = typename FmmOperatorType::near_field_type::matrix_kernel_type; @@ -179,11 +252,14 @@ auto run(inria::tcli::parser<Parameters...> const& parser) -> int const std::string input_file(parser.template get<local_args::input_file>()); const std::string output_file(parser.template get<local_args::output_file>()); const std::string visu_file(parser.template get<local_args::visu_file>()); + const bool catalyst_enable(parser.template get<local_args::catalyst>()); + const auto delta = parser.template get<local_args::delta>(); std::cout << scalfmm::colors::blue << "<params> Tree height : " << tree_height << scalfmm::colors::reset << '\n'; std::cout << scalfmm::colors::blue << "<params> Group Size : " << group_size << scalfmm::colors::reset << '\n'; std::cout << scalfmm::colors::blue << "<params> Runtime order : " << order << scalfmm::colors::reset << '\n'; std::cout << scalfmm::colors::blue << "<params> Time Steps : " << n_time_steps << scalfmm::colors::reset << '\n'; + std::cout << scalfmm::colors::blue << "<params> Delta forces : " << delta << scalfmm::colors::reset << '\n'; // --------------------------------------- // Open particle file @@ -232,23 +308,45 @@ auto run(inria::tcli::parser<Parameters...> const& parser) -> int std::cout << scalfmm::colors::yellow << "Kernel and Interp created in " << time.elapsed() << "ms\n" << scalfmm::colors::reset; +#ifdef USE_CATALYST + if(catalyst_enable) + { + std::cout << scalfmm::colors::on_blue << "Initializing catalyst..." << scalfmm::colors::reset << '\n'; + catalyst_adaptor::initialize(parser); + } +#endif // --------------------------------------- // start algorithm for step 0 auto operator_to_proceed = scalfmm::algorithms::all; - scalfmm::algorithms::sequential(tree, std::move(fmm_operator), operator_to_proceed); + scalfmm::algorithms::sequential(tree, fmm_operator, operator_to_proceed); // --------------------------------------- // time loop for(std::size_t steps{1}; steps < n_time_steps; ++steps) { - // --- - // compute the forces // --- // update particles + update_particles(tree, delta); + // --- + // visu related post treatment + if(!visu_file.empty()) + { + scalfmm::tools::io::exportVTKxml(std::to_string(steps-1)+visu_file, tree, container->size()); + } + +#ifdef USE_CATALYST + if(catalyst_enable) + { + catalyst_adaptor::execute(steps-1, tree); + } +#endif // --- // compute the corners and set new box + auto const new_box = get_new_box(tree); + std::cout << scalfmm::colors::on_green << "New box width is " << new_box.width(0) << scalfmm::colors::reset << '\n'; // --- // compute new morton indices + // --- // move particles according to new morton indices // --- @@ -256,8 +354,29 @@ auto run(inria::tcli::parser<Parameters...> const& parser) -> int // --- // build tree levels // --- + // start algorithm at step : compute forces + // --- } + // --------------------------------------- + // last step update + // --- + // update particles + // --- + update_particles(tree, delta); + + // --- + // visu related post treatment + if(!visu_file.empty()) + { + scalfmm::tools::io::exportVTKxml(std::to_string(n_time_steps-1) + visu_file, tree, container->size()); + } +#ifdef USE_CATALYST + if(catalyst_enable) + { + } +#endif + // --------------------------------------- // write output fma if(!output_file.empty()) @@ -283,10 +402,10 @@ auto main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) -> int { // // Parameter handling - auto parser = - inria::tcli::make_parser(inria::tcli::help{}, local_args::tree_height{}, local_args::order{}, - local_args::input_file{}, local_args::output_file{}, local_args::block_size{}, - local_args::dimension{}, local_args::time_steps{}, local_args::visu_file{}); + auto parser = inria::tcli::make_parser(inria::tcli::help{}, local_args::tree_height{}, local_args::order{}, + local_args::input_file{}, local_args::output_file{}, + local_args::block_size{}, local_args::dimension{}, local_args::time_steps{}, + local_args::visu_file{}, local_args::delta{}, local_args::catalyst{}); parser.parse(argc, argv); // Getting command line parameters @@ -297,28 +416,29 @@ auto main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) -> int case 2: { constexpr std::size_t dim = 2; - using matrix_kernel_type = scalfmm::matrix_kernels::others::one_over_r2; - using near_field_type = scalfmm::operators::near_field_operator<matrix_kernel_type>; + using near_matrix_kernel_type = scalfmm::matrix_kernels::others::grad_one_over_r2<dim>; + using near_field_type = scalfmm::operators::near_field_operator<near_matrix_kernel_type>; // - using interpolator_type = scalfmm::interpolation::uniform_interpolator<double, dim, matrix_kernel_type>; - using far_field_type = scalfmm::operators::far_field_operator<interpolator_type>; + using far_matrix_kernel_type = scalfmm::matrix_kernels::others::one_over_r2; + using interpolator_type = scalfmm::interpolation::uniform_interpolator<double, dim, far_matrix_kernel_type>; + using far_field_type = scalfmm::operators::far_field_operator<interpolator_type, true>; run<dim, scalfmm::operators::fmm_operators<near_field_type, far_field_type>>(parser); break; } - case 3: - { - constexpr std::size_t dim = 3; - using matrix_kernel_type = scalfmm::matrix_kernels::others::one_over_r2; - // using matrix_kernel_type = scalfmm::matrix_kernels::laplace::one_over_r; - using near_field_type = scalfmm::operators::near_field_operator<matrix_kernel_type>; - // - using interpolator_type = scalfmm::interpolation::uniform_interpolator<double, dim, matrix_kernel_type>; - using far_field_type = scalfmm::operators::far_field_operator<interpolator_type>; + //case 3: + //{ + // constexpr std::size_t dim = 3; + // using matrix_kernel_type = scalfmm::matrix_kernels::others::one_over_r2; + // // using matrix_kernel_type = scalfmm::matrix_kernels::laplace::one_over_r; + // using near_field_type = scalfmm::operators::near_field_operator<matrix_kernel_type>; + // // + // using interpolator_type = scalfmm::interpolation::uniform_interpolator<double, dim, matrix_kernel_type>; + // using far_field_type = scalfmm::operators::far_field_operator<interpolator_type>; - run<dim, scalfmm::operators::fmm_operators<near_field_type, far_field_type>>(parser); - break; - } + // run<dim, scalfmm::operators::fmm_operators<near_field_type, far_field_type>>(parser); + // break; + //} default: std::cout << "check 1/r^2 Kernel for dimension 2 and 3. Value is \n" << " 0 for dimension 2 "