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 #pragma omp simd
38 for(int i = 0; i < NSIMD; i++) {
39 if(p->running[i]) {
40 a5err errflag = 0;
41
42 /* Initial (R,z) position and magnetic field are needed for later */
43 real Brpz[3] = {p->B_r[i], p->B_phi[i], p->B_z[i]};
44 real Bnorm = math_norm(Brpz);
45 real Bxyz[3];
46 math_vec_rpz2xyz(Brpz, Bxyz, p->phi[i]);
47 real R0 = p->r[i];
48 real z0 = p->z[i];
49
50 /* Move guiding center to (x, y, z, vnorm, xi) coordinates */
51 real vin, pin, xiin, Xin_xyz[3];
52 pin = physlib_gc_p( p->mass[i], p->mu[i], p->ppar[i], Bnorm);
53 xiin = physlib_gc_xi(p->mass[i], p->mu[i], p->ppar[i], Bnorm);
54 vin = physlib_vnorm_pnorm(p->mass[i], pin);
55 Xin_xyz[0] = p->r[i] * cos(p->phi[i]);
56 Xin_xyz[1] = p->r[i] * sin(p->phi[i]);
57 Xin_xyz[2] = p->z[i];
58
59 /* Evaluate plasma density and temperature */
61 if(!errflag) {
62 errflag = plasma_eval_densandtemp(nb, Tb, p->rho[i],
63 p->r[i], p->phi[i], p->z[i],
64 p->time[i], pdata);
65 }
66
67 /* Coulomb logarithm */
68 real clogab[MAX_SPECIES];
69 mccc_coefs_clog(clogab, p->mass[i], p->charge[i], vin,
70 n_species, mb, qb, nb, Tb);
71
72 /* Evaluate collision coefficients and sum them for each *
73 * species */
74 real gyrofreq = phys_gyrofreq_pnorm(p->mass[i], p->charge[i],
75 pin, Bnorm);
76 real K = 0, Dpara = 0, nu = 0, DX = 0;
77 for(int j = 0; j < n_species; j++) {
78 real vb = sqrt( 2 * Tb[j] / mb[j] );
79 real x = vin / vb;
80 real mufun[3];
81 mccc_coefs_mufun(mufun, x, mdata); // eq. 2.83 PhD Hirvijoki
82
83 real Qb = mccc_coefs_Q(p->mass[i], p->charge[i], mb[j],
84 qb[j], nb[j], vb, clogab[j],
85 mufun[0]);
86 real Dparab = mccc_coefs_Dpara(p->mass[i], p->charge[i], vin,
87 qb[j], nb[j], vb, clogab[j],
88 mufun[0]);
89 real Dperpb = mccc_coefs_Dperp(p->mass[i], p->charge[i], vin,
90 qb[j], nb[j], vb, clogab[j],
91 mufun[1]);
92 real dDparab = mccc_coefs_dDpara(p->mass[i], p->charge[i], vin,
93 qb[j], nb[j], vb, clogab[j],
94 mufun[0], mufun[2]);
95
96 K += mccc_coefs_K(vin, Dparab, dDparab, Qb);
97 Dpara += Dparab;
98 nu += mccc_coefs_nu(vin, Dperpb); // eq.41
99 DX += mccc_coefs_DX(xiin, Dparab, Dperpb, gyrofreq);
100 }
101
102 /* Evaluate collisions */
103 real sdt = sqrt(h[i]);
104 real dW[5];
105 dW[0]=sdt*rnd[0*NSIMD + i]; // For X_1
106 dW[1]=sdt*rnd[1*NSIMD + i]; // For X_2
107 dW[2]=sdt*rnd[2*NSIMD + i]; // For X_3
108 dW[3]=sdt*rnd[3*NSIMD + i]; // For v
109 dW[4]=sdt*rnd[4*NSIMD + i]; // For xi
110
111 real bhat[3];
112 math_unit(Bxyz, bhat);
113
114 real k1 = sqrt(2*DX);
115 real k2 = math_dot(bhat, dW);
116
117 real vout, xiout, Xout_xyz[3];
118 Xout_xyz[0] = Xin_xyz[0] + k1 * ( dW[0] - k2 * bhat[0] );
119 Xout_xyz[1] = Xin_xyz[1] + k1 * ( dW[1] - k2 * bhat[1] );
120 Xout_xyz[2] = Xin_xyz[2] + k1 * ( dW[2] - k2 * bhat[2] );
121 vout = vin + K*h[i] + sqrt( 2 * Dpara ) * dW[3];
122 xiout = xiin - xiin*nu*h[i] + sqrt(( 1 - xiin*xiin ) * nu) * dW[4];
123
124 /* Enforce boundary conditions */
125 real cutoff = MCCC_CUTOFF * sqrt( Tb[0] / p->mass[i] );
126 if(vout < cutoff){
127 vout = 2 * cutoff - vout;
128 }
129
130 if(fabs(xiout) > 1){
131 xiout = ( (xiout > 0) - (xiout < 0) )
132 * ( 2 - fabs( xiout ) );
133 }
134
135 /* Remove energy or pitch change or spatial diffusion from the *
136 * results if that is requested */
137 if(!mdata->include_energy) {
138 vout = vin;
139 }
140 if(!mdata->include_pitch) {
141 xiout = xiin;
142 }
143 if(!mdata->include_gcdiff) {
144 Xout_xyz[0] = Xin_xyz[0];
145 Xout_xyz[1] = Xin_xyz[1];
146 Xout_xyz[2] = Xin_xyz[2];
147 }
148 real pout = physlib_pnorm_vnorm(p->mass[i], vout);
149
150 /* Back to cylindrical coordinates */
151 real Xout_rpz[3];
152 math_xyz2rpz(Xout_xyz, Xout_rpz);
153
154 /* Evaluate magnetic field (and gradient) and rho at new position */
155 real B_dB[15], psi[1], rho[2];
156 if(!errflag) {
157 errflag = B_field_eval_B_dB(B_dB, Xout_rpz[0], Xout_rpz[1],
158 Xout_rpz[2], p->time[i] + h[i],
159 Bdata);
160 }
161 if(!errflag) {
162 errflag = B_field_eval_psi(psi, Xout_rpz[0], Xout_rpz[1],
163 Xout_rpz[2], p->time[i] + h[i],
164 Bdata);
165 }
166 if(!errflag) {
167 errflag = B_field_eval_rho(rho, psi[0], Bdata);
168 }
169
170 if(!errflag) {
171 /* Update marker coordinates at the new position */
172 p->B_r[i] = B_dB[0];
173 p->B_r_dr[i] = B_dB[1];
174 p->B_r_dphi[i] = B_dB[2];
175 p->B_r_dz[i] = B_dB[3];
176
177 p->B_phi[i] = B_dB[4];
178 p->B_phi_dr[i] = B_dB[5];
179 p->B_phi_dphi[i] = B_dB[6];
180 p->B_phi_dz[i] = B_dB[7];
181
182 p->B_z[i] = B_dB[8];
183 p->B_z_dr[i] = B_dB[9];
184 p->B_z_dphi[i] = B_dB[10];
185 p->B_z_dz[i] = B_dB[11];
186
187 p->rho[i] = rho[0];
188
189 Bnorm = math_normc(B_dB[0], B_dB[4], B_dB[8]);
190
191 p->r[i] = Xout_rpz[0];
192 p->z[i] = Xout_rpz[2];
193 p->ppar[i] = physlib_gc_ppar(pout, xiout);
194 p->mu[i] = physlib_gc_mu(p->mass[i], pout, xiout, Bnorm);
195
196 /* Evaluate phi and theta angles so that they are cumulative */
197 real axisrz[2];
198 errflag = B_field_get_axis_rz(axisrz, Bdata, p->phi[i]);
199 p->theta[i] += atan2( (R0-axisrz[0]) * (p->z[i]-axisrz[1])
200 - (z0-axisrz[1]) * (p->r[i]-axisrz[0]),
201 (R0-axisrz[0]) * (p->r[i]-axisrz[0])
202 + (z0-axisrz[1]) * (p->z[i]-axisrz[1]) );
203 p->phi[i] += atan2( Xin_xyz[0] * Xout_xyz[1]
204 - Xin_xyz[1] * Xout_xyz[0],
205 Xin_xyz[0] * Xout_xyz[0]
206 + Xin_xyz[1] * Xout_xyz[1] );
207 }
208
209 /* Error handling */
210 if(errflag) {
211 p->err[i] = errflag;
212 p->running[i] = 0;
213 }
214 }
215 }
216}
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:327
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:201
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:547
a5err B_field_get_axis_rz(real rz[2], B_field_data *Bdata, real phi)
Return magnetic axis Rz-coordinates.
Definition B_field.c:599
Header file for B_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 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:28
#define math_unit(a, b)
Calculate unit vector b from a 3D vector a.
Definition math.h:70
#define math_xyz2rpz(xyz, rpz)
Convert cartesian coordinates xyz to cylindrical coordinates rpz.
Definition math.h:74
#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:83
#define math_normc(a1, a2, a3)
Calculate norm of 3D vector from its components a1, a2, a3.
Definition math.h:67
#define math_norm(a)
Calculate norm of 3D vector a.
Definition math.h:64
Header file for mccc package.
#define MCCC_CUTOFF
Defines minimum energy boundary condition.
Definition mccc.h:22
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
static void mccc_coefs_mufun(real mufun[3], real x, mccc_data *mdata)
Evaluate special functions needed by collision coefficients.
Definition mccc_coefs.h:275
#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
static DECLARE_TARGET_END void mccc_coefs_clog(real *clogab, real ma, real qa, real va, int nspec, const real *mb, const real *qb, const real *nb, const real *Tb)
Evaluate Coulomb logarithm.
Definition mccc_coefs.h:228
#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
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.
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:210
#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:257
#define physlib_gc_ppar(p, xi)
Evaluate guiding center parallel momentum [kg m/s] from momentum norm and pitch.
Definition physlib.h:166
#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:195
#define physlib_gc_mu(m, p, xi, B)
Evaluate guiding center magnetic moment [J/T] from momentum norm and pitch.
Definition physlib.h:180
const real * plasma_get_species_mass(plasma_data *pls_data)
Get mass of all plasma species.
Definition plasma.c:361
int plasma_get_n_species(plasma_data *pls_data)
Get the number of plasma species.
Definition plasma.c:331
const real * plasma_get_species_charge(plasma_data *pls_data)
Get charge of all plasma species.
Definition plasma.c:391
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:280
Header file for plasma.c.
Header file for random.c.
Magnetic field simulation data.
Definition B_field.h:63
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
Plasma simulation data.
Definition plasma.h:57