ASCOT5
Loading...
Searching...
No Matches
simulate_gc_adaptive.c
Go to the documentation of this file.
1
5#include <stdio.h>
6#include <stdlib.h>
7#include <time.h>
8#include <omp.h>
9#include <math.h>
10#include "../ascot5.h"
11#include "../endcond.h"
12#include "../math.h"
13#include "../consts.h"
14#include "../physlib.h"
15#include "../simulate.h"
16#include "../particle.h"
17#include "../wall.h"
18#include "../diag.h"
19#include "../B_field.h"
20#include "../E_field.h"
21#include "../boozer.h"
22#include "../mhd.h"
23#include "../rfof.h"
24#include "../plasma.h"
26#include "step/step_gc_cashkarp.h"
27#include "mccc/mccc.h"
28#include "mccc/mccc_wiener.h"
29
30DECLARE_TARGET_SIMD_UNIFORM(sim)
32
33#define DUMMY_TIMESTEP_VAL 1.0
34
56
57 /* Wiener arrays needed for the adaptive time step */
58 mccc_wienarr wienarr[NSIMD];
59
60 /* Current time step, suggestions for the next time step and next time
61 * step */
63 real hout_orb[NSIMD] __memalign__;
64 real hout_col[NSIMD] __memalign__;
65 real hout_rfof[NSIMD] __memalign__;
66 real hnext[NSIMD] __memalign__;
67
68 /* Flag indicateing whether a new marker was initialized */
69 int cycle[NSIMD] __memalign__;
70
71 real tol_col = sim->ada_tol_clmbcol;
72 real tol_orb = sim->ada_tol_orbfol;
73
74 real cputime, cputime_last; // Global cpu time: recent and previous record
75
76 particle_simd_gc p; // This array holds current states
77 particle_simd_gc p0; // This array stores previous states
78
79 rfof_marker rfof_mrk; // RFOF specific data
80
81 for(int i=0; i< NSIMD; i++) {
82 p.id[i] = -1;
83 p.running[i] = 0;
84 }
85
86 /* Initialize running particles */
87 int n_running = particle_cycle_gc(pq, &p, &sim->B_data, cycle);
88
89 if(sim->enable_icrh) {
90 rfof_set_up(&rfof_mrk, &sim->rfof_data);
91 }
92
93 #pragma omp simd
94 for(int i = 0; i < NSIMD; i++) {
95 if(cycle[i] > 0) {
96 /* Determine initial time-step */
97 hin[i] = simulate_gc_adaptive_inidt(sim, &p, i);
98 if(sim->enable_clmbcol) {
99 /* Allocate array storing the Wiener processes */
100 mccc_wiener_initialize(&(wienarr[i]), p.time[i]);
101 }
102 }
103 }
104
105 cputime_last = A5_WTIME;
106
107 /* MAIN SIMULATION LOOP
108 * - Store current state
109 * - Integrate motion due to bacgkround EM-field (orbit-following)
110 * - Integrate scattering due to Coulomb collisions
111 * - Check whether time step was accepted
112 * - NO: revert to initial state and ignore the end of the loop
113 * (except CPU_TIME_MAX end condition if this is implemented)
114 * - YES: update particle time, clean redundant Wiener processes, and
115 * proceed
116 * - Check for end condition(s)
117 * - Update diagnostics
118 */
119 while(n_running > 0) {
120
121 /* Store marker states in case time step will be rejected */
122 #pragma omp simd
123 for(int i = 0; i < NSIMD; i++) {
124 particle_copy_gc(&p, i, &p0, i);
125 hout_orb[i] = DUMMY_TIMESTEP_VAL;
126 hout_col[i] = DUMMY_TIMESTEP_VAL;
127 hout_rfof[i] = DUMMY_TIMESTEP_VAL;
128 hnext[i] = DUMMY_TIMESTEP_VAL;
129 }
130
131 /*************************** Physics **********************************/
132
133 /* Set time-step negative if tracing backwards in time */
134 #pragma omp simd
135 for(int i = 0; i < NSIMD; i++) {
136 if(sim->reverse_time) {
137 hin[i] = -hin[i];
138 }
139 }
140
141 /* Cash-Karp method for orbit-following */
142 if(sim->enable_orbfol) {
143 if(sim->enable_mhd) {
145 &p, hin, hout_orb, tol_orb, &sim->B_data, &sim->E_data,
146 &sim->boozer_data, &sim->mhd_data, sim->enable_aldforce);
147 }
148 else {
150 &p, hin, hout_orb, tol_orb, &sim->B_data, &sim->E_data,
151 sim->enable_aldforce);
152 }
153 /* Check whether time step was rejected */
154 #pragma omp simd
155 for(int i = 0; i < NSIMD; i++) {
156 /* Switch sign of the time-step again if it was reverted earlier
157 */
158 if(sim->reverse_time) {
159 hout_orb[i] = -hout_orb[i];
160 hin[i] = -hin[i];
161 }
162 if(p.running[i] && hout_orb[i] < 0){
163 p.running[i] = 0;
164 hnext[i] = hout_orb[i];
165 }
166 }
167 }
168
169 /* Milstein method for collisions */
170 if(sim->enable_clmbcol) {
171 real rnd[5*NSIMD];
172 random_normal_simd(&sim->random_data, 5*NSIMD, rnd);
173 mccc_gc_milstein(&p, hin, hout_col, tol_col, wienarr, &sim->B_data,
174 &sim->plasma_data, &sim->mccc_data, rnd);
175
176 /* Check whether time step was rejected */
177 #pragma omp simd
178 for(int i = 0; i < NSIMD; i++) {
179 if(p.running[i] && hout_col[i] < 0){
180 p.running[i] = 0;
181 hnext[i] = hout_col[i];
182 }
183 }
184 }
185
186 /* Performs the ICRH kick if in resonance. */
187 if(sim->enable_icrh) {
188 rfof_resonance_check_and_kick_gc(
189 &p, hin, hout_rfof, &rfof_mrk, &sim->rfof_data, &sim->B_data);
190
191 /* Check whether time step was rejected */
192 #pragma omp simd
193 for(int i = 0; i < NSIMD; i++) {
194 if(p.running[i] && hout_rfof[i] < 0){
195 p.running[i] = 0;
196 hnext[i] = hout_rfof[i];
197 }
198 }
199 }
200
201 /**********************************************************************/
202
203 cputime = A5_WTIME;
204 #pragma omp simd
205 for(int i = 0; i < NSIMD; i++) {
206 if(p.id[i] > 0 && !p.err[i]) {
207 /* Check other time step limitations */
208 if(hnext[i] > 0) {
209 real dphi = fabs(p0.phi[i]-p.phi[i]) / sim->ada_max_dphi;
210 real drho = fabs(p0.rho[i]-p.rho[i]) / sim->ada_max_drho;
211
212 if(dphi > 1 && dphi > drho) {
213 hnext[i] = -hin[i]/dphi;
214 }
215 else if(drho > 1 && drho > dphi) {
216 hnext[i] = -hin[i]/drho;
217 }
218 }
219
220 /* Retrieve marker states in case time step was rejected */
221 if(hnext[i] < 0) {
222 particle_copy_gc(&p0, i, &p, i);
223 }
224 if(p.running[i]){
225
226 /* Advance time (if time step was accepted) and determine
227 next time step */
228 if(hnext[i] < 0){
229 /* if hnext < 0, you screwed up and had to copy the
230 previous state. Therefore, let us use the suggestion
231 given by the integrator when retaking the failed step.*/
232 hin[i] = -hnext[i];
233 }
234 else {
235 p.time[i] += ( 1.0 - 2.0 * ( sim->reverse_time > 0 ) )
236 * hin[i];
237 p.mileage[i] += hin[i];
238 /* In case the time step was succesful, pick the
239 smallest recommended value for the next step */
240 if(hnext[i] > hout_orb[i]) {
241 /* Use time step suggested by the orbit-following
242 integrator */
243 hnext[i] = hout_orb[i];
244 }
245 if(hnext[i] > hout_col[i]) {
246 /* Use time step suggested by the collision
247 integrator */
248 hnext[i] = hout_col[i];
249 }
250 if(hnext[i] > hout_rfof[i]) {
251 /* Use time step suggested by RFOF */
252 hnext[i] = hout_rfof[i];
253 }
254 if(hnext[i] == 1.0) {
255 /* Time step is unchanged (happens when no physics
256 are enabled) */
257 hnext[i] = hin[i];
258 }
259 hin[i] = hnext[i];
260 if(sim->enable_clmbcol) {
261 /* Clear wiener processes */
262 mccc_wiener_clean(&(wienarr[i]), p.time[i]);
263 }
264 }
265
266 p.cputime[i] += cputime - cputime_last;
267 }
268 }
269 }
270 cputime_last = cputime;
271
272 /* Check possible end conditions */
273 endcond_check_gc(&p, &p0, sim);
274
275 /* Update diagnostics */
276 diag_update_gc(&sim->diag_data, &sim->B_data, &p, &p0);
277
278 /* Update number of running particles */
279 n_running = particle_cycle_gc(pq, &p, &sim->B_data, cycle);
280
281 /* Determine simulation time-step for new particles */
282 #pragma omp simd
283 for(int i = 0; i < NSIMD; i++) {
284 if(cycle[i] > 0) {
285 hin[i] = simulate_gc_adaptive_inidt(sim, &p, i);
286 if(sim->enable_clmbcol) {
287 /* Re-allocate array storing the Wiener processes */
288 mccc_wiener_initialize(&(wienarr[i]), p.time[i]);
289 }
290 if(sim->enable_icrh) {
291 /* Reset icrh (rfof) resonance memory matrix. */
292 rfof_clear_history(&rfof_mrk, i);
293 }
294 }
295 }
296 }
297
298 /* All markers simulated! */
299
300 /* Deallocate rfof structs */
301 if(sim->enable_icrh) {
302 rfof_tear_down(&rfof_mrk);
303 }
304}
305
319 /* Just use some large value if no physics are defined */
321
322 /* Value defined directly by user */
323 if(sim->fix_usrdef_use) {
324 h = sim->fix_usrdef_val;
325 }
326 else {
327 /* Value calculated from gyrotime */
328 if(sim->enable_orbfol) {
329 real Bnorm = math_normc(p->B_r[i], p->B_phi[i], p->B_z[i]);
330 real gyrotime = CONST_2PI /
331 phys_gyrofreq_ppar(p->mass[i], p->charge[i], p->mu[i],
332 p->ppar[i], Bnorm);
333 if(h > gyrotime) {
334 h = gyrotime;
335 }
336 }
337
338 /* Value calculated from collision frequency */
339 if(sim->enable_clmbcol) {
340 real nu = 1;
341 /*mccc_collfreq_gc(p, &sim->B_data, &sim->plasma_data,
342 sim->coldata, &nu, i); */
343
344 /* Only small angle collisions so divide this by 100 */
345 real colltime = 1/(100*nu);
346 if(h > colltime) {h=colltime;}
347 }
348 }
349 return h;
350}
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
#define __memalign__
Definition ascot5.h:76
Header file for boozer.c.
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:194
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:262
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:70
Header file for mccc package.
void mccc_gc_milstein(particle_simd_gc *p, real *hin, real *hout, real tol, mccc_wienarr *w, B_field_data *Bdata, plasma_data *pdata, mccc_data *mdata, real *rnd)
Integrate collisions for one time-step.
a5err mccc_wiener_clean(mccc_wienarr *w, real t)
Removes Wiener processes from the array that are no longer required.
void mccc_wiener_initialize(mccc_wienarr *w, real initime)
Initializes a struct that stores generated Wiener processes.
Definition mccc_wiener.c:36
header file for mccc_wiener.c
Header file for mhd.c.
void particle_copy_gc(particle_simd_gc *p1, int i, particle_simd_gc *p2, int j)
Copy GC struct.
Definition particle.c:1355
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:367
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:102
Contains the functions to be called from the simulation loop when using ICRH.
Header file for simulate.c.
real simulate_gc_adaptive_inidt(sim_data *sim, particle_simd_gc *p, int i)
Calculates time step value.
void simulate_gc_adaptive(particle_queue *pq, sim_data *sim)
Simulates guiding centers using adaptive time-step.
#define DUMMY_TIMESTEP_VAL
Header file for simulate_gc_adaptive.c.
void step_gc_cashkarp_mhd(particle_simd_gc *p, real *h, real *hnext, real tol, B_field_data *Bdata, E_field_data *Edata, boozer_data *boozer, mhd_data *mhd, int aldforce)
Integrate a guiding center step for a struct of markers with MHD.
void step_gc_cashkarp(particle_simd_gc *p, real *h, real *hnext, real tol, B_field_data *Bdata, E_field_data *Edata, int aldforce)
Integrate a guiding center step for a struct of markers.
Struct for storing Wiener processes.
Definition mccc_wiener.h:28
Marker queue.
Definition particle.h:154
Struct representing NSIMD guiding center markers.
Definition particle.h:275
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
real ada_max_drho
Definition simulate.h:93
real ada_tol_clmbcol
Definition simulate.h:91
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
mccc_data mccc_data
Definition simulate.h:75
random_data random_data
Definition simulate.h:74
boozer_data boozer_data
Definition simulate.h:65
B_field_data B_data
Definition simulate.h:60
int reverse_time
Definition simulate.h:113
real ada_max_dphi
Definition simulate.h:95
int enable_icrh
Definition simulate.h:103
int enable_clmbcol
Definition simulate.h:100
real ada_tol_orbfol
Definition simulate.h:89
diag_data diag_data
Definition simulate.h:69
Header file for wall.c.