Program Listing for File test.h¶
↰ Return to documentation for file (include/test.h
)
#ifndef test_h
#define test_h
#include <cassert>
#include "exafmm_t.h"
#include "fmm_base.h"
namespace exafmm_t {
template <typename T>
class DummyFmm : public FmmBase<T> {
public:
DummyFmm() {}
DummyFmm(int ncrit_) { this->p = 1; this->nsurf = 1; this->ncrit = ncrit_;}
ivec3 octant2coord(int octant) {
ivec3 rel_coord;
rel_coord[0] = octant & 1 ? 1 : -1;
rel_coord[1] = octant & 2 ? 1 : -1;
rel_coord[2] = octant & 4 ? 1 : -1;
return rel_coord;
}
void P2M(NodePtrs<T>& leafs) {
#pragma omp parallel for
for(size_t i=0; i<leafs.size(); ++i) {
Node<T>* leaf = leafs[i];
leaf->up_equiv[0] += leaf->nsrcs;
}
}
void M2M(Node<T>* node) {
if(node->is_leaf) return;
for(int octant=0; octant<8; ++octant) {
if(node->children[octant])
#pragma omp task untied
M2M(node->children[octant]);
}
#pragma omp taskwait
for(int octant=0; octant<8; octant++) {
if(node->children[octant]) {
Node<T>* child = node->children[octant];
node->up_equiv[0] += child->up_equiv[0];
}
}
}
void M2L(NodePtrs<T>& nonleafs) {
#pragma omp parallel for schedule(dynamic)
for(size_t i=0; i<nonleafs.size(); ++i) {
Node<T>* trg_parent = nonleafs[i];
NodePtrs<T>& M2L_list = trg_parent->M2L_list;
for(size_t j=0; j<M2L_list.size(); ++j) {
Node<T>* src_parent = M2L_list[j];
if(src_parent) {
// find src_parent's relative position to trg_parent
// NodePtrs<T>::iterator
auto it = std::find(trg_parent->colleagues.begin(),
trg_parent->colleagues.end(), src_parent);
assert(it != trg_parent->colleagues.end()); // src_parent has to be trg_parent's colleague
int colleague_idx = it - trg_parent->colleagues.begin();
ivec3 parent_rel_coord;
parent_rel_coord[0] = colleague_idx % 3 - 1;
parent_rel_coord[1] = (colleague_idx/3) % 3 - 1;
parent_rel_coord[2] = (colleague_idx/9) % 3 - 1;
for(int src_octant=0; src_octant<8; ++src_octant) {
Node<T>* src_child = src_parent->children[src_octant];
ivec3 src_child_coord = octant2coord(src_octant);
for(int trg_octant=0; trg_octant<8; ++trg_octant) {
Node<T>* trg_child = trg_parent->children[trg_octant];
ivec3 trg_child_coord = octant2coord(trg_octant);
if(src_child && trg_child) {
ivec3 rel_coord = parent_rel_coord*2 + (src_child_coord - trg_child_coord) / 2; // calculate relative coords between children
bool is_colleague = true;
for(int d=0; d<3; ++d) {
if(rel_coord[d]>1 || rel_coord[d]<-1)
is_colleague = false;
}
if(!is_colleague) // perform M2L if they are not neighbors
trg_child->dn_equiv[0] += src_child->up_equiv[0];
}
}
}
}
}
}
}
void P2L(Nodes<T>& nodes) {
#pragma omp parallel for schedule(dynamic)
for(size_t i=0; i<nodes.size(); ++i) {
NodePtrs<T>& P2L_list = nodes[i].P2L_list;
for(size_t j=0; j<P2L_list.size(); ++j) {
nodes[i].dn_equiv[0] += P2L_list[j]->nsrcs;
}
}
}
void M2P(NodePtrs<T>& leafs) {
#pragma omp parallel for schedule(dynamic)
for(size_t i=0; i<leafs.size(); ++i) {
if (leafs[i]->ntrgs == 0) continue;
NodePtrs<T>& M2P_list = leafs[i]->M2P_list;
for (size_t j=0; j<M2P_list.size(); ++j) {
leafs[i]->trg_value[0] += M2P_list[j]->up_equiv[0];
}
}
}
void L2L(Node<T>* node) {
if(node->is_leaf) return;
for(int octant=0; octant<8; octant++) {
if(node->children[octant]) {
Node<T>* child = node->children[octant];
child->dn_equiv[0] += node->dn_equiv[0];
}
}
for(int octant=0; octant<8; ++octant) {
if(node->children[octant])
#pragma omp task untied
L2L(node->children[octant]);
}
#pragma omp taskwait
}
void L2P(NodePtrs<T>& leafs) {
#pragma omp parallel for
for(size_t i=0; i<leafs.size(); ++i) {
Node<T>* leaf = leafs[i];
if (leaf->ntrgs==0) continue;
leaf->trg_value[0] += leaf->dn_equiv[0];
}
}
void P2P(NodePtrs<T>& leafs) {
#pragma omp parallel for schedule(dynamic)
for(size_t i=0; i<leafs.size(); ++i) {
Node<T>* leaf = leafs[i];
if (leaf->ntrgs==0) continue;
NodePtrs<T>& P2P_list = leaf->P2P_list;
for(size_t j=0; j<P2P_list.size(); ++j) {
leaf->trg_value[0] += P2P_list[j]->nsrcs;
}
}
}
// below are the virtual methods define in FmmBase class
void potential_P2P(RealVec& src_coord, std::vector<T>& src_value,
RealVec& trg_coord, std::vector<T>& trg_value) {}
void gradient_P2P(RealVec& src_coord, std::vector<T>& src_value,
RealVec& trg_coord, std::vector<T>& trg_value) {}
void M2L(Nodes<T>& nodes) {}
};
template <typename T>
void set_children(Node<T>* parent, Node<T>* first_child) {
parent->is_leaf = false;
for (int octant=0; octant<8; ++octant) {
Node<T>* child = first_child + octant;
child->octant = octant;
child->parent = parent;
child->level = parent->level + 1;
child->x = parent->x;
child->r = parent->r / 2;
for (int d=0; d<3; d++) {
child->x[d] += child->r * (((octant & 1 << d) >> d) * 2 - 1);
}
parent->children.push_back(child);
}
}
}// end namespace
#endif