ASCOT5
Loading...
Searching...
No Matches
dist_rho5D.c
Go to the documentation of this file.
1
5#include <stdio.h>
6#include <stdlib.h>
7#include <math.h>
8#include "../ascot5.h"
9#include "../consts.h"
10#include "../physlib.h"
11#include "dist_rho5D.h"
12#include "../particle.h"
13
17size_t dist_rho5D_index(int i_rho, int i_theta, int i_phi, int i_ppara,
18 int i_pperp, int i_time, int i_q, size_t step_6,
19 size_t step_5, size_t step_4, size_t step_3,
20 size_t step_2, size_t step_1) {
21 return (size_t)(i_rho) * step_6
22 + (size_t)(i_theta) * step_5
23 + (size_t)(i_phi) * step_4
24 + (size_t)(i_ppara) * step_3
25 + (size_t)(i_pperp) * step_2
26 + (size_t)(i_time) * step_1
27 + (size_t)(i_q);
28}
29
36
37 size_t n_q = (size_t)(data->n_q);
38 size_t n_time = (size_t)(data->n_time);
39 size_t n_pperp = (size_t)(data->n_pperp);
40 size_t n_ppara = (size_t)(data->n_ppara);
41 size_t n_phi = (size_t)(data->n_phi);
42 size_t n_theta = (size_t)(data->n_theta);
43 data->step_6 = n_q * n_time * n_pperp * n_ppara * n_phi * n_theta;
44 data->step_5 = n_q * n_time * n_pperp * n_ppara * n_phi;
45 data->step_4 = n_q * n_time * n_pperp * n_ppara;
46 data->step_3 = n_q * n_time * n_pperp;
47 data->step_2 = n_q * n_time;
48 data->step_1 = n_q;
49
50 data->histogram = calloc(data->step_6 * (size_t)data->n_rho, sizeof(real));
51 return data->histogram == NULL;
52}
53
60 free(data->histogram);
61}
62
69 GPU_MAP_TO_DEVICE(
70 data->histogram[0:data->n_rho*data->n_theta*data->n_phi*data->n_ppara*data->n_pperp*data->n_time*data->n_q]
71 )
72}
73
80 GPU_UPDATE_FROM_DEVICE(
81 data->histogram[0:data->n_rho*data->n_theta*data->n_phi*data->n_ppara*data->n_pperp*data->n_time*data->n_q]
82 )
83}
84
97 particle_simd_fo* p_i) {
98
99#ifdef GPU
100 size_t index;
101 real weight;
102#else
103 size_t index[NSIMD];
104 real weight[NSIMD];
105#endif
106
107 GPU_PARALLEL_LOOP_ALL_LEVELS
108 for(int i = 0; i < p_f->n_mrk; i++) {
109 if(p_f->running[i]) {
110
111 int i_rho = floor((p_f->rho[i] - dist->min_rho)
112 / ((dist->max_rho - dist->min_rho)/dist->n_rho));
113
114 real phi = fmod(p_f->phi[i], 2*CONST_PI);
115 if(phi < 0) {
116 phi += 2*CONST_PI;
117 }
118 int i_phi = floor((phi - dist->min_phi)
119 / ((dist->max_phi - dist->min_phi)/dist->n_phi));
120
121 real theta = fmod(p_f->theta[i], 2*CONST_PI);
122 if(theta < 0) {
123 theta += 2*CONST_PI;
124 }
125 int i_theta = floor((theta - dist->min_theta)
126 / ( (dist->max_theta - dist->min_theta)
127 / dist->n_theta) );
128
129 real ppara = ( p_f->p_r[i] * p_f->B_r[i]
130 + p_f->p_phi[i] * p_f->B_phi[i]
131 + p_f->p_z[i] * p_f->B_z[i])
132 / sqrt( p_f->B_r[i] * p_f->B_r[i]
133 + p_f->B_phi[i]* p_f->B_phi[i]
134 + p_f->B_z[i] * p_f->B_z[i]);
135 int i_ppara = floor((ppara - dist->min_ppara)
136 / ((dist->max_ppara - dist->min_ppara)
137 / dist->n_ppara));
138
139 real pperp = sqrt(
140 p_f->p_r[i] * p_f->p_r[i]
141 + p_f->p_phi[i] * p_f->p_phi[i]
142 + p_f->p_z[i] * p_f->p_z[i]
143 - ppara * ppara);
144 int i_pperp = floor((pperp - dist->min_pperp)
145 / ((dist->max_pperp - dist->min_pperp)
146 / dist->n_pperp));
147
148 int i_time = floor((p_f->time[i] - dist->min_time)
149 / ((dist->max_time - dist->min_time) / dist->n_time));
150
151 int i_q = floor((p_f->charge[i]/CONST_E - dist->min_q)
152 / ((dist->max_q - dist->min_q) / dist->n_q));
153
154 if(i_rho >= 0 && i_rho <= dist->n_rho - 1 &&
155 i_phi >= 0 && i_phi <= dist->n_phi - 1 &&
156 i_theta >= 0 && i_theta <= dist->n_theta - 1 &&
157 i_ppara >= 0 && i_ppara <= dist->n_ppara - 1 &&
158 i_pperp >= 0 && i_pperp <= dist->n_pperp - 1 &&
159 i_time >= 0 && i_time <= dist->n_time - 1 &&
160 i_q >= 0 && i_q <= dist->n_q - 1 ) {
161#ifdef GPU
162 index = dist_rho5D_index(
163 i_rho, i_theta, i_phi, i_ppara, i_pperp,
164 i_time, i_q, dist->step_6, dist->step_5, dist->step_4,
165 dist->step_3, dist->step_2, dist->step_1);
166 weight = p_f->weight[i] * (p_f->time[i] - p_i->time[i]);
167 GPU_ATOMIC
168 dist->histogram[index] += weight;
169#else
170 index[i] = dist_rho5D_index(
171 i_rho, i_theta, i_phi, i_ppara, i_pperp,
172 i_time, i_q, dist->step_6, dist->step_5, dist->step_4,
173 dist->step_3, dist->step_2, dist->step_1);
174 weight[i] = p_f->weight[i] * (p_f->time[i] - p_i->time[i]);
175#endif
176 }
177 }
178 }
179#ifndef GPU
180 for(int i = 0; i < p_f->n_mrk; i++) {
181 if(p_f->running[i] && index[i] >= 0 &&
182 index[i] < dist->step_6 * dist->n_rho) {
183 GPU_ATOMIC
184 dist->histogram[index[i]] += weight[i];
185 }
186 }
187#endif
188}
189
202 particle_simd_gc* p_i) {
203 real phi[NSIMD];
204 real theta[NSIMD];
205 real pperp[NSIMD];
206
207 int i_rho[NSIMD];
208 int i_phi[NSIMD];
209 int i_theta[NSIMD];
210 int i_ppara[NSIMD];
211 int i_pperp[NSIMD];
212 int i_time[NSIMD];
213 int i_q[NSIMD];
214
215 int ok[NSIMD];
216 real weight[NSIMD];
217
218 #pragma omp simd
219 for(int i = 0; i < NSIMD; i++) {
220 if(p_f->running[i]) {
221
222 i_rho[i] = floor((p_f->rho[i] - dist->min_rho)
223 / ((dist->max_rho - dist->min_rho)/dist->n_rho));
224
225 phi[i] = fmod(p_f->phi[i], 2*CONST_PI);
226 if(phi[i] < 0) {
227 phi[i] = phi[i] + 2*CONST_PI;
228 }
229 i_phi[i] = floor((phi[i] - dist->min_phi)
230 / ((dist->max_phi - dist->min_phi)/dist->n_phi));
231
232 theta[i] = fmod(p_f->theta[i], 2*CONST_PI);
233 if(theta[i] < 0) {
234 theta[i] = theta[i] + 2*CONST_PI;
235 }
236 i_theta[i] = floor((theta[i] - dist->min_theta)
237 / ((dist->max_theta - dist->min_theta)
238 / dist->n_theta));
239
240 i_ppara[i] = floor((p_f->ppar[i] - dist->min_ppara)
241 / ((dist->max_ppara - dist->min_ppara) / dist->n_ppara));
242
243 pperp[i] = sqrt(2 * sqrt( p_f->B_r[i] * p_f->B_r[i]
244 + p_f->B_phi[i] * p_f->B_phi[i]
245 + p_f->B_z[i] * p_f->B_z[i] )
246 * p_f->mu[i] * p_f->mass[i]);
247 i_pperp[i] = floor((pperp[i] - dist->min_pperp)
248 / ((dist->max_pperp - dist->min_pperp)
249 / dist->n_pperp));
250
251 i_time[i] = floor((p_f->time[i] - dist->min_time)
252 / ((dist->max_time - dist->min_time) / dist->n_time));
253
254 i_q[i] = floor((p_f->charge[i]/CONST_E - dist->min_q)
255 / ((dist->max_q - dist->min_q) / dist->n_q));
256
257 if(i_rho[i] >= 0 && i_rho[i] <= dist->n_rho - 1 &&
258 i_phi[i] >= 0 && i_phi[i] <= dist->n_phi - 1 &&
259 i_theta[i] >= 0 && i_theta[i] <= dist->n_theta - 1 &&
260 i_ppara[i] >= 0 && i_ppara[i] <= dist->n_ppara - 1 &&
261 i_pperp[i] >= 0 && i_pperp[i] <= dist->n_pperp - 1 &&
262 i_time[i] >= 0 && i_time[i] <= dist->n_time - 1 &&
263 i_q[i] >= 0 && i_q[i] <= dist->n_q - 1 ) {
264 ok[i] = 1;
265 weight[i] = p_f->weight[i] * (p_f->time[i] - p_i->time[i]);
266 }
267 else {
268 ok[i] = 0;
269 }
270 }
271 }
272
273 for(int i = 0; i < NSIMD; i++) {
274 if(p_f->running[i] && ok[i]) {
275 size_t index = dist_rho5D_index(
276 i_rho[i], i_theta[i], i_phi[i], i_ppara[i], i_pperp[i],
277 i_time[i], i_q[i], dist->step_6, dist->step_5, dist->step_4,
278 dist->step_3, dist->step_2, dist->step_1);
279 #pragma omp atomic
280 dist->histogram[index] += weight[i];
281 }
282 }
283}
Main header file for ASCOT5.
double real
Definition ascot5.h:85
#define NSIMD
Number of particles simulated simultaneously in a particle group operations.
Definition ascot5.h:91
Header file containing physical and mathematical constants.
#define CONST_PI
pi
Definition consts.h:11
#define CONST_E
Elementary charge [C].
Definition consts.h:35
int dist_rho5D_init(dist_rho5D_data *data)
Initializes distribution data.
Definition dist_rho5D.c:35
void dist_rho5D_free(dist_rho5D_data *data)
Free the allocated resources.
Definition dist_rho5D.c:59
void dist_rho5D_offload(dist_rho5D_data *data)
Offload data to the accelerator.
Definition dist_rho5D.c:68
void dist_rho5D_onload(dist_rho5D_data *data)
Onload data back to the host.
Definition dist_rho5D.c:79
void dist_rho5D_update_gc(dist_rho5D_data *dist, particle_simd_gc *p_f, particle_simd_gc *p_i)
Update the histogram from guiding center markers.
Definition dist_rho5D.c:201
size_t dist_rho5D_index(int i_rho, int i_theta, int i_phi, int i_ppara, int i_pperp, int i_time, int i_q, size_t step_6, size_t step_5, size_t step_4, size_t step_3, size_t step_2, size_t step_1)
Internal function calculating the index in the histogram array.
Definition dist_rho5D.c:17
void dist_rho5D_update_fo(dist_rho5D_data *dist, particle_simd_fo *p_f, particle_simd_fo *p_i)
Update the histogram from full-orbit particles.
Definition dist_rho5D.c:96
Header file for dist_rho5D.c.
real fmod(real x, real y)
Compute the modulus of two real numbers.
Definition math.c:22
Header file for math.c.
Header file for particle.c.
Methods to evaluate elementary physical quantities.
Histogram parameters.
Definition dist_rho5D.h:15
Struct representing NSIMD particle markers.
Definition particle.h:210
integer * running
Definition particle.h:252
Struct representing NSIMD guiding center markers.
Definition particle.h:275