ASCOT5
Loading...
Searching...
No Matches
mpi_interface.c
Go to the documentation of this file.
1
7#ifdef MPI
8#include <mpi.h>
9#endif
10#include <stddef.h>
11#include <stdlib.h>
12#include "ascot5.h"
13#include "diag.h"
14#include "mpi_interface.h"
15#include "particle.h"
16#include "simulate.h"
17
30void mpi_interface_init(int argc, char** argv, int* mpi_rank, int* mpi_size,
31 int* mpi_root) {
32#ifdef MPI
33 /* MPI is used. Init MPI and set rank and size as determined by MPI.
34 * Rank of the root process is zero */
35 int provided;
36 int initialized;
37 MPI_Initialized(&initialized);
38 if(initialized == 0)
39 MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &provided);
40 MPI_Comm_rank(MPI_COMM_WORLD, mpi_rank);
41 MPI_Comm_size(MPI_COMM_WORLD, mpi_size);
42 *mpi_root = 0;
43#else
44 /* MPI is not used and no command line arguments are given. Assume that
45 * the entire simulation is a single process. */
46 *mpi_rank = 0;
47 *mpi_size = 1;
48 *mpi_root = 0;
49#endif
50}
51
59#ifdef MPI
60 MPI_Finalize();
61#endif
62}
63
70#ifdef MPI
71 MPI_Barrier(MPI_COMM_WORLD);
72#endif
73}
74
87void mpi_my_particles(int* start_index, int* n, int n_tot, int mpi_rank,
88 int mpi_size) {
89 if(mpi_rank == mpi_size-1) {
90 *n = n_tot - mpi_rank * (n_tot / mpi_size);
91 }
92 else {
93 *n = n_tot / mpi_size;
94 }
95
96 *start_index = mpi_rank * (n_tot / mpi_size);
97}
98
118 particle_state* ps, particle_state** ps_gather, int* n_gather, int n_tot,
119 int mpi_rank, int mpi_size, int mpi_root) {
120#ifdef MPI
121 const int n_real = 32;
122 const int n_int = 5;
123 const int n_err = 1;
124
125 particle_state* ps_all = malloc(n_tot * sizeof(particle_state));
126
127 if(mpi_rank == mpi_root) {
128 int start_index, n;
129 mpi_my_particles(&start_index, &n, n_tot, mpi_rank, mpi_size);
130
131 for(int j = 0; j < n; j++) {
132 ps_all[j] = ps[j];
133 }
134
135 for(int i = 1; i < mpi_size; i++) {
136 mpi_my_particles(&start_index, &n, n_tot, i, mpi_size);
137
138 real* realdata;
139 realdata = malloc(n_real * n * sizeof(realdata));
140 integer* intdata;
141 intdata = malloc(n_int * n * sizeof(intdata));
142 a5err* errdata;
143 errdata = malloc(n_err * n * sizeof(intdata));
144
145 MPI_Recv(realdata, n_real*n, mpi_type_real, i, 0,
146 MPI_COMM_WORLD, MPI_STATUS_IGNORE);
147 MPI_Recv(intdata, n_int*n, mpi_type_integer, i, 0,
148 MPI_COMM_WORLD, MPI_STATUS_IGNORE);
149 MPI_Recv(errdata, n_err*n, mpi_type_a5err, i, 0,
150 MPI_COMM_WORLD, MPI_STATUS_IGNORE);
151
152 for(int j = 0; j < n; j++) {
153 ps_all[start_index+j].r = realdata[0*n+j];
154 ps_all[start_index+j].phi = realdata[1*n+j];
155 ps_all[start_index+j].z = realdata[2*n+j];
156 ps_all[start_index+j].ppar = realdata[3*n+j];
157 ps_all[start_index+j].mu = realdata[4*n+j];
158 ps_all[start_index+j].zeta = realdata[5*n+j];
159 ps_all[start_index+j].rprt = realdata[6*n+j];
160 ps_all[start_index+j].phiprt = realdata[7*n+j];
161 ps_all[start_index+j].zprt = realdata[8*n+j];
162 ps_all[start_index+j].p_r = realdata[9*n+j];
163 ps_all[start_index+j].p_phi = realdata[10*n+j];
164 ps_all[start_index+j].p_z = realdata[11*n+j];
165 ps_all[start_index+j].mass = realdata[12*n+j];
166 ps_all[start_index+j].charge = realdata[13*n+j];
167 ps_all[start_index+j].anum = intdata[0*n+j];
168 ps_all[start_index+j].znum = intdata[1*n+j];
169 ps_all[start_index+j].weight = realdata[14*n+j];
170 ps_all[start_index+j].time = realdata[15*n+j];
171 ps_all[start_index+j].cputime = realdata[16*n+j];
172 ps_all[start_index+j].rho = realdata[17*n+j];
173 ps_all[start_index+j].theta = realdata[18*n+j];
174 ps_all[start_index+j].id = intdata[2*n+j];
175 ps_all[start_index+j].endcond = intdata[3*n+j];
176 ps_all[start_index+j].walltile = intdata[4*n+j];
177 ps_all[start_index+j].B_r = realdata[19*n+j];
178 ps_all[start_index+j].B_phi = realdata[20*n+j];
179 ps_all[start_index+j].B_z = realdata[21*n+j];
180 ps_all[start_index+j].B_r_dr = realdata[22*n+j];
181 ps_all[start_index+j].B_phi_dr = realdata[23*n+j];
182 ps_all[start_index+j].B_z_dr = realdata[24*n+j];
183 ps_all[start_index+j].B_r_dphi = realdata[25*n+j];
184 ps_all[start_index+j].B_phi_dphi = realdata[26*n+j];
185 ps_all[start_index+j].B_z_dphi = realdata[27*n+j];
186 ps_all[start_index+j].B_r_dz = realdata[28*n+j];
187 ps_all[start_index+j].B_phi_dz = realdata[29*n+j];
188 ps_all[start_index+j].B_z_dz = realdata[30*n+j];
189 ps_all[start_index+j].mileage = realdata[31*n+j];
190 ps_all[start_index+j].err = errdata[j];
191 }
192
193 free(realdata);
194 free(intdata);
195 free(errdata);
196 }
197 }
198 else {
199
200 int start_index, n;
201 mpi_my_particles(&start_index, &n, n_tot, mpi_rank, mpi_size);
202
203 real* realdata;
204 realdata = malloc(n_real * n * sizeof(realdata));
205 integer* intdata;
206 intdata = malloc(n_int * n * sizeof(intdata));
207 a5err* errdata;
208 errdata = malloc(n_err * n * sizeof(intdata));
209
210 for(int j = 0; j < n; j++) {
211 realdata[0*n+j] = ps[j].r;
212 realdata[1*n+j] = ps[j].phi;
213 realdata[2*n+j] = ps[j].z;
214 realdata[3*n+j] = ps[j].ppar;
215 realdata[4*n+j] = ps[j].mu;
216 realdata[5*n+j] = ps[j].zeta;
217 realdata[6*n+j] = ps[j].rprt;
218 realdata[7*n+j] = ps[j].phiprt;
219 realdata[8*n+j] = ps[j].zprt;
220 realdata[9*n+j] = ps[j].p_r;
221 realdata[10*n+j] = ps[j].p_phi;
222 realdata[11*n+j] = ps[j].p_z;
223 realdata[12*n+j] = ps[j].mass;
224 realdata[13*n+j] = ps[j].charge;
225 intdata[0*n+j] = ps[j].anum;
226 intdata[1*n+j] = ps[j].znum;
227 realdata[14*n+j] = ps[j].weight;
228 realdata[15*n+j] = ps[j].time;
229 realdata[16*n+j] = ps[j].cputime;
230 realdata[17*n+j] = ps[j].rho;
231 realdata[18*n+j] = ps[j].theta;
232 intdata[2*n+j] = ps[j].id;
233 intdata[3*n+j] = ps[j].endcond;
234 intdata[4*n+j] = ps[j].walltile;
235 realdata[19*n+j] = ps[j].B_r;
236 realdata[20*n+j] = ps[j].B_phi;
237 realdata[21*n+j] = ps[j].B_z;
238 realdata[22*n+j] = ps[j].B_r_dr;
239 realdata[23*n+j] = ps[j].B_phi_dr;
240 realdata[24*n+j] = ps[j].B_z_dr;
241 realdata[25*n+j] = ps[j].B_r_dphi;
242 realdata[26*n+j] = ps[j].B_phi_dphi;
243 realdata[27*n+j] = ps[j].B_z_dphi;
244 realdata[28*n+j] = ps[j].B_r_dz;
245 realdata[29*n+j] = ps[j].B_phi_dz;
246 realdata[30*n+j] = ps[j].B_z_dz;
247 realdata[31*n+j] = ps[j].mileage;
248 errdata[j] = ps[j].err;
249 }
250
251 MPI_Send(realdata, n_real*n, mpi_type_real, 0, 0, MPI_COMM_WORLD);
252 MPI_Send(intdata, n_int*n, mpi_type_integer, 0, 0, MPI_COMM_WORLD);
253 MPI_Send(errdata, n_err*n, mpi_type_a5err, 0, 0, MPI_COMM_WORLD);
254
255 free(realdata);
256 free(intdata);
257 free(errdata);
258 }
259
260 *ps_gather = ps_all;
261 *n_gather = n_tot;
262
263#else
264
265 int start_index, n;
266 mpi_my_particles(&start_index, &n, n_tot, mpi_rank, mpi_size);
267
268 /* Only store particles for this process in Condor-style execution */
269 particle_state* ps_all = malloc(n * sizeof(particle_state));
270
271 for(int j = 0; j < n; j++) {
272 ps_all[j] = ps[j];
273 }
274
275 *ps_gather = ps_all;
276 *n_gather = n;
277
278#endif
279}
280
295void mpi_gather_diag(diag_offload_data* data, real* offload_array, int ntotal,
296 int mpi_rank, int mpi_size, int mpi_root) {
297#ifdef MPI
298
299 if(data->dist5D_collect || data->distrho5D_collect
300 || data->dist6D_collect || data->distrho6D_collect) {
301 if(mpi_rank == mpi_root) {
302 MPI_Reduce(MPI_IN_PLACE, offload_array,
303 data->offload_dist_length, mpi_type_real, MPI_SUM,
304 0, MPI_COMM_WORLD);
305 } else {
306 MPI_Reduce(offload_array, offload_array,
307 data->offload_dist_length, mpi_type_real, MPI_SUM,
308 0, MPI_COMM_WORLD);
309 }
310 }
311
312 if(data->diagorb_collect) {
313 if(mpi_rank == mpi_root) {
314 for(int i = 1; i < mpi_size; i++) {
315 int start_index, n;
316 mpi_my_particles(&start_index, &n, ntotal, i, mpi_size);
317
318 for(int j = 0; j < data->diagorb.Nfld; j++) {
319 MPI_Recv(&offload_array[data->offload_diagorb_index
320 +j*data->diagorb.Nmrk*data->diagorb.Npnt
321 +start_index*data->diagorb.Npnt],
322 n*data->diagorb.Npnt, mpi_type_real, i, 0,
323 MPI_COMM_WORLD, MPI_STATUS_IGNORE);
324 }
325 }
326 }
327 else {
328 int start_index, n;
329 mpi_my_particles(&start_index, &n, ntotal, mpi_rank, mpi_size);
330
331 for(int j = 0; j < data->diagorb.Nfld; j++) {
332 MPI_Send(&offload_array[data->offload_diagorb_index
333 +j*data->diagorb.Nmrk*data->diagorb.Npnt],
334 n*data->diagorb.Npnt, mpi_type_real, 0, 0, MPI_COMM_WORLD);
335 }
336 }
337 }
338
339 if(data->diagtrcof_collect) {
340 /* 3 fields for transport coefficients, id, D, K */
341 int nfield = 3;
342
343 if(mpi_rank == mpi_root) {
344 for(int i = 1; i < mpi_size; i++) {
345 int start_index, n;
346 mpi_my_particles(&start_index, &n, ntotal, i, mpi_size);
347
348 for(int j = 0; j < nfield; j++) {
349 MPI_Recv(&offload_array[data->offload_diagtrcof_index
350 +j*data->diagtrcof.Nmrk
351 +start_index],
352 n, mpi_type_real, i, 0,
353 MPI_COMM_WORLD, MPI_STATUS_IGNORE);
354 }
355 }
356 }
357 else {
358 int start_index, n;
359 mpi_my_particles(&start_index, &n, ntotal, mpi_rank, mpi_size);
360
361 for(int j = 0; j < nfield; j++) {
362 MPI_Send(&offload_array[data->offload_diagtrcof_index
363 +j*data->diagtrcof.Nmrk],
364 n, mpi_type_real, 0, 0, MPI_COMM_WORLD);
365 }
366 }
367 }
368
369#endif
370}
Main header file for ASCOT5.
double real
Definition ascot5.h:85
long integer
Definition ascot5.h:84
Header file for diag.c.
unsigned long int a5err
Simulation error flag.
Definition error.h:17
void mpi_my_particles(int *start_index, int *n, int n_tot, int mpi_rank, int mpi_size)
Divide markers to mpi processes.
void mpi_gather_diag(diag_offload_data *data, real *offload_array, int ntotal, int mpi_rank, int mpi_size, int mpi_root)
Gather all diagnostics to the root process.
void mpi_interface_finalize()
Finalize MPI.
void mpi_interface_init(int argc, char **argv, int *mpi_rank, int *mpi_size, int *mpi_root)
Initialize MPI.
void mpi_interface_barrier()
Wait until all processes have reached this routine.
void mpi_gather_particlestate(particle_state *ps, particle_state **ps_gather, int *n_gather, int n_tot, int mpi_rank, int mpi_size, int mpi_root)
Gather all particle states to the root process.
Header file for mpi_interface.c.
#define mpi_type_integer
ASCOT integer in MPI standard.
#define mpi_type_a5err
ASCOT error in MPI standard
#define mpi_type_real
ASCOT real in MPI standard
Header file for particle.c.
Header file for simulate.c.
Diagnostics offload data struct.
Definition diag.h:21
int distrho6D_collect
Definition diag.h:26
size_t offload_dist_length
Definition diag.h:46
int diagtrcof_collect
Definition diag.h:28
diag_transcoef_offload_data diagtrcof
Definition diag.h:36
size_t offload_diagtrcof_index
Definition diag.h:44
int distrho5D_collect
Definition diag.h:25
int dist5D_collect
Definition diag.h:23
int diagorb_collect
Definition diag.h:22
int dist6D_collect
Definition diag.h:24
size_t offload_diagorb_index
Definition diag.h:43
diag_orb_offload_data diagorb
Definition diag.h:30
General representation of a marker.
Definition particle.h:40
integer id
Definition particle.h:63
integer walltile
Definition particle.h:65
real B_phi_dphi
Definition particle.h:73
integer endcond
Definition particle.h:64