Skip to content

Commit 48abe09

Browse files
committed
Add work in progress to adding CPU BH/FMM code to Fidimag atomistic simulator
1 parent 8dcc0cd commit 48abe09

File tree

9 files changed

+3622
-6
lines changed

9 files changed

+3622
-6
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
//############################################
2+
//#
3+
//# Functions for running the Barnes-Hut
4+
//# method for gravitational source particles.
5+
//#
6+
//# (C) Ryan Pepper, 2018
7+
//# University of Southampton, UK
8+
//#
9+
//#
10+
//###########################################
11+
12+
#include<iostream>
13+
#include<omp.h>
14+
#include "calculate.hpp"
15+
16+
17+
void evaluate_P2M(std::vector<Particle> &particles, std::vector<Cell> &cells, unsigned int cell, unsigned int ncrit, unsigned int exporder) {
18+
/*
19+
evaluate_P2M(particles, cells, cell, ncrit)
20+
21+
This function evaluates the particle to multipole
22+
kernel part of the multipolar Barnes-Hut method,
23+
by iterating down the tree recursively, with the P2M
24+
method called if the curent cell is a leaf cell
25+
(i.e. it has no child cells) and the evaluate
26+
function agian otherwise
27+
*/
28+
if (cells[cell].nleaf > ncrit) {
29+
for (unsigned int octant = 0; octant < 8; octant++) {
30+
if (cells[cell].nchild & (1 << octant)) {
31+
evaluate_P2M(particles, cells, cells[cell].child[octant], ncrit, exporder);
32+
}
33+
}
34+
}
35+
else {
36+
P2M(particles, cell, cells, ncrit, exporder);
37+
}
38+
}
39+
40+
41+
void evaluate_M2M(std::vector<Particle> &particles, std::vector<Cell> &cells, unsigned int exporder) {
42+
/*
43+
evaluate_M2M(particles, cells)
44+
45+
This function evaluates the multipole to
46+
multipole kernel. It does this by working up the
47+
tree from the leaf nodes, which is possible
48+
by iterating backwards through the nodes because
49+
of the way the tree is constructed.
50+
*/
51+
for(int i = cells.size() - 1; i > 0; i--) {
52+
M2M(cells[i].parent, i, cells, exporder);
53+
}
54+
}
55+
56+
void evaluate_M2P_and_P2P(std::vector<Particle> &particles, unsigned int p, unsigned int i, std::vector<Cell> &cells, std::vector<double> &Bx, std::vector<double> &By, std::vector<double> &Bz, unsigned int n_crit, double theta, unsigned int exporder, std::vector<std::vector<double>> &mempool) {
57+
double dx, dy, dz, r;
58+
int c, j;
59+
if (cells[p].nleaf >= n_crit) {
60+
for (unsigned int octant = 0; octant < 8; octant++) {
61+
if (cells[p].nchild & (1 << octant)) {
62+
c = cells[p].child[octant];
63+
dx = particles[i].x - cells[c].x;
64+
dy = particles[i].y - cells[c].y;
65+
dz = particles[i].z - cells[c].z;
66+
r = sqrt(dx*dx + dy*dy + dz*dz);
67+
if (cells[c].r > theta * r) {
68+
evaluate_M2P_and_P2P(particles, c, i, cells, Bx, By, Bz, n_crit, theta, exporder, mempool);
69+
}
70+
else {
71+
int thread = omp_get_thread_num();
72+
M2P(c, i, cells, particles, Bx, By, Bz, exporder, mempool[thread]);
73+
}
74+
}
75+
}
76+
}
77+
else {
78+
// loop in leaf cell's particles
79+
for(unsigned int l = 0; l < (cells[p].nleaf); l++) {
80+
j = cells[p].leaf[l];
81+
P2P(i, j, particles, Bx, By, Bz);
82+
}
83+
}
84+
}
85+
86+
void evaluate_approx(std::vector<Particle> &particles, std::vector<Cell> &cells, std::vector<double> &Bx, std::vector<double> &By, std::vector<double> &Bz, unsigned int n_crit, double theta, unsigned int exp_order) {
87+
int nthreads;
88+
#pragma omp parallel
89+
{
90+
#pragma omp single
91+
nthreads = omp_get_num_threads();
92+
}
93+
std::vector<std::vector<double>> mempool;
94+
for(int i = 0; i < nthreads; i++) {
95+
mempool.push_back(std::vector<double>(Nterms(exp_order + 2)));
96+
}
97+
#pragma omp parallel for schedule(guided)
98+
for(unsigned int i = 0; i < particles.size(); i++) {
99+
evaluate_M2P_and_P2P(particles, 0, i, cells, Bx, By, Bz, n_crit, theta, exp_order, mempool);
100+
}
101+
}
102+
103+
void evaluate_direct(std::vector<Particle> &particles, std::vector<double> &Bx, std::vector<double> &By, std::vector<double> &Bz) {
104+
#pragma omp parallel for schedule(dynamic)
105+
for (unsigned int i = 0; i < particles.size(); i++) {
106+
for (unsigned int j = 0; j < particles.size(); j++) {
107+
P2P(i, j, particles, Bx, By, Bz);
108+
}
109+
}
110+
}
111+
112+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//############################################
2+
//#
3+
//# Functions for running the Barnes-Hut
4+
//# method for gravitational source particles.
5+
//#
6+
//# (C) Ryan Pepper, 2018
7+
//# University of Southampton, UK
8+
//#
9+
//#
10+
//###########################################
11+
12+
#include<iostream>
13+
#include "expansions.hpp"
14+
#include "tree.hpp"
15+
#include "utils.hpp"
16+
#include<omp.h>
17+
18+
#ifndef FMMLIB_CALCULATE_HPP
19+
#define FMMLIB_CALCULATE_HPP
20+
21+
22+
void evaluate_P2M(std::vector<Particle> &particles, std::vector<Cell> &cells, unsigned int cell, unsigned int ncrit, unsigned int exporder);
23+
24+
void evaluate_M2M(std::vector<Particle> &particles, std::vector<Cell> &cells, unsigned int exporder);
25+
26+
void evaluate_M2P_and_P2P(std::vector<Particle> &particles, unsigned int p,
27+
unsigned int i, std::vector<Cell> &cells, std::vector<double> &Bx,
28+
std::vector<double> &By, std::vector<double> &Bz, unsigned int n_crit,
29+
double theta, unsigned int exporder, std::vector<std::vector<double>> &mempool);
30+
31+
void evaluate_approx(std::vector<Particle> &particles, std::vector<Cell> &cells, std::vector<double> &Bx,
32+
std::vector<double> &By, std::vector<double> &Bz, unsigned int n_crit, double theta,
33+
unsigned int exp_order);
34+
35+
void evaluate_direct(std::vector<Particle> &particles, std::vector<double> &Bx, std::vector<double> &By,
36+
std::vector<double> &Bz);
37+
38+
39+
40+
#endif

0 commit comments

Comments
 (0)