18 #if !defined(__FLECSI_PRIVATE__) 19 #error Do not include this file directly! 22 #include "flecsi/topo/core.hh" 24 #include "flecsi/topo/ntree/geometry.hh" 31 #include <type_traits> 32 #include <unordered_map> 49 template<
typename POLICY_TYPE>
57 template<
class Policy>
58 template<std::
size_t Priv>
60 static constexpr
bool Write = privilege_write(Priv);
70 static constexpr
size_t dimension = Policy::dimension;
71 using element_t =
typename Policy::element_t;
73 using range_t = std::array<point_t, 2>;
75 using key_t =
typename Policy::key_t;
77 using node_t =
typename Policy::node_t;
78 using tree_entity_t =
typename Policy::tree_entity_t;
79 using entity_t =
typename Policy::entity_t;
93 node_map_.emplace(key_t::root(), key_t::root());
94 root_ = node_map_.find(key_t::root());
95 assert(root_ != node_map_.end());
111 template<
class... S,
class = std::enable_if_t<Write>>
113 return nts_.template make_entity(std::forward<S>(args)...);
120 for(
auto & ent : *(nts_.entity_index_space.
storage())) {
121 ent.set_key(key_t(range_, ent.coordinates()));
144 template<
class... S,
class = std::enable_if_t<Write>>
146 return nts_.template make_tree_entity(std::forward<S>(args)...);
154 for(
auto & ent : *(nts_.entity_index_space.
storage())) {
165 key_t node_key = ent.key();
166 node_t * parent = find_parent(node_key);
167 assert(parent !=
nullptr);
170 if(!parent->is_leaf()) {
172 int depth = parent->key().depth() + 1;
173 node_key.truncate(depth);
174 int bit = node_key.last_value();
175 parent->add_bit_child(bit);
178 node_map_.emplace_back(node_key, node_key);
179 auto * new_parent = &(node_map_.find(node_key)->second);
180 new_parent->set_leaf(
true);
181 new_parent->insert(ent.global_id());
185 if(parent->size() == (1 << dimension)) {
190 parent->insert(ent.global_id());
193 parent = find_parent(node_key);
199 entity_t &
get(
const entity_id_t & id) {
200 return *(nts_.entity_index_space.
storage()->begin() +
id.entity());
207 key.truncate(max_depth_);
208 while(key != root()->key()) {
209 auto br = &(node_map_.find(key)->second);
221 void cofm(node_t * b =
nullptr,
bool local =
false) {
225 std::vector<node_t *> working_branches;
226 std::stack<node_t *> stk_remaining;
228 std::stack<node_t *> stk;
230 while(!stk.empty()) {
231 node_t * c = stk.top();
232 int cur_level = c->key().depth();
235 working_branches.push_back(c);
238 if(cur_level == level) {
239 working_branches.push_back(c);
242 stk_remaining.push(c);
243 for(
int i = (1 << dimension) - 1; i >= 0; --i) {
246 auto next = child_(c, i);
247 assert(next !=
nullptr);
255 const int nwork = working_branches.size();
258 #pragma omp parallel for 260 for(
int b = 0; b < nwork; ++b) {
262 std::stack<node_t *> stk1;
263 std::stack<node_t *> stk2;
264 stk1.push(working_branches[b]);
265 while(!stk1.empty()) {
266 node_t * cur = stk1.top();
270 if(!cur->is_leaf()) {
271 for(
int i = 0; i < (1 << dimension); ++i) {
272 if(!cur->as_child(i))
274 node_t * next = child_(cur, i);
280 while(!stk2.empty()) {
281 node_t * cur = stk2.top();
283 update_COM(cur, local);
287 while(!stk_remaining.empty()) {
288 node_t * cur = stk_remaining.top();
290 update_COM(cur, local);
302 uint64_t nchildren = 0;
303 int owner = b->owner();
304 for(
size_t d = 0; d < dimension; ++d) {
310 for(
auto child : *b) {
311 auto ent =
get(child);
314 element_t childmass = ent.mass();
315 for(
size_t d = 0; d < dimension; ++d) {
316 bmax[d] = std::max(bmax[d], ent.coordinates()[d] + ent.radius() / 2.);
317 bmin[d] = std::min(bmin[d], ent.coordinates()[d] - ent.radius() / 2.);
319 coordinates += childmass * ent.coordinates();
322 if(mass > element_t(0))
326 for(
int i = 0; i < (1 << dimension); ++i) {
327 auto node = child_(b, i);
330 nchildren += node->sub_entities();
331 mass += node->mass();
332 if(node->mass() > 0) {
333 for(
size_t d = 0; d < dimension; ++d) {
334 bmax[d] = std::max(bmax[d], node->bmax()[d]);
335 bmin[d] = std::min(bmin[d], node->bmin()[d]);
338 coordinates += node->mass() * node->coordinates();
340 if(mass > element_t(0))
343 b->set_sub_entities(nchildren);
344 b->set_coordinates(coordinates);
348 assert(nchildren != 0);
357 flog(trace) <<
" outputing tree file #" << num << std::endl;
360 sprintf(fname,
"output_graphviz_%02d.gv", num);
361 std::ofstream output;
363 output <<
"digraph G {" << std::endl <<
"forcelabels=true;" << std::endl;
366 output <<
"node [label=\"node\" xlabel=\"sub_entities,owner,requested," 370 std::stack<node_t *> stk;
375 while(!stk.empty()) {
376 node_t * cur = stk.top();
378 if(!cur->is_leaf()) {
379 output << cur->key() <<
" [label=\"" << cur->key() <<
"\", xlabel=\"" 380 << cur->sub_entities() <<
" - " << cur->owner() <<
" - " 381 << cur->requested() <<
" - " << cur->ghosts_local() <<
"\"];" 383 switch(cur->locality()) {
385 output << cur->key() <<
" [shape=circle,color=blue]" << std::endl;
388 output << cur->key() <<
" [shape=circle,color=red]" << std::endl;
391 output << cur->key() <<
" [shape=circle,color=green]" << std::endl;
394 output << cur->key() <<
" [shape=circle,color=black]" << std::endl;
399 for(
size_t i = 0; i < (1 << dimension); ++i) {
400 auto br = child_(cur, i);
404 output << std::oct << cur->key() <<
"->" << br->key() << std::dec
409 output << cur->key() <<
" [label=\"" << cur->key() <<
"\", xlabel=\"" 410 << cur->sub_entities() <<
" - " << cur->owner() <<
" - " 411 << cur->requested() <<
" - " << cur->ghosts_local() <<
"\"];" 413 switch(cur->locality()) {
415 output << cur->key() <<
" [shape=circle,color=blue]" << std::endl;
418 output << cur->key() <<
" [shape=circle,color=red]" << std::endl;
421 output << cur->key() <<
" [shape=circle,color=green]" << std::endl;
424 output << cur->key() <<
" [shape=circle,color=black]" << std::endl;
427 for(
auto ent : *cur) {
430 key.truncate(max_depth_ + 2);
431 output << key <<
" [label=\"" << key <<
"\", xlabel=\"" << e.owner()
432 <<
" - " << e.global_id().entity() <<
"\"];" << std::endl;
434 output << cur->key() <<
"->" << key << std::endl;
435 switch(e.locality()) {
437 output << key <<
" [shape=box,color=black]" << std::endl;
440 output << key <<
" [shape=box,color=red]" << std::endl;
443 output << key <<
" [shape=box,color=green]" << std::endl;
446 output << key <<
" [shape=circle,color=black]" << std::endl;
453 output <<
"}" << std::endl;
461 node_t * child_(node_t * b,
const int & i) {
462 key_t key = b->key();
464 return &(node_map_.find(key)->second);
470 void refine_(node_t * b) {
471 key_t pid = b->key();
472 size_t depth = pid.depth() + 1;
476 key_t k =
get(ent).key();
478 bit_child |= 1 << k.last_value();
479 node_map_.emplace_back(k, k);
481 max_depth_ = std::max(max_depth_, depth);
487 b->set_bit_child(bit_child);
495 struct node_key_hasher__ {
496 size_t operator()(
const K & k)
const noexcept {
497 return k.value() & ((1 << 22) - 1);
500 std::unordered_map<key_t, node_t, node_key_hasher__<key_t>> node_map_;
501 typename std::unordered_map<key_t, node_t, node_key_hasher__<key_t>>::iterator
505 os <<
"Tree: range: " << t.range_[0] <<
"-" << t.range_[1];
node_t * root()
Definition: interface.hh:135
entity_t * make_tree_entity(S &&... args)
Construct a new tree entity. The tree entity's constructor should not be called directly.
Definition: interface.hh:145
void sort_entities()
Sort the entities present in the tree.
Definition: interface.hh:128
void insert(entity_t &ent)
Insert a particle in the tree. Search for the nearest parent and refine if necessary.
Definition: interface.hh:163
void generate_keys()
Make the keys for all the enities present in the tree.
Definition: interface.hh:119
#define flog(severity)
Definition: flog.hh:136
offset represents an offset range (a start index plus a count of elements) in a single uint64_t...
Definition: offset.hh:34
entity_t * make_entity(S &&... args)
Construct a new entity. The entity's constructor should not be called directly.
Definition: interface.hh:112
Definition: coloring.hh:33
Definition: coloring.hh:31
std::ostream & operator<<(std::ostream &ostr, const filling_curve< D, T, DER > &k)
output for filling_curve using output_ function defined in the class
Definition: filling_curve.hh:206
Definition: interface.hh:52
node_t * find_parent(key_t key)
Find the closest parent of a key.
Definition: interface.hh:206
void set_range(const range_t &range)
Set the range of the current domain. This range is the same among all the processes and is used to co...
Definition: interface.hh:103
storage_t * storage()
Return the storage object.
Definition: index_space.hh:627
Definition: dimensioned_array.hh:58
Definition: interface.hh:50
access()
Definition: interface.hh:89
void graphviz(int num)
Output the tree topology in a file The format is graphviz and can be converted to PDF with dot dot -T...
Definition: interface.hh:356
void build_tree()
Build the tree topology in the node_map_, insert all the local particles of the tree in a serial way...
Definition: interface.hh:153
Definition: geometry.hh:45
void cofm(node_t *b=nullptr, bool local=false)
Compute the cofm data for the tree using double stack.
Definition: interface.hh:221
Definition: control.hh:31
void update_COM(node_t *b, bool=false)
Compute the COFM information for a dedicated branch.
Definition: interface.hh:297