ASCOT5
Loading...
Searching...
No Matches
nbi.c
Go to the documentation of this file.
1
5#include <stdlib.h>
6#include <math.h>
7#include "print.h"
8#include "ascot5.h"
9#include "consts.h"
10#include "physlib.h"
11#include "math.h"
12#include "random.h"
13#include "nbi.h"
14
22int nbi_init(nbi_data* data, int ninj, int* id, int* anum, int* znum,
23 real* mass, real* power, real* efrac, real* energy,
24 real* div_h, real* div_v, real* div_halo_v, real* div_halo_h,
25 real* div_halo_frac, int* nbeamlet, real* beamlet_xyz) {
26 int idx = 0;
27 data->ninj =ninj;
28 data->inj = (nbi_injector*) malloc( ninj*sizeof(nbi_injector) );
29 for(int i=0; i<data->ninj; i++) {
30 data->inj[i].anum = anum[i];
31 data->inj[i].znum = znum[i];
32 data->inj[i].mass = mass[i];
33 data->inj[i].power = power[i];
34 data->inj[i].energy = energy[i];
35 data->inj[i].efrac[0] = efrac[3*i+0];
36 data->inj[i].efrac[1] = efrac[3*i+1];
37 data->inj[i].efrac[2] = efrac[3*i+2];
38 data->inj[i].div_h = div_h[i];
39 data->inj[i].div_v = div_v[i];
40 data->inj[i].div_halo_frac = div_halo_frac[i];
41 data->inj[i].div_halo_h = div_halo_h[i];
42 data->inj[i].div_halo_v = div_halo_v[i];
43 data->inj[i].id = id[i];
44 data->inj[i].n_beamlet = nbeamlet[i];
45
46 int n_beamlet = data->inj[i].n_beamlet;
47 data->inj[i].beamlet_x = (real*) malloc( n_beamlet*sizeof(real) );
48 data->inj[i].beamlet_y = (real*) malloc( n_beamlet*sizeof(real) );
49 data->inj[i].beamlet_z = (real*) malloc( n_beamlet*sizeof(real) );
50 data->inj[i].beamlet_dx = (real*) malloc( n_beamlet*sizeof(real) );
51 data->inj[i].beamlet_dy = (real*) malloc( n_beamlet*sizeof(real) );
52 data->inj[i].beamlet_dz = (real*) malloc( n_beamlet*sizeof(real) );
53 for(int j = 0; j < n_beamlet; j++) {
54 data->inj[i].beamlet_x[j] = beamlet_xyz[idx + 0*n_beamlet + j];
55 data->inj[i].beamlet_y[j] = beamlet_xyz[idx + 1*n_beamlet + j];
56 data->inj[i].beamlet_z[j] = beamlet_xyz[idx + 2*n_beamlet + j];
57 data->inj[i].beamlet_dx[j] = beamlet_xyz[idx + 3*n_beamlet + j];
58 data->inj[i].beamlet_dy[j] = beamlet_xyz[idx + 4*n_beamlet + j];
59 data->inj[i].beamlet_dz[j] = beamlet_xyz[idx + 5*n_beamlet + j];
60 }
61 idx += 6 * n_beamlet;
62 }
63
64 int err = 0;
65 print_out(VERBOSE_IO, "\nNBI input\n");
66 print_out(VERBOSE_IO, "Number of injectors %d:\n", data->ninj);
67 for(int i=0; i < data->ninj; i++) {
68 print_out(VERBOSE_IO, "\n Injector ID %d (%d beamlets) Power: %1.1e\n",
69 data->inj[i].id, data->inj[i].n_beamlet,
70 data->inj[i].power);
72 " Anum %d Znum %d mass %1.1e amu energy %1.1e eV\n",
73 data->inj[i].anum, data->inj[i].znum,
74 data->inj[i].mass / CONST_U, data->inj[i].energy / CONST_E);
76 " Energy fractions: %1.1e (Full) %1.1e (1/2) %1.1e (1/3)\n",
77 data->inj[i].efrac[0], data->inj[i].efrac[1],
78 data->inj[i].efrac[2]);
79
80 /* Even if halo fraction is zero, the divergences should be nonzero
81 to avoid division by zero during evaluation. Do this after the
82 input has been printed as to not confuse the user */
83 if(data->inj[i].div_halo_frac == 0) {
84 data->inj[i].div_halo_h = 1e-10;
85 data->inj[i].div_halo_v = 1e-10;
86 }
87 }
88 return err;
89}
90
96void nbi_free(nbi_data* data) {
97 for(int i=0; i<data->ninj; i++) {
98 data->inj[i].n_beamlet = 0;
99 free(data->inj[i].beamlet_x);
100 free(data->inj[i].beamlet_y);
101 free(data->inj[i].beamlet_z);
102 free(data->inj[i].beamlet_dx);
103 free(data->inj[i].beamlet_dy);
104 free(data->inj[i].beamlet_dz);
105 }
106 data->ninj = 0;
107 free(data->inj);
108}
109
118void nbi_inject(real* xyz, real* vxyz, nbi_injector* inj, random_data* rng) {
119 /* Pick a random beamlet and initialize marker there */
120 int i_beamlet = floor(random_uniform(rng) * inj->n_beamlet);
121 xyz[0] = inj->beamlet_x[i_beamlet];
122 xyz[1] = inj->beamlet_y[i_beamlet];
123 xyz[2] = inj->beamlet_z[i_beamlet];
124
125 /* Pick marker energy based on the energy fractions */
126 real energy;
127 real r = random_uniform(rng);
128 if(r < inj->efrac[0]) {
129 energy = inj->energy;
130 } else if(r < inj->efrac[0] + inj->efrac[1]) {
131 energy = inj->energy / 2;
132 } else {
133 energy = inj->energy / 3;
134 }
135
136 /* Calculate vertical and horizontal normals for beam divergence */
137 real dir[3], normalv[3], normalh[3], tmp[3];
138 dir[0] = inj->beamlet_dx[i_beamlet];
139 dir[1] = inj->beamlet_dy[i_beamlet];
140 dir[2] = inj->beamlet_dz[i_beamlet];
141
142 real phi = atan2(dir[1], dir[0]);
143 real theta = acos(dir[2]);
144
145 normalv[0] = sin(theta+CONST_PI/2) * cos(phi);
146 normalv[1] = sin(theta+CONST_PI/2) * sin(phi);
147 normalv[2] = cos(theta+CONST_PI/2);
148
149 math_cross(dir, normalv, tmp);
150 math_unit(tmp, normalh);
151
152 /* Generate a random number on interval [0,1]. If the number is smaller
153 * than the halo fraction, this marker will be considered as part
154 * of the halo. The divergences are different for the core and halo.
155 * Additionally, two normally distributed random variables are generated:
156 * the divergences in horizontal and the vertical directions. */
157 real div_h, div_v;
158 if(random_uniform(rng) < inj->div_halo_frac) {
159 // Use halo divergences instead
160 div_h = inj->div_halo_h * random_normal(rng) / sqrt(2.0);
161 div_v = inj->div_halo_v * random_normal(rng) / sqrt(2.0);
162 } else {
163 div_h = inj->div_h * random_normal(rng) / sqrt(2.0);
164 div_v = inj->div_v * random_normal(rng) / sqrt(2.0);
165 }
166
167 /* Convert the divergence angle to an unit vector. The marker velocity
168 * vector points in the direction of v_beam + v_divergence. */
169 tmp[0] = cos(div_h) * ( cos(div_v) * dir[0] + sin(div_v) * normalv[0] )
170 + sin(div_h) * normalh[0];
171 tmp[1] = cos(div_h) * ( cos(div_v) * dir[1] + sin(div_v) * normalv[1] )
172 + sin(div_h) * normalh[1];
173 tmp[2] = cos(div_h) * ( cos(div_v) * dir[2] + sin(div_v) * normalv[2] )
174 + sin(div_h) * normalh[2];
175 math_unit(tmp, dir);
176
177 real gamma = physlib_gamma_Ekin(inj->mass, energy);
178 real absv = sqrt( 1.0 - 1.0 / (gamma * gamma) ) * CONST_C;
179 vxyz[0] = absv * dir[0];
180 vxyz[1] = absv * dir[1];
181 vxyz[2] = absv * dir[2];
182}
Main header file for ASCOT5.
double real
Definition ascot5.h:85
Header file containing physical and mathematical constants.
#define CONST_U
Atomic mass unit in kilograms [kg]
Definition consts.h:29
#define CONST_PI
pi
Definition consts.h:11
#define CONST_C
Speed of light [m/s]
Definition consts.h:23
#define CONST_E
Elementary charge [C]
Definition consts.h:32
Header file for math.c.
#define math_unit(a, b)
Calculate unit vector b from a 3D vector a.
Definition math.h:70
#define math_cross(a, b, c)
Calculate cross product for 3D vectors c = a x b.
Definition math.h:31
int nbi_init(nbi_data *data, int ninj, int *id, int *anum, int *znum, real *mass, real *power, real *efrac, real *energy, real *div_h, real *div_v, real *div_halo_v, real *div_halo_h, real *div_halo_frac, int *nbeamlet, real *beamlet_xyz)
Initialize NBI data struct on target.
Definition nbi.c:22
void nbi_free(nbi_data *data)
Free allocated resources.
Definition nbi.c:96
void nbi_inject(real *xyz, real *vxyz, nbi_injector *inj, random_data *rng)
Sample injected marker's coordinates.
Definition nbi.c:118
Header file for nbi.c.
Methods to evaluate elementary physical quantities.
#define physlib_gamma_Ekin(m, ekin)
Evaluate Lorentz factor from kinetic energy [J].
Definition physlib.h:103
Macros for printing console output.
#define print_out(v,...)
Print to standard output.
Definition print.h:31
@ VERBOSE_IO
Definition print.h:20
Header file for random.c.
void * random_data
Definition random.h:87
#define random_uniform(data)
Definition random.h:96
#define random_normal(data)
Definition random.h:98
NBI data consisting of ninj injectors.
Definition nbi.h:40
int ninj
Definition nbi.h:41
nbi_injector * inj
Definition nbi.h:42
Structure for describing an NBI injector.
Definition nbi.h:15
real mass
Definition nbi.h:34
int id
Definition nbi.h:16
real efrac[3]
Definition nbi.h:26
real * beamlet_x
Definition nbi.h:18
int anum
Definition nbi.h:32
real * beamlet_dy
Definition nbi.h:22
real energy
Definition nbi.h:25
real div_halo_h
Definition nbi.h:30
real power
Definition nbi.h:24
real * beamlet_y
Definition nbi.h:19
int znum
Definition nbi.h:33
real * beamlet_dz
Definition nbi.h:23
real div_halo_frac
Definition nbi.h:29
real * beamlet_dx
Definition nbi.h:21
real * beamlet_z
Definition nbi.h:20
int n_beamlet
Definition nbi.h:17
real div_halo_v
Definition nbi.h:31
real div_v
Definition nbi.h:28
real div_h
Definition nbi.h:27