ASCOT5
Loading...
Searching...
No Matches
simulate_gc_fixed.c
Go to the documentation of this file.
1
5#include <stdio.h>
6#include <stdlib.h>
7#include <omp.h>
8#include <math.h>
9#include "../ascot5.h"
10#include "../endcond.h"
11#include "../math.h"
12#include "../consts.h"
13#include "../physlib.h"
14#include "../simulate.h"
15#include "../particle.h"
16#include "../wall.h"
17#include "../diag.h"
18#include "../B_field.h"
19#include "../E_field.h"
20#include "../rfof.h"
21#include "../plasma.h"
22#include "simulate_gc_fixed.h"
23#include "step/step_gc_rk4.h"
24#include "mccc/mccc.h"
25
26DECLARE_TARGET_SIMD_UNIFORM(sim)
28
29#define DUMMY_TIMESTEP_VAL 1.0
30
49void simulate_gc_fixed(particle_queue* pq, sim_data* sim, int mrk_array_size) {
50 int* cycle = (int*) malloc(mrk_array_size*sizeof(int)); /* Flag indigating whether a new marker
51 was initialized */
52 real* hin = (real*) malloc(mrk_array_size*sizeof(real));/* Time step given as an input into the
53 integrators. Almost always default.*/
54 real* hin_default = (real*) malloc(mrk_array_size*sizeof(real)); /* The default fixed time step. */
55 real* hnext_recom = (real*) malloc(mrk_array_size*sizeof(real)); /* Next time step, only used to
56 store the value when RFOF has
57 rejected a time step. */
58 real* hout_rfof = (real*) malloc(mrk_array_size*sizeof(real)); /* The time step that RFOF recommends.
59 Small positive means that resonance
60 is close, small negative means that
61 the step failed because the marker
62 overshot the resonance and that the
63 time step should be retaken with a
64 smaller time step given by the
65 negative of hout_rfof */
66 real cputime, cputime_last; // Global cpu time: recent and previous record
67
68 particle_simd_gc p; // This array holds current states
69 particle_simd_gc p0; // This array stores previous states
70 particle_allocate_gc(&p, mrk_array_size);
71 particle_allocate_gc(&p0, mrk_array_size);
72 rfof_marker rfof_mrk; // RFOF specific data
73
74 /* Init dummy markers */
75 for(int i=0; i< mrk_array_size; i++) {
76 p.id[i] = -1;
77 p.running[i] = 0;
78 hout_rfof[i] = DUMMY_TIMESTEP_VAL;
79 hnext_recom[i] = DUMMY_TIMESTEP_VAL;
80 }
81
82 /* Initialize running particles */
83 int n_running = particle_cycle_gc(pq, &p, &sim->B_data, cycle);
84
85 if(sim->enable_icrh) {
86 rfof_set_up(&rfof_mrk, &sim->rfof_data);
87 }
88
89 /* Determine simulation time-step */
90 #pragma omp simd
91 for(int i = 0; i < mrk_array_size; i++) {
92 if(cycle[i] > 0) {
93 hin_default[i] = simulate_gc_fixed_inidt(sim, &p, i);
94 hin[i] = hin_default[i];
95 }
96 }
97
98 cputime_last = A5_WTIME;
99
100 /* MAIN SIMULATION LOOP
101 * - Store current state
102 * - Integrate motion due to background EM-field (orbit-following)
103 * - Integrate scattering due to Coulomb collisions
104 * - Perform ICRH kick with RFOF if in wave-particle resonance
105 * - Advance time
106 * - Check for end condition(s)
107 * - Update diagnostics
108 */
111 real* rnd = (real*) malloc(5*mrk_array_size*sizeof(real));
112 GPU_MAP_TO_DEVICE(hin[0:mrk_array_size], rnd[0:5*mrk_array_size], hin_default[0:mrk_array_size], hnext_recom[0:mrk_array_size], hout_rfof[0:mrk_array_size])
113 while(n_running > 0) {
114
115 /* Store marker states */
116 GPU_PARALLEL_LOOP_ALL_LEVELS
117 for(int i = 0; i < p.n_mrk; i++) {
118 particle_copy_gc(&p, i, &p0, i);
119 }
120
121 /*************************** Physics **********************************/
122
123 /* Set time-step negative if tracing backwards in time */
124 GPU_PARALLEL_LOOP_ALL_LEVELS
125 for(int i = 0; i < p.n_mrk; i++) {
126 if(sim->reverse_time) {
127 hin[i] = -hin[i];
128 }
129 }
130
131 /* RK4 method for orbit-following */
132 if(sim->enable_orbfol) {
133 if(sim->enable_mhd) {
135 &p, hin, &sim->B_data, &sim->E_data, &sim->boozer_data,
136 &sim->mhd_data, sim->enable_aldforce);
137 }
138 else {
139 step_gc_rk4(&p, hin, &sim->B_data, &sim->E_data,
140 sim->enable_aldforce);
141 }
142 }
143
144 /* Switch sign of the time-step again if it was reverted earlier */
145 GPU_PARALLEL_LOOP_ALL_LEVELS
146 for(int i = 0; i < p.n_mrk; i++) {
147 if(sim->reverse_time) {
148 hin[i] = -hin[i];
149 }
150 }
151
152 /* Euler-Maruyama method for collisions */
153 if(sim->enable_clmbcol) {
154 random_normal_simd(sim->random_data, 5*p.n_mrk, rnd);
155 mccc_gc_euler(&p, hin, &sim->B_data, &sim->plasma_data,
156 &sim->mccc_data, rnd);
157 }
158
159 /* Performs the ICRH kick if in resonance. */
160 if(sim->enable_icrh) {
161 rfof_resonance_check_and_kick_gc(
162 &p, hin, hout_rfof, &rfof_mrk, &sim->rfof_data, &sim->B_data);
163
164 /* Check whether time step was rejected */
165 #pragma omp simd
166 for(int i = 0; i < NSIMD; i++) {
167 if(p.running[i] && hout_rfof[i] < 0){
168 // Screwed up big time
169 p.running[i] = 0;
170 hnext_recom[i] = hout_rfof[i]; /* Use the smaller time-step
171 suggested by RFOF on the
172 next round. */
173 } else if(p.running[i]) {
174 // Everything went better than expected
175 hin[i] = hin_default[i]; // use the original fixed step
176 }
177 }
178 }
179
180 /**********************************************************************/
181
182
183 /* Update simulation and cpu times */
184 cputime = A5_WTIME;
185 GPU_PARALLEL_LOOP_ALL_LEVELS
186 for(int i = 0; i < p.n_mrk; i++) {
187 if(hnext_recom[i] < 0) {
188 /* Screwed up big time (negative time-step only when RFOF
189 rejected) */
190 particle_copy_gc(&p0, i, &p, i);
191 hin[i] = -hnext_recom[i];
192 }
193 if(p.running[i]) {
194 if(hnext_recom[i] < 0) {
195 // unsuccessful step, only reset the recommendation
196 hnext_recom[i] = DUMMY_TIMESTEP_VAL;
197 } else {
198 // The step was successful
199 p.time[i] += ( 1.0 - 2.0 * ( sim->reverse_time > 0 ) ) * hin[i];
200 p.mileage[i] += hin[i];
201 p.cputime[i] += cputime - cputime_last;
202 }
203 }
204 }
205 cputime_last = cputime;
206
207 /* Check possible end conditions */
208 endcond_check_gc(&p, &p0, sim);
209
210 /* Update diagnostics */
211 diag_update_gc(&sim->diag_data, &sim->B_data, &p, &p0);
212
213 /* Update running particles */
214#ifdef GPU
215 n_running = 0;
216 GPU_PARALLEL_LOOP_ALL_LEVELS_REDUCTION(n_running)
217 for(int i = 0; i < p.n_mrk; i++)
218 {
219 if(p.running[i] > 0) n_running++;
220 }
221#else
222 n_running = particle_cycle_gc(pq, &p, &sim->B_data, cycle);
223#endif
224
225#ifndef GPU
226 /* Determine simulation time-step */
227 #pragma omp simd
228 for(int i = 0; i < p.n_mrk; i++) {
229 if(cycle[i] > 0) {
230 hin[i] = simulate_gc_fixed_inidt(sim, &p, i);
231 if(sim->enable_icrh) {
232 /* Reset icrh (rfof) resonance memory matrix. */
233 rfof_clear_history(&rfof_mrk, i);
234 }
235 }
236 }
237#endif
238
239 }
240
241 /* All markers simulated! */
242#ifdef GPU
243 GPU_MAP_FROM_DEVICE(sim[0:1])
245 n_running = particle_cycle_gc(pq, &p, &sim->B_data, cycle);
246#endif
247 free(cycle);
248 free(hin);
249 free(rnd);
250
251 /* Deallocate rfof structs */
252 if(sim->enable_icrh) {
253 rfof_tear_down(&rfof_mrk);
254 }
255}
256
271 real h;
272
273 /* Value defined directly by user */
274 if(sim->fix_usrdef_use) {
275 h = sim->fix_usrdef_val;
276 }
277 else {
278 /* Value calculated from gyrotime */
279 real Bnorm = math_normc(p->B_r[i], p->B_phi[i], p->B_z[i]);
280 real gyrotime = CONST_2PI /
281 phys_gyrofreq_ppar(p->mass[i], p->charge[i],
282 p->mu[i], p->ppar[i], Bnorm);
283 h = gyrotime/sim->fix_gyrodef_nstep;
284 }
285
286 return h;
287}
Header file for B_field.c.
Header file for E_field.c.
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
#define A5_WTIME
Wall time.
Definition ascot5.h:124
Header file containing physical and mathematical constants.
#define CONST_2PI
2*pi
Definition consts.h:14
void diag_update_gc(diag_data *data, B_field_data *Bdata, particle_simd_gc *p_f, particle_simd_gc *p_i)
Collects diagnostics when marker represents a guiding center.
Definition diag.c:217
Header file for diag.c.
void endcond_check_gc(particle_simd_gc *p_f, particle_simd_gc *p_i, sim_data *sim)
Check end conditions for GC markers.
Definition endcond.c:277
Header file for endcond.c.
Header file for math.c.
#define math_normc(a1, a2, a3)
Calculate norm of 3D vector from its components a1, a2, a3.
Definition math.h:71
Header file for mccc package.
void mccc_gc_euler(particle_simd_gc *p, real *h, B_field_data *Bdata, plasma_data *pdata, mccc_data *mdata, real *rnd)
Integrate collisions for one time-step.
void particle_allocate_gc(particle_simd_gc *p_gc, int nmrk)
Allocates guiding center struct representing particle markers.
Definition particle.c:126
void particle_onload_gc(particle_simd_gc *p)
Onload guiding center particle struct from the GPU.
Definition particle.c:1914
void particle_copy_gc(particle_simd_gc *p1, int i, particle_simd_gc *p2, int j)
Copy GC struct.
Definition particle.c:1407
void particle_offload_gc(particle_simd_gc *p)
Offload guiding center particle struct to GPU.
Definition particle.c:1870
int particle_cycle_gc(particle_queue *q, particle_simd_gc *p, B_field_data *Bdata, int *cycle)
Replace finished GC markers with new ones or dummies.
Definition particle.c:419
Header file for particle.c.
Methods to evaluate elementary physical quantities.
#define phys_gyrofreq_ppar(m, q, mu, ppar, B)
Evaluate gyrofrequency [rad/s] from parallel momentum and magnetic moment.
Definition physlib.h:278
Header file for plasma.c.
#define random_normal_simd(data, n, r)
Definition random.h:115
Contains the functions to be called from the simulation loop when using ICRH.
Header file for simulate.c.
#define DUMMY_TIMESTEP_VAL
real simulate_gc_fixed_inidt(sim_data *sim, particle_simd_gc *p, int i)
Calculates time step value.
void simulate_gc_fixed(particle_queue *pq, sim_data *sim, int mrk_array_size)
Simulates guiding centers using fixed time-step.
Header file for simulate_gc_fixed.c.
void step_gc_rk4(particle_simd_gc *p, real *h, B_field_data *Bdata, E_field_data *Edata, int aldforce)
Integrate a guiding center step for a struct of markers with RK4.
Definition step_gc_rk4.c:34
void step_gc_rk4_mhd(particle_simd_gc *p, real *h, B_field_data *Bdata, E_field_data *Edata, boozer_data *boozer, mhd_data *mhd, int aldforce)
Integrate a guiding center step with RK4 with MHD modes present.
Header file for step_gc_rk4.c.
Marker queue.
Definition particle.h:154
Struct representing NSIMD guiding center markers.
Definition particle.h:275
integer * running
Definition particle.h:320
integer * id
Definition particle.h:312
Reusable struct for storing marker specific data during the simulation loop.
Definition rfof.h:19
Simulation data struct.
Definition simulate.h:58
int enable_orbfol
Definition simulate.h:99
plasma_data plasma_data
Definition simulate.h:62
mhd_data mhd_data
Definition simulate.h:66
rfof_data rfof_data
Definition simulate.h:70
real fix_usrdef_val
Definition simulate.h:84
E_field_data E_data
Definition simulate.h:61
int enable_aldforce
Definition simulate.h:104
int enable_mhd
Definition simulate.h:101
int fix_usrdef_use
Definition simulate.h:83
random_data * random_data
Definition simulate.h:74
mccc_data mccc_data
Definition simulate.h:75
int fix_gyrodef_nstep
Definition simulate.h:85
boozer_data boozer_data
Definition simulate.h:65
B_field_data B_data
Definition simulate.h:60
int reverse_time
Definition simulate.h:113
int enable_icrh
Definition simulate.h:103
int enable_clmbcol
Definition simulate.h:100
diag_data diag_data
Definition simulate.h:69
Header file for wall.c.