Commit 364eb9a8 authored by Quentin Khan's avatar Quentin Khan

FAdaptiveSequential: Make direct computation work with existing kernels

For a given leaf A, the existing symmetric kernels expect to receive the list of
adjacent B leaves sorted by offset index.

The offset index is computed by `compute_box_offset_index`. For direct
computation, it ranges from 0 to 3^dim.

A node's U list is not sorted. It is first looped over to compute the indices
and stored in a sorted std::multimap. The map is then looped over to create the
adequate arrays (managed through std::vector objects) to give to the kernel P2P
call.
parent 140c9555
......@@ -4,6 +4,8 @@
#include <algorithm>
#include <cmath> // Used to round box differences
#include <functional>
#include <map>
#include "Core/FCoreCommon.hpp"
#include "Containers/FTreeCoordinate.hpp"
......@@ -214,44 +216,78 @@ public:
}
// P2P
/** \brief Direct computation step (P2P)
*
* For each tree leaf, a direct computation is done with the adjacent
* leaves.
*
* The symmetric computation kernels expect to receive the list of adjacent
* leaves, stored in a leaf's U list, sorted by offset index.
*
* The offset index is of a node compared to another follows the
* numerotation of the adjacent nodes, on each axis. In 3D, this woud give,
* with L the reference leaf:
*
* x x x
* 0 1 2 | 9 10 11 | 18 19 20
* y 3 4 5 | 12 L 14 | 21 22 23
* 6 7 8 | 15 16 17 | 24 25 26
* z=0 z=1 z=2
*
* When two node that are to be compared are not on the same level, the
* lowest one's ancestor that is at the highest one's level is used to
* compute the index.
*
* To statisfy this condition, the leaves have to be sorted before being
* given to the kernel P2P method.
*
*/
void u_list_step() {
using container_t = typename node_t::particle_container_t;
// The following containers are reused for each leaf to avoid repeated
// dynamic allocation.
// Used to sort the U items by index
std::multimap<int, node_t*> sorted_u_items;
// Vectors to be filled after sort and passed to kernel P2P
std::vector<container_t*> u_item_source_particle_containers;
std::vector<int> u_item_indices;
std::vector<node_t*> leaves(_tree.leaves().begin(), _tree.leaves().end());
std::sort(leaves.begin(), leaves.end(),
[](node_t* a, node_t* b) -> bool {return a->getIndex() < b->getIndex();});
for(node_t* leaf : _tree.leaves()) {
for(node_t* leaf : leaves) {
u_item_source_particle_containers.clear();
u_item_indices.clear();
sorted_u_items.clear();
container_t* const leaf_source_particle_container =
leaf->getParticleContainer();
const container_t* const leaf_target_particle_container =
leaf->getParticleContainer();
if( leaf_source_particle_container->size() == 0
&& leaf_target_particle_container->size() == 0) {
//continue;
}
// Insert U items in sorteed multimap
for(node_t* u_item : leaf->U) {
// The kernels do not consider leaf to be adjacent to itself
if(u_item == leaf) {
continue;
}
u_item_indices.push_back(compute_box_offset_index(leaf, u_item, 1));
//u_item_source_particle_containers.push_back(u_item->getParticleContainer());
sorted_u_items.insert({compute_box_offset_index(leaf, u_item, 1), u_item});
}
std::sort(u_item_indices.begin(), u_item_indices.end());
for(int idx : u_item_indices) {
for(node_t* u_item : leaf->U) {
if(idx == compute_box_offset_index(leaf, u_item, 1)) {
u_item_source_particle_containers.push_back(u_item->getParticleContainer());
}
}
// Get sorted items and transfer them to vectors
for(auto& keyval : sorted_u_items) {
int key; node_t* u_item;
std::tie(key, u_item) = keyval;
u_item_source_particle_containers.push_back(u_item->getParticleContainer());
u_item_indices.push_back(key);
}
// Call P2P on vectors data
_kernel.P2P(
FTreeCoordinate(MortonIndex(leaf->getIndex())),
leaf_source_particle_container,
......@@ -281,6 +317,9 @@ public:
* \param other_node The interacting node
* \param n The longest possible distance between node and other_node in
* terms of boxes on an axis
*
* \warning If the nodes are not at the same level, the lowest one's
* ancestor at the highest one's level is used.
*/
int compute_box_offset_index(node_t* node, node_t* other_node, const std::size_t n) {
while(node->getDepth() > other_node->getDepth()) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment