Program Listing for File geometry.h¶
↰ Return to documentation for file (include/geometry.h
)
#ifndef geometry_h
#define geometry_h
#include "exafmm_t.h"
namespace exafmm_t {
// Global variables REL_COORD, HASH_LUT, M2L_INDEX_MAP are now defined in exafmm_t.h.
RealVec surface(int p, real_t r0, int level, real_t * c, real_t alpha) {
int n = 6*(p-1)*(p-1) + 2;
RealVec coord(n*3);
coord[0] = -1.0;
coord[1] = -1.0;
coord[2] = -1.0;
int count = 1;
for (int i=0; i<p-1; i++) {
for (int j=0; j<p-1; j++) {
coord[count*3 ] = -1.0;
coord[count*3+1] = (2.0*(i+1)-p+1) / (p-1);
coord[count*3+2] = (2.0*j-p+1) / (p-1);
count++;
}
}
for (int i=0; i<p-1; i++) {
for (int j=0; j<p-1; j++) {
coord[count*3 ] = (2.0*i-p+1) / (p-1);
coord[count*3+1] = -1.0;
coord[count*3+2] = (2.0*(j+1)-p+1) / (p-1);
count++;
}
}
for (int i=0; i<p-1; i++) {
for (int j=0; j<p-1; j++) {
coord[count*3 ] = (2.0*(i+1)-p+1) / (p-1);
coord[count*3+1] = (2.0*j-p+1) / (p-1);
coord[count*3+2] = -1.0;
count++;
}
}
for (int i=0; i<(n/2)*3; i++) {
coord[count*3+i] = -coord[i];
}
real_t r = r0 * powf(0.5, level);
real_t b = alpha * r;
for (int i=0; i<n; i++){
coord[i*3+0] = coord[i*3+0]*b + c[0];
coord[i*3+1] = coord[i*3+1]*b + c[1];
coord[i*3+2] = coord[i*3+2]*b + c[2];
}
return coord;
}
RealVec convolution_grid(int p, real_t r0, int level, real_t * c) {
real_t d = 2 * r0 * powf(0.5, level);
real_t a = d * 1.05; // side length of upward equivalent/downward check box
int n1 = p * 2;
int n2 = n1 * n1;
int n3 = n1 * n1 * n1;
RealVec grid(n3*3);
for (int i=0; i<n1; i++) {
for (int j=0; j<n1; j++) {
for (int k=0; k<n1; k++) {
grid[(i+n1*j+n2*k)*3+0] = (i-p)*a/(p-1) + c[0];
grid[(i+n1*j+n2*k)*3+1] = (j-p)*a/(p-1) + c[1];
grid[(i+n1*j+n2*k)*3+2] = (k-p)*a/(p-1) + c[2];
}
}
}
return grid;
}
std::vector<int> generate_surf2conv_up(int p) {
int n1 = 2*p;
real_t c[3];
for (int d=0; d<3; d++) c[d] = 0.5*(p-1);
RealVec surf = surface(p, 0.5, 0, c, real_t(p-1));
std::vector<int> map(6*(p-1)*(p-1)+2);
for (size_t i=0; i<map.size(); i++) {
map[i] = (int)(p-1-surf[i*3])
+ ((int)(p-1-surf[i*3+1])) * n1
+ ((int)(p-1-surf[i*3+2])) * n1 * n1;
}
return map;
}
std::vector<int> generate_surf2conv_dn(int p) {
int n1 = 2*p;
real_t c[3];
for (int d=0; d<3; d++) c[d] = 0.5*(p-1);
RealVec surf = surface(p, 0.5, 0, c, real_t(p-1));
std::vector<int> map(6*(p-1)*(p-1)+2);
for (size_t i=0; i<map.size(); i++) {
map[i] = (int)(2*p-1-surf[i*3])
+ ((int)(2*p-1-surf[i*3+1])) * n1
+ ((int)(2*p-1-surf[i*3+2])) * n1 * n1;
}
return map;
}
int hash(ivec3& coord) {
const int n = 5;
return ((coord[2]+n) * (2*n) + (coord[1]+n)) *(2*n) + (coord[0]+n);
}
void init_rel_coord(int max_r, int min_r, int step, Mat_Type t) {
const int max_hash = 2000;
HASH_LUT[t].resize(max_hash, -1);
for (int k=-max_r; k<=max_r; k+=step) {
for (int j=-max_r; j<=max_r; j+=step) {
for (int i=-max_r; i<=max_r; i+=step) {
if (abs(i)>=min_r || abs(j)>=min_r || abs(k)>=min_r) {
ivec3 coord;
coord[0] = i;
coord[1] = j;
coord[2] = k;
REL_COORD[t].push_back(coord);
HASH_LUT[t][hash(coord)] = REL_COORD[t].size() - 1;
}
}
}
}
}
void generate_M2L_index_map() {
int npos = REL_COORD[M2L_Type].size(); // number of relative coords for M2L_Type
M2L_INDEX_MAP.resize(npos, std::vector<int>(NCHILD*NCHILD));
#pragma omp parallel for
for (int i=0; i<npos; ++i) {
for (int j1=0; j1<NCHILD; ++j1) {
for (int j2=0; j2<NCHILD; ++j2) {
ivec3& parent_rel_coord = REL_COORD[M2L_Type][i];
ivec3 child_rel_coord;
child_rel_coord[0] = parent_rel_coord[0]*2 - (j1/1)%2 + (j2/1)%2;
child_rel_coord[1] = parent_rel_coord[1]*2 - (j1/2)%2 + (j2/2)%2;
child_rel_coord[2] = parent_rel_coord[2]*2 - (j1/4)%2 + (j2/4)%2;
int coord_hash = hash(child_rel_coord);
int child_rel_idx = HASH_LUT[M2L_Helper_Type][coord_hash];
int j = j2*NCHILD + j1;
M2L_INDEX_MAP[i][j] = child_rel_idx;
}
}
}
}
void init_rel_coord() {
static bool is_initialized = false;
if (!is_initialized) {
REL_COORD.resize(Type_Count);
HASH_LUT.resize(Type_Count);
init_rel_coord(1, 1, 2, M2M_Type);
init_rel_coord(1, 1, 2, L2L_Type);
init_rel_coord(3, 3, 2, P2P0_Type);
init_rel_coord(1, 0, 1, P2P1_Type);
init_rel_coord(3, 3, 2, P2P2_Type);
init_rel_coord(3, 2, 1, M2L_Helper_Type);
init_rel_coord(1, 1, 1, M2L_Type);
init_rel_coord(5, 5, 2, M2P_Type);
init_rel_coord(5, 5, 2, P2L_Type);
generate_M2L_index_map();
is_initialized = true;
}
}
} // end namespace
#endif