ASCOT5
Loading...
Searching...
No Matches
simulate.c
Go to the documentation of this file.
1
14#include <string.h>
15#include <unistd.h>
16#include "endcond.h"
17#include "particle.h"
18#include "plasma.h"
19#include "wall.h"
20#include "boozer.h"
21#include "mhd.h"
22#include "neutral.h"
23#include "B_field.h"
24#include "E_field.h"
25#include "random.h"
26#include "simulate.h"
27#include "print.h"
32#include "simulate/mccc/mccc.h"
33#include "gctransform.h"
34#include "asigma.h"
35
36void sim_monitor(char* filename, volatile int* n, volatile int* finished);
37
83void simulate(int n_particles, particle_state* p, sim_data* sim) {
84
85 // Size = NSIMD on CPU and Size = Total number of particles on GPU
86 int n_queue_size;
87#ifdef GPU
88 n_queue_size = n_particles;
89#else
90 n_queue_size = NSIMD;
91#endif
92 /**************************************************************************/
93 /* 1. Input offload data is unpacked and initialized by calling */
94 /* respective init functions. */
95 /* */
96 /**************************************************************************/
97 simulate_init(sim);
98
99#ifdef GPU
100 if(sim->sim_mode != 1) {
101 print_err("Only GO mode ported to GPU. Please set SIM_MODE=1.");
102 exit(1);
103 }
104 if(sim->record_mode) {
105 print_err("RECORD_MODE=1 not ported to GPU. Please disable it.");
106 exit(1);
107 }
108 if(sim->enable_atomic) {
109 print_err("Atomic not yet ported to GPU. Please set ENABLE_ATOMIC=0.");
110 exit(1);
111 }
112 if(sim->enable_mhd) {
113 print_err("MHD not yet ported to GPU. Please set ENABLE_MHD=0.");
114 exit(1);
115 }
116 if(sim->diag_data.diagorb_collect) {
117 print_err(
118 "ENABLE_ORBITWRITE=1 not ported to GPU. Please disable it.");
119 exit(1);
120 }
122 print_err(
123 "ENABLE_TRANSCOEF=1 not ported to GPU. Please disable it.");
124 exit(1);
125 }
126#endif
127
128 diag_init(&sim->diag_data, n_particles);
129 GPU_MAP_TO_DEVICE(sim[0:1])
130 B_field_offload(&sim->B_data);
131 E_field_offload(&sim->E_data);
134 wall_offload(&sim->wall_data);
136 mhd_offload(&sim->mhd_data);
138 diag_offload(&sim->diag_data);
139
140 /**************************************************************************/
141 /* 2. Meta data (e.g. random number generator) is initialized. */
142 /* */
143 /**************************************************************************/
144 random_init(&sim->random_data, 0);
145
146 /**************************************************************************/
147 /* 3. Markers are put into simulation queue. */
148 /* */
149 /**************************************************************************/
151
152 pq.n = 0;
153 for(int i = 0; i < n_particles; i++) {
154 pq.n++;
155 }
156
157 pq.p = (particle_state**) malloc(pq.n * sizeof(particle_state*));
158 pq.finished = 0;
159
160 pq.next = 0;
161 for(int i = 0; i < n_particles; i++) {
162 pq.p[pq.next++] = &p[i];
163
164 }
165 pq.next = 0;
166
167 print_out(VERBOSE_NORMAL, "Simulation begins; %d threads.\n",
168 omp_get_max_threads());
169 fflush(stdout);
170
171 /**************************************************************************/
172 /* 4. Threads are spawned. One thread is dedicated for monitoring */
173 /* progress, if monitoring is active. */
174 /* */
175 /**************************************************************************/
176#ifndef GPU
177 omp_set_max_active_levels(2);
178#endif
179#if !defined(GPU) && VERBOSE > 1
180 #pragma omp parallel sections num_threads(2)
181 {
182 #pragma omp section
183#endif
184 {
185 /******************************************************************/
186 /* 5. Other threads execute marker simulation using the mode the */
187 /* user has chosen. */
188 /* */
189 /******************************************************************/
190 if(pq.n > 0 && (sim->sim_mode == simulate_mode_gc
191 || sim->sim_mode == simulate_mode_hybrid)) {
192 if(sim->enable_ada) {
193 OMP_PARALLEL_CPU_ONLY
194 simulate_gc_adaptive(&pq, sim);
195 }
196 else {
197 OMP_PARALLEL_CPU_ONLY
198 simulate_gc_fixed(&pq, sim);
199 }
200 }
201 else if(pq.n > 0 && sim->sim_mode == simulate_mode_fo) {
202 OMP_PARALLEL_CPU_ONLY
203 simulate_fo_fixed(&pq, sim, n_queue_size);
204 }
205 else if(pq.n > 0 && sim->sim_mode == simulate_mode_ml) {
206 OMP_PARALLEL_CPU_ONLY
207 simulate_ml_adaptive(&pq, sim);
208 }
209 }
210#if !defined(GPU) && VERBOSE > 1
211 #pragma omp section
212 {
213 /* Update progress until simulation is complete. */
214 /* Trim .h5 from filename and replace it with _<QID>.stdout */
215 if(id == 0) {
216 char filename[519], outfn[256];
217 strcpy(outfn, sim->hdf5_out);
218 outfn[strlen(outfn)-3] = '\0';
219 sprintf(filename, "%s_%s.stdout", outfn, sim->qid);
220 sim_monitor(filename, &pq.n, &pq.finished);
221 }
222 }
223 }
224#endif
225
226 /**************************************************************************/
227 /* 6. (If hybrid mode is active) Markers with hybrid end condition active */
228 /* are placed on a new queue, and they have their end condition */
229 /* deactivated and they are simulated with simulate_fo_fixed.c until */
230 /* they have met some other end condition. Threads are spawned and */
231 /* progress is monitored as previously. */
232 /* */
233 /**************************************************************************/
234 int n_new = 0;
235 if(sim->sim_mode == simulate_mode_hybrid) {
236
237 /* Determine the number markers that should be run
238 * in fo after previous gc simulation */
239 for(int i = 0; i < pq.n; i++) {
240 if(pq.p[i]->endcond == endcond_hybrid) {
241 /* Check that there was no wall between when moving from
242 gc to fo */
243 real w_coll;
244 int tile = wall_hit_wall(pq.p[i]->r, pq.p[i]->phi, pq.p[i]->z,
245 pq.p[i]->rprt, pq.p[i]->phiprt, pq.p[i]->zprt,
246 &sim->wall_data, &w_coll);
247 if(tile > 0) {
248 pq.p[i]->walltile = tile;
249 pq.p[i]->endcond |= endcond_wall;
250 }
251 else {
252 n_new++;
253 }
254 }
255 }
256 }
257 if(n_new > 0) {
258
259 /* Reset hybrid marker end condition */
260 for(int i = 0; i < pq.n; i++) {
261 if(pq.p[i]->endcond & endcond_hybrid) {
262 pq.p[i]->endcond ^= endcond_hybrid;
263 }
264 }
265 pq.next = 0;
266 pq.finished = 0;
267
268#if !defined(GPU) && VERBOSE > 1
269 #pragma omp parallel sections num_threads(2)
270 {
271 #pragma omp section
272#endif
273 {
274 OMP_PARALLEL_CPU_ONLY
275 simulate_fo_fixed(&pq, sim, n_queue_size);
276 }
277#if !defined(GPU) && VERBOSE > 1
278 #pragma omp section
279 {
280 /* Trim .h5 from filename and replace it with _<qid>.stdout */
281 if(id == 0) {
282 char filename[519], outfn[256];
283 strcpy(outfn, sim->hdf5_out);
284 outfn[strlen(outfn)-3] = '\0';
285 sprintf(filename, "%s_%s.stdout", outfn, sim->qid);
286 sim_monitor(filename, &pq.n, &pq.finished);
287 }
288 }
289 }
290#endif
291 }
292
293 /**************************************************************************/
294 /* 7. Simulation data is deallocated. */
295 /**************************************************************************/
296 free(pq.p);
297
298 print_out(VERBOSE_NORMAL, "Simulation complete.\n");
299}
300
307
310
311 if(sim->disable_gctransform) {
313 }
315
316}
317
334void sim_monitor(char* filename, volatile int* n, volatile int* finished) {
335 /* Open a file for writing simulation progress */
336 FILE *f = fopen(filename, "w");
337 if (f == NULL) {
339 "Warning. %s could not be opened for progress updates.\n",
340 filename);
341 return;
342 }
343
344 real time_sim_started = A5_WTIME;
345 int stopflag = 1; /* Ensures progress is written one last time at 100% */
346 int n_temp, finished_temp; /* Use these to store volatile variables so that
347 their value does not change during one loop */
348 while(stopflag) {
349 n_temp = *n;
350 finished_temp = *finished;
351 real fracprog = ((real) finished_temp)/n_temp;
352 real timespent = (A5_WTIME)-time_sim_started;
353
354 if(n_temp == finished_temp) {
355 stopflag = 0;
356 }
357
358 if(fracprog == 0) {
359 fprintf(f, "No marker has finished simulation yet. "
360 "Time spent: %.2f h\n", timespent/3600);
361 }
362 else {
363 fprintf(f, "Progress: %d/%d, %.2f %%. Time spent: %.2f h, "
364 "estimated time to finish: %.2f h\n", finished_temp, n_temp,
365 100*fracprog, timespent/3600, (1/fracprog-1)*timespent/3600);
366 }
367 fflush(f);
368 //sleep(A5_PRINTPROGRESSINTERVAL);
369 }
370
371 fprintf(f, "Simulation finished.\n");
372 fclose(f);
373}
void B_field_offload(B_field_data *data)
Offload data to the accelerator.
Definition B_field.c:61
Header file for B_field.c.
void E_field_offload(E_field_data *data)
Offload data to the accelerator.
Definition E_field.c:46
Header file for E_field.c.
double real
Definition ascot5.h:85
#define NSIMD
Number of particles simulated simultaneously in a particle group operations.
Definition ascot5.h:91
#define A5_WTIME
Wall time.
Definition ascot5.h:124
void asigma_extrapolate(int extrapolate)
Toggle extrapolation when evaluating cross sections.
Definition asigma.c:45
void asigma_offload(asigma_data *data)
Offload data to the accelerator.
Definition asigma.c:67
Header file for asigma.c.
void boozer_offload(boozer_data *data)
Offload data to the accelerator.
Definition boozer.c:91
Header file for boozer.c.
void diag_offload(diag_data *data)
Offload data to the accelerator.
Definition diag.c:116
int diag_init(diag_data *data, int Nmrk)
Initializes diagnostics data.
Definition diag.c:37
Header file for endcond.c.
@ endcond_wall
Definition endcond.h:22
@ endcond_hybrid
Definition endcond.h:28
void gctransform_setorder(int order)
Set the order of the transformation.
Definition gctransform.c:62
Header file for gctransform.c.
void mccc_init(mccc_data *mdata, int include_energy, int include_pitch, int include_gcdiff)
Set collision operator data.
Definition mccc.c:17
Header file for mccc package.
void mhd_offload(mhd_data *data)
Offload data to the accelerator.
Definition mhd.c:50
Header file for mhd.c.
void neutral_offload(neutral_data *data)
Offload data to the accelerator.
Definition neutral.c:45
Header file for neutral.c.
Header file for particle.c.
void plasma_offload(plasma_data *data)
Offload data to the accelerator.
Definition plasma.c:57
Header file for plasma.c.
Macros for printing console output.
#define print_out(v,...)
Print to standard output.
Definition print.h:31
@ VERBOSE_NORMAL
Definition print.h:18
@ VERBOSE_DEBUG
Definition print.h:17
#define print_err(...)
Print to standard error.
Definition print.h:42
Header file for random.c.
#define random_init(data, seed)
Definition random.h:94
void simulate(int n_particles, particle_state *p, sim_data *sim)
Execute marker simulation.
Definition simulate.c:83
void simulate_init(sim_data *sim)
Initialize simulation data struct.
Definition simulate.c:306
void sim_monitor(char *filename, volatile int *n, volatile int *finished)
Monitor simulation progress.
Definition simulate.c:334
Header file for simulate.c.
@ simulate_mode_fo
Definition simulate.h:33
@ simulate_mode_ml
Definition simulate.h:44
@ simulate_mode_gc
Definition simulate.h:36
@ simulate_mode_hybrid
Definition simulate.h:41
void simulate_fo_fixed(particle_queue *pq, sim_data *sim, int mrk_array_size)
Simulates particles using fixed time-step.
Header file for simulate_fo_fixed.c.
void simulate_gc_adaptive(particle_queue *pq, sim_data *sim)
Simulates guiding centers using adaptive time-step.
Header file for simulate_gc_adaptive.c.
void simulate_gc_fixed(particle_queue *pq, sim_data *sim)
Simulates guiding centers using fixed time-step.
Header file for simulate_gc_fixed.c.
void simulate_ml_adaptive(particle_queue *pq, sim_data *sim)
Simulates magnetic field-lines using adaptive time-step.
Header file for simulate_ml_adaptive.c.
int diagtrcof_collect
Definition diag.h:28
int diagorb_collect
Definition diag.h:22
Marker queue.
Definition particle.h:154
particle_state ** p
Definition particle.h:156
volatile int next
Definition particle.h:158
volatile int finished
Definition particle.h:159
General representation of a marker.
Definition particle.h:40
integer walltile
Definition particle.h:65
integer endcond
Definition particle.h:64
Simulation data struct.
Definition simulate.h:57
char qid[256]
Definition simulate.h:128
int record_mode
Definition simulate.h:78
int sim_mode
Definition simulate.h:76
int disable_energyccoll
Definition simulate.h:103
plasma_data plasma_data
Definition simulate.h:61
mhd_data mhd_data
Definition simulate.h:65
int enable_atomic
Definition simulate.h:100
int disable_gcdiffccoll
Definition simulate.h:107
E_field_data E_data
Definition simulate.h:60
int disable_pitchccoll
Definition simulate.h:105
int enable_mhd
Definition simulate.h:99
mccc_data mccc_data
Definition simulate.h:72
random_data random_data
Definition simulate.h:71
neutral_data neutral_data
Definition simulate.h:62
boozer_data boozer_data
Definition simulate.h:64
int enable_ada
Definition simulate.h:77
B_field_data B_data
Definition simulate.h:59
char hdf5_out[256]
Definition simulate.h:127
wall_data wall_data
Definition simulate.h:63
asigma_data asigma_data
Definition simulate.h:66
int disable_gctransform
Definition simulate.h:101
diag_data diag_data
Definition simulate.h:68
void wall_offload(wall_data *data)
Offload data to the accelerator.
Definition wall.c:46
int wall_hit_wall(real r1, real phi1, real z1, real r2, real phi2, real z2, wall_data *w, real *w_coll)
Check if a given directed line segment intersects the wall.
Definition wall.c:80
Header file for wall.c.