-
Olivier COULAUD authored
Fixed argument problem with omp
Olivier COULAUD authoredFixed argument problem with omp
omp.hpp 11.07 KiB
// --------------------------------
// See LICENCE file at project root
// File : scalfmm/lists/omp.hpp
// --------------------------------
#ifndef SCALFMM_LISTS_OMP_HPP
#define SCALFMM_LISTS_OMP_HPP
#define SCALFMM_LISTS_OMP
#include "scalfmm/algorithms/omp/priorities.hpp"
#include "scalfmm/lists/utils.hpp"
#include "scalfmm/utils/io_helpers.hpp"
namespace scalfmm::list::omp
{
/**
* @brief Construct the P2P interaction list for the target tree
*
* @tparam SourceTreeType
* @tparam TargetTreeType
* @param[in] source_tree the tree containing the sources
* @param[inout] target_tree the tree containing the targets.
* @param[in] neighbour_separation separation criterion use to separate teh near and the far field
* @param[in] mutual boolean to specify if the direct pass use a symmetric algorithm (mutual interactions)
*/
template<typename SourceTreeType, typename TargetTreeType>
inline auto build_p2p_interaction_list(SourceTreeType const& source_tree, TargetTreeType& target_tree,
const int& neighbour_separation, const bool mutual) -> void
{
// We iterate on the leaves
// true if source == target
bool source_target{false};
if constexpr(std::is_same_v<std::decay_t<SourceTreeType>, std::decay_t<TargetTreeType>>)
{
source_target = (&source_tree == &target_tree);
}
if((!source_target) && mutual)
{
throw std::invalid_argument(
" Mutual set to true is prohibited when the sources are different from the targets.\n");
}
// std::cout << std::boolalpha << "source == target " << source_target << std::endl;
const auto& period = target_tree.box().get_periodicity();
const auto leaf_level = target_tree.leaf_level();
auto begin_of_source_groups = std::get<0>(source_tree.begin());
auto end_of_source_groups = std::get<0>(source_tree.end());
// Iterate on the group of leaves I own
component::for_each(
target_tree.begin_mine_leaves(), target_tree.end_mine_leaves(),
[&period, &neighbour_separation, &begin_of_source_groups, &end_of_source_groups, &leaf_level, mutual,
source_target](auto& group_target)
{
auto group_target_ptr = group_target;
static constexpr int prio{scalfmm::algorithms::omp::priorities::max};
#pragma omp task untied default(none) firstprivate(begin_of_source_groups, end_of_source_groups, group_target_ptr) \
shared(leaf_level, mutual, source_target, period, neighbour_separation) priority(prio)
{
std::size_t index_in_group{0};
// Iterate on leaves inside the group
component::for_each(
std::begin(*group_target_ptr), std::end(*group_target_ptr),
[&group_target_ptr, &index_in_group, &begin_of_source_groups, &end_of_source_groups, &period,
&neighbour_separation, &leaf_level, mutual, source_target](auto& leaf_target)
{
scalfmm::list::build_p2p_interaction_list_inside_group(
leaf_target, begin_of_source_groups, end_of_source_groups, *group_target_ptr, index_in_group,
leaf_level, mutual, period, neighbour_separation, source_target);
++index_in_group;
});
//
if(mutual)
{
// here we are in the case that source == target and mutual interactions (optimization)
scalfmm::list::build_out_of_group_interactions(begin_of_source_groups, *group_target_ptr);
}
}
});
#pragma omp taskwait
target_tree.is_interaction_p2p_lists_built() = true;
}
/**
* @brief Construct the M2L interaction list for the target tree
*
* @tparam SourceTreeType
* @tparam TargetTreeType
* @param[in] source_tree the tree containing the sources
* @param[inout] target_tree the tree containing the targets.
* @param[in] neighbour_separation separation criterion use to separate teh near and the far field
*/
template<typename SourceTreeType, typename TargetTreeType>
inline auto build_m2l_interaction_list(SourceTreeType& source_tree, TargetTreeType& target_tree,
const int& neighbour_separation, const int leaf_neighbour_separation) -> void
{
// Iterate on the group of leaves
// here we get the first level of cells (leaf_level up to the top_level)
auto tree_height = target_tree.height();
int leaf_level = int(tree_height) - 1;
auto const& period = target_tree.box().get_periodicity();
auto const& top_level = target_tree.box().is_periodic() ? 1 : 2;
//
// auto cell_source_level_it = std::get<1>(source_tree.begin()) + leaf_level;
for(int level = leaf_level; level >= top_level; --level)
{
auto separation_criterion = level == leaf_level ? leaf_neighbour_separation : neighbour_separation;
// target
auto group_of_cell_begin = target_tree.begin_mine_cells(level);
auto group_of_cell_end = target_tree.end_mine_cells(level);
// source
// auto begin_of_source_cell_groups = std::begin(*cell_source_level_it);
// auto end_of_source_cell_groups = std::end(*cell_source_level_it);
auto begin_of_source_cell_groups = source_tree.begin_cells(level);
auto end_of_source_cell_groups = source_tree.end_cells(level);
// loop on target group
component::for_each(group_of_cell_begin, group_of_cell_end,
[begin_of_source_cell_groups, end_of_source_cell_groups, level, &period,
&separation_criterion](auto& group_target)
{
static constexpr int prio{scalfmm::algorithms::omp::priorities::max};
#pragma omp task untied default(none) \
firstprivate(group_target, begin_of_source_cell_groups, end_of_source_cell_groups, level) \
shared(period, separation_criterion) priority(prio)
{
// loop on target cell group
component::for_each(
std::begin(*group_target), std::end(*group_target),
[&group_target, begin_of_source_cell_groups, end_of_source_cell_groups, level,
&period, &separation_criterion](auto& cell)
{
list::build_m2l_interaction_list_for_group(
*group_target, cell, begin_of_source_cell_groups,
end_of_source_cell_groups, level, period, separation_criterion);
});
}
});
// --cell_source_level_it;
}
#pragma omp taskwait
target_tree.is_interaction_m2l_lists_built() = true;
}
/**
* @brief Construct the P2P and the M2L interaction lists for the target tree.
*
* @tparam SourceTreeType
* @tparam TargetTreeType
* @param[in] source_tree the tree containing the sources.
* @param[inout] target_tree the tree containing the targets.
* @param[in] neighbour_separation separation criterion use to separate teh near and the far field.
* @param[in] mutual boolean to specify if the direct pass use a symmetric algorithm (mutual interactions).
*/
template<typename SourceTreeType, typename TargetTreeType>
inline auto build_interaction_lists(SourceTreeType& source_tree, TargetTreeType& target_tree,
const int& neighbour_separation, const bool mutual) -> void
{
#pragma omp parallel default(none) shared(source_tree, target_tree, neighbour_separation, mutual)
{
#pragma omp single nowait
{
build_m2l_interaction_list(source_tree, target_tree, neighbour_separation, neighbour_separation);
}
#pragma omp single
{
build_p2p_interaction_list(source_tree, target_tree, neighbour_separation, mutual);
}
}
}
/**
* @brief Construct the P2P and the M2L interaction lists for the target tree
*
* @tparam SourceTreeType
* @tparam TargetTreeType
* @tparam FmmOperatorType
* @param[in] source_tree the tree containing the sources
* @param[inout] target_tree the tree containing the targets.
* @param[in] fmm_operator The FMM operator used to get separtion criterion and mutual compultation
* @param[in] verbose boolean to specify if the direct pass use a symmetric algorithm (mutual interactions)
*/
template<typename SourceTreeType, typename TargetTreeType,
typename FmmOperatorType> //NearFieldType, typename NearFieldType>
[[deprecated("Use build_interaction_lists(tre, tre, ffm_operator, verbose) instead.")]] inline auto
build_interaction_lists(SourceTreeType& source_tree, TargetTreeType& target_tree,
FmmOperatorType const& fmm_operator, bool verbose = false) -> void
{
int leaf_neighbour_separation{fmm_operator.near_field().separation_criterion()};
int neighbour_separation{fmm_operator.near_field().separation_criterion()};
// if constexpr(scalfmm::meta::is_smooth_v<typename FmmOperatorType::near_field_type::matrix_kernel_type>)
// {
// leaf_neighbour_separation = fmm_operator.near_field().matrix_kernel().leaf_separation_criterion;
// }
bool const& mutual = fmm_operator.near_field().mutual();
if(verbose)
{
std::cout << "list::neighbour_separation " << neighbour_separation
<< std::endl
// << "list::leaf_neighbour_separation " << leaf_neighbour_separation << std::endl
<< "list::mutual " << std::boolalpha << mutual << std::endl
<< std::flush;
}
// std::cout << " build_p2p_interaction_list start \n" << std::flush;
try
{
build_p2p_interaction_list(source_tree, target_tree, leaf_neighbour_separation, mutual);
// std::cout << " build_m2l_interaction_list start \n" << std::flush;
build_m2l_interaction_list(source_tree, target_tree, neighbour_separation, leaf_neighbour_separation);
// std::cout << " build_interaction_lists end \n" << std::flush;
}
catch(const std::out_of_range& e)
{
std::cerr << e.what() << std::endl;
}
}
} // namespace scalfmm::list::omp
#endif // SCALFMM_LISTS_OMP_HPP