ASCOT5
Loading...
Searching...
No Matches
mccc_gc_euler.c
Go to the documentation of this file.
1
5#include <math.h>
6#include "../../ascot5.h"
7#include "../../consts.h"
8#include "../../math.h"
9#include "../../physlib.h"
10#include "../../error.h"
11#include "../../particle.h"
12#include "../../B_field.h"
13#include "../../plasma.h"
14#include "../../random.h"
15#include "mccc_coefs.h"
16#include "mccc.h"
17
30 plasma_data* pdata, mccc_data* mdata, real* rnd) {
31
32 /* Get plasma information before going to the SIMD loop */
33 int n_species = plasma_get_n_species(pdata);
34 const real* qb = plasma_get_species_charge(pdata);
35 const real* mb = plasma_get_species_mass(pdata);
36
37 GPU_DATA_IS_MAPPED(h[0:p->n_mrk], rnd[0:3*p->n_mrk])
38 GPU_PARALLEL_LOOP_ALL_LEVELS
39 for(int i = 0; i < p->n_mrk; i++) {
40 if(p->running[i]) {
41 a5err errflag = 0;
42
43 /* Initial (R,z) position and magnetic field are needed for later */
44 real Brpz[3] = {p->B_r[i], p->B_phi[i], p->B_z[i]};
45 real Bnorm = math_norm(Brpz);
46 real Bxyz[3];
47 math_vec_rpz2xyz(Brpz, Bxyz, p->phi[i]);
48 real R0 = p->r[i];
49 real z0 = p->z[i];
50
51 /* Move guiding center to (x, y, z, vnorm, xi) coordinates */
52 real vin, pin, vflow, vpar, vperp2, xiin, Xin_xyz[3];
53 Xin_xyz[0] = p->r[i] * cos(p->phi[i]);
54 Xin_xyz[1] = p->r[i] * sin(p->phi[i]);
55 Xin_xyz[2] = p->z[i];
56 if(!errflag) {
57 errflag = plasma_eval_flow(
58 &vflow, p->rho[i], p->r[i], p->phi[i], p->z[i], p->time[i],
59 pdata);
60 }
61 pin = physlib_gc_p(p->mass[i], p->mu[i], p->ppar[i], Bnorm);
62 xiin = physlib_gc_xi(p->mass[i], p->mu[i], p->ppar[i], Bnorm);
63 vin = physlib_vnorm_pnorm(p->mass[i], pin);
64 vpar = xiin * vin;
65 vperp2 = (1 - xiin * xiin) * vin * vin;
66 vin = sqrt((vpar - vflow) * (vpar - vflow) + vperp2);
67 xiin = (vpar - vflow) / vin;
68
69 /* Evaluate plasma density and temperature */
71 if(!errflag) {
72 errflag = plasma_eval_densandtemp(nb, Tb, p->rho[i],
73 p->r[i], p->phi[i], p->z[i],
74 p->time[i], pdata);
75 }
76
77 /* Coulomb logarithm */
78 real clogab[MAX_SPECIES];
79 mccc_coefs_clog(clogab, p->mass[i], p->charge[i], vin,
80 n_species, mb, qb, nb, Tb);
81
82 /* Evaluate collision coefficients and sum them for each *
83 * species */
84 real gyrofreq = phys_gyrofreq_pnorm(p->mass[i], p->charge[i],
85 pin, Bnorm);
86 real K = 0, Dpara = 0, nu = 0, DX = 0;
87 GPU_SEQUENTIAL_LOOP
88 for(int j = 0; j < n_species; j++) {
89 real vb = sqrt( 2 * Tb[j] / mb[j] );
90 real x = vin / vb;
91 real mufun[3];
92 mccc_coefs_mufun(mufun, x, mdata); // eq. 2.83 PhD Hirvijoki
93
94 real Qb = mccc_coefs_Q(p->mass[i], p->charge[i], mb[j],
95 qb[j], nb[j], vb, clogab[j],
96 mufun[0]);
97 real Dparab = mccc_coefs_Dpara(p->mass[i], p->charge[i], vin,
98 qb[j], nb[j], vb, clogab[j],
99 mufun[0]);
100 real Dperpb = mccc_coefs_Dperp(p->mass[i], p->charge[i], vin,
101 qb[j], nb[j], vb, clogab[j],
102 mufun[1]);
103 real dDparab = mccc_coefs_dDpara(p->mass[i], p->charge[i], vin,
104 qb[j], nb[j], vb, clogab[j],
105 mufun[0], mufun[2]);
106
107 K += mccc_coefs_K(vin, Dparab, dDparab, Qb);
108 Dpara += Dparab;
109 nu += mccc_coefs_nu(vin, Dperpb); // eq.41
110 DX += mccc_coefs_DX(xiin, Dparab, Dperpb, gyrofreq);
111 }
112
113 /* Evaluate collisions */
114 real sdt = sqrt(h[i]);
115 real dW[5];
116 dW[0]=sdt*rnd[0*p->n_mrk + i]; // For X_1
117 dW[1]=sdt*rnd[1*p->n_mrk + i]; // For X_2
118 dW[2]=sdt*rnd[2*p->n_mrk + i]; // For X_3
119 dW[3]=sdt*rnd[3*p->n_mrk + i]; // For v
120 dW[4]=sdt*rnd[4*p->n_mrk + i]; // For xi
121
122 real bhat[3];
123 math_unit(Bxyz, bhat);
124
125 real k1 = sqrt(2*DX);
126 real k2 = math_dot(bhat, dW);
127
128 real vout, xiout, Xout_xyz[3];
129 Xout_xyz[0] = Xin_xyz[0] + k1 * ( dW[0] - k2 * bhat[0] );
130 Xout_xyz[1] = Xin_xyz[1] + k1 * ( dW[1] - k2 * bhat[1] );
131 Xout_xyz[2] = Xin_xyz[2] + k1 * ( dW[2] - k2 * bhat[2] );
132 vout = vin + K*h[i] + sqrt( 2 * Dpara ) * dW[3];
133 xiout = xiin - xiin*nu*h[i] + sqrt(( 1 - xiin*xiin ) * nu) * dW[4];
134
135 /* Enforce boundary conditions */
136 real cutoff = MCCC_CUTOFF * sqrt( Tb[0] / p->mass[i] );
137 if(vout < cutoff){
138 vout = 2 * cutoff - vout;
139 }
140
141 if(fabs(xiout) > 1){
142 xiout = ( (xiout > 0) - (xiout < 0) )
143 * ( 2 - fabs( xiout ) );
144 }
145
146 /* Remove energy or pitch change or spatial diffusion from the *
147 * results if that is requested */
148 if(!mdata->include_energy) {
149 vout = vin;
150 }
151 if(!mdata->include_pitch) {
152 xiout = xiin;
153 }
154 if(!mdata->include_gcdiff) {
155 Xout_xyz[0] = Xin_xyz[0];
156 Xout_xyz[1] = Xin_xyz[1];
157 Xout_xyz[2] = Xin_xyz[2];
158 }
159 vpar = xiout * vout;
160 vperp2 = (1 - xiout * xiout) * vout * vout;
161 vout = sqrt((vpar + vflow) * (vpar + vflow) + vperp2);
162 xiout = (vpar + vflow) / vout;
163 real pout = physlib_pnorm_vnorm(p->mass[i], vout);
164
165 /* Back to cylindrical coordinates */
166 real Xout_rpz[3];
167 math_xyz2rpz(Xout_xyz, Xout_rpz);
168
169 /* Evaluate magnetic field (and gradient) and rho at new position */
170 real B_dB[15], psi[1], rho[2];
171 if(!errflag) {
172 errflag = B_field_eval_B_dB(B_dB, Xout_rpz[0], Xout_rpz[1],
173 Xout_rpz[2], p->time[i] + h[i],
174 Bdata);
175 }
176 if(!errflag) {
177 errflag = B_field_eval_psi(psi, Xout_rpz[0], Xout_rpz[1],
178 Xout_rpz[2], p->time[i] + h[i],
179 Bdata);
180 }
181 if(!errflag) {
182 errflag = B_field_eval_rho(rho, psi[0], Bdata);
183 }
184
185 if(!errflag) {
186 /* Update marker coordinates at the new position */
187 p->B_r[i] = B_dB[0];
188 p->B_r_dr[i] = B_dB[1];
189 p->B_r_dphi[i] = B_dB[2];
190 p->B_r_dz[i] = B_dB[3];
191
192 p->B_phi[i] = B_dB[4];
193 p->B_phi_dr[i] = B_dB[5];
194 p->B_phi_dphi[i] = B_dB[6];
195 p->B_phi_dz[i] = B_dB[7];
196
197 p->B_z[i] = B_dB[8];
198 p->B_z_dr[i] = B_dB[9];
199 p->B_z_dphi[i] = B_dB[10];
200 p->B_z_dz[i] = B_dB[11];
201
202 p->rho[i] = rho[0];
203
204 Bnorm = math_normc(B_dB[0], B_dB[4], B_dB[8]);
205
206 p->r[i] = Xout_rpz[0];
207 p->z[i] = Xout_rpz[2];
208 p->mu[i] = physlib_gc_mu(p->mass[i], pout, xiout, Bnorm);
209 p->ppar[i] = physlib_gc_ppar(pout, xiout);
210
211 /* Evaluate phi and theta angles so that they are cumulative */
212 real axisrz[2];
213 errflag = B_field_get_axis_rz(axisrz, Bdata, p->phi[i]);
214 p->theta[i] += atan2( (R0-axisrz[0]) * (p->z[i]-axisrz[1])
215 - (z0-axisrz[1]) * (p->r[i]-axisrz[0]),
216 (R0-axisrz[0]) * (p->r[i]-axisrz[0])
217 + (z0-axisrz[1]) * (p->z[i]-axisrz[1]) );
218 p->phi[i] += atan2( Xin_xyz[0] * Xout_xyz[1]
219 - Xin_xyz[1] * Xout_xyz[0],
220 Xin_xyz[0] * Xout_xyz[0]
221 + Xin_xyz[1] * Xout_xyz[1] );
222 }
223
224 /* Error handling */
225 if(errflag) {
226 p->err[i] = errflag;
227 p->running[i] = 0;
228 }
229 }
230 }
231}
a5err B_field_eval_rho(real rho[2], real psi, B_field_data *Bdata)
Evaluate normalized poloidal flux rho and its psi derivative.
Definition B_field.c:228
a5err B_field_eval_psi(real *psi, real r, real phi, real z, real t, B_field_data *Bdata)
Evaluate poloidal flux psi.
Definition B_field.c:102
a5err B_field_eval_B_dB(real B_dB[15], real r, real phi, real z, real t, B_field_data *Bdata)
Evaluate magnetic field and its derivatives.
Definition B_field.c:449
a5err B_field_get_axis_rz(real rz[2], B_field_data *Bdata, real phi)
Return magnetic axis Rz-coordinates.
Definition B_field.c:501
Header file for B_field.c.
Main header file for ASCOT5.
double real
Definition ascot5.h:85
#define MAX_SPECIES
Maximum number of plasma species.
Definition ascot5.h:95
Header file containing physical and mathematical constants.
Error module for ASCOT5.
unsigned long int a5err
Simulation error flag.
Definition error.h:17
Header file for math.c.
#define math_dot(a, b)
Calculate dot product a[3] dot b[3].
Definition math.h:32
#define math_unit(a, b)
Calculate unit vector b from a 3D vector a.
Definition math.h:74
#define math_xyz2rpz(xyz, rpz)
Convert cartesian coordinates xyz to cylindrical coordinates rpz.
Definition math.h:78
#define math_vec_rpz2xyz(vrpz, vxyz, phi)
Transform vector from cylindrical to cartesian basis: vrpz -> vxyz, phi is the toroidal angle in radi...
Definition math.h:87
#define math_normc(a1, a2, a3)
Calculate norm of 3D vector from its components a1, a2, a3.
Definition math.h:71
#define math_norm(a)
Calculate norm of 3D vector a.
Definition math.h:68
Header file for mccc package.
#define MCCC_CUTOFF
Defines minimum energy boundary condition.
Definition mccc.h:22
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.
Routines to evaluate coefficients needed to evaluate collisions.
#define mccc_coefs_Dpara(ma, qa, va, qb, nb, vb, clogab, mu0)
Evaluate non-relativistic parallel diffusion coefficient [m^2/s^3].
Definition mccc_coefs.h:103
#define mccc_coefs_dDpara(ma, qa, va, qb, nb, vb, clogab, mu0, dmu0)
Evaluate derivative of non-relativistic parallel diffusion coefficient [m/s^2].
Definition mccc_coefs.h:126
#define mccc_coefs_K(va, Dpara, dDpara, Q)
Evaluate guiding center drag coefficient [m/s^2].
Definition mccc_coefs.h:167
#define mccc_coefs_Dperp(ma, qa, va, qb, nb, vb, clogab, mu1)
Evaluate non-relativistic perpendicular diffusion coefficient [m^2/s^3].
Definition mccc_coefs.h:150
#define mccc_coefs_nu(va, Dperp)
Evaluate pitch collision frequency [1/s].
Definition mccc_coefs.h:180
#define mccc_coefs_DX(xi, Dpara, Dperp, gyrofreq)
Evaluate spatial diffusion coefficient [m^2/s].
Definition mccc_coefs.h:195
#define mccc_coefs_Q(ma, qa, mb, qb, nb, vb, clogab, mu0)
Evaluate non-relativistic drag coefficient [m/s^2].
Definition mccc_coefs.h:43
Header file for particle.c.
Methods to evaluate elementary physical quantities.
#define physlib_gc_xi(m, mu, ppar, B)
Evaluate guiding center pitch from parallel momentum and magnetic moment.
Definition physlib.h:214
#define physlib_pnorm_vnorm(m, v)
Evaluate momentum norm [kg m/s] from velocity norm.
Definition physlib.h:154
#define physlib_vnorm_pnorm(m, p)
Evaluate velocity norm [m/s] from momentum norm.
Definition physlib.h:141
#define phys_gyrofreq_pnorm(m, q, p, B)
Evaluate gyrofrequency [rad/s] from momentum norm.
Definition physlib.h:261
#define physlib_gc_ppar(p, xi)
Evaluate guiding center parallel momentum [kg m/s] from momentum norm and pitch.
Definition physlib.h:167
#define physlib_gc_p(m, mu, ppar, B)
Evaluate guiding center momentum norm [kg m/s] from parallel momentum and magnetic moment.
Definition physlib.h:198
#define physlib_gc_mu(m, p, xi, B)
Evaluate guiding center magnetic moment [J/T] from momentum norm and pitch.
Definition physlib.h:182
const real * plasma_get_species_mass(plasma_data *pls_data)
Get mass of all plasma species.
Definition plasma.c:345
int plasma_get_n_species(plasma_data *pls_data)
Get the number of plasma species.
Definition plasma.c:311
a5err plasma_eval_flow(real *vflow, real rho, real r, real phi, real z, real t, plasma_data *pls_data)
Evalate plasma flow along the field lines.
Definition plasma.c:258
const real * plasma_get_species_charge(plasma_data *pls_data)
Get charge of all plasma species.
Definition plasma.c:379
a5err plasma_eval_densandtemp(real *dens, real *temp, real rho, real r, real phi, real z, real t, plasma_data *pls_data)
Evaluate plasma density and temperature for all species.
Definition plasma.c:204
Header file for plasma.c.
Header file for random.c.
Magnetic field simulation data.
Definition B_field.h:41
Parameters and data required to evaluate Coulomb collisions.
Definition mccc.h:27
int include_pitch
Definition mccc.h:30
int include_gcdiff
Definition mccc.h:31
int include_energy
Definition mccc.h:29
Struct representing NSIMD guiding center markers.
Definition particle.h:275
integer * running
Definition particle.h:320
real * B_phi_dphi
Definition particle.h:299
Plasma simulation data.
Definition plasma.h:34