ASCOT5
Loading...
Searching...
No Matches
mhd_stat.c
Go to the documentation of this file.
1
5#include <stdlib.h>
6#include "../ascot5.h"
7#include "../print.h"
8#include "../error.h"
9#include "../boozer.h"
10#include "../spline/interp.h"
11#include "../B_field.h"
12#include "../math.h"
13#include "../mhd.h"
14#include "mhd_stat.h"
15
23int mhd_stat_init(mhd_stat_data* data, int nmode, int nrho,
24 real rhomin, real rhomax, int* moden, int* modem,
25 real* amplitude_nm, real* omega_nm, real* phase_nm,
26 real* alpha, real* phi) {
27
28 int err = 0;
29 data->n_modes = nmode;
30 data->rho_min = rhomin;
31 data->rho_max = rhomax;
32 data->nmode = (int*) malloc(nmode * sizeof(int));
33 data->mmode = (int*) malloc(nmode * sizeof(int));
34 data->omega_nm = (real*) malloc(nmode * sizeof(real));
35 data->phase_nm = (real*) malloc(nmode * sizeof(real));
36 data->amplitude_nm = (real*) malloc(nmode * sizeof(real));
37 data->phi_nm = (interp1D_data*) malloc(nmode * sizeof(interp1D_data));
38 data->alpha_nm = (interp1D_data*) malloc(nmode * sizeof(interp1D_data));
39 for(int i = 0; i < nmode; i++) {
40 data->nmode[i] = moden[i];
41 data->mmode[i] = modem[i];
42 data->omega_nm[i] = omega_nm[i];
43 data->phase_nm[i] = phase_nm[i];
44 data->amplitude_nm[i] = amplitude_nm[i];
45
46 err = interp1Dcomp_setup(&data->alpha_nm[i], &alpha[i*nrho],
47 nrho, NATURALBC, rhomin, rhomax);
48 if(err) {
49 print_err("Error: Failed to initialize splines.\n");
50 return err;
51 }
52 err = interp1Dcomp_setup(&data->phi_nm[i], &phi[i*nrho],
53 nrho, NATURALBC, rhomin, rhomax);
54 if(err) {
55 print_err("Error: Failed to initialize splines.\n");
56 return err;
57 }
58 }
59
60 /* Print some sanity check on data */
61 print_out(VERBOSE_IO, "\nMHD (stationary) input\n");
62 print_out(VERBOSE_IO, "Grid: nrho = %4.d rhomin = %3.3f rhomax = %3.3f\n",
63 nrho, data->rho_min, data->rho_max);
64
65 print_out(VERBOSE_IO, "\nModes:\n");
66 for(int i = 0; i < nmode; i++) {
68 "(n,m) = (%2.d,%2.d) Amplitude = %3.3g Frequency = %3.3g"
69 " Phase = %3.3g\n",
70 data->nmode[i], data->mmode[i], data->amplitude_nm[i],
71 data->omega_nm[i], data->phase_nm[i]);
72 }
73
74 return err;
75}
76
83 for(int i = 0; i < data->n_modes; i++) {
84 free(data->phi_nm[i].c);
85 free(data->alpha_nm[i].c);
86 }
87 free(data->phi_nm);
88 free(data->alpha_nm);
89 free(data->nmode);
90 free(data->mmode);
91 free(data->phase_nm);
92 free(data->omega_nm);
93 free(data->amplitude_nm);
94}
95
102 //TODO: Implement
103}
104
135a5err mhd_stat_eval(real mhd_dmhd[10], real r, real phi, real z, real t,
136 int includemode, boozer_data* boozerdata,
137 mhd_stat_data* mhddata, B_field_data* Bdata) {
138
139 a5err err = 0;
140
141 real ptz[12];
142 int isinside;
143 if(!err) {
144 err = boozer_eval_psithetazeta(ptz, &isinside, r, phi, z, Bdata,
145 boozerdata);
146 }
147 real rho[2];
148 if(!err && isinside) {
149 err = B_field_eval_rho(rho, ptz[0], Bdata);
150 }
151
152 /* Initialize values */
153 for(int i=0; i<10; i++) {
154 mhd_dmhd[i] = 0;
155 }
156
157 int interperr = 0;
158 for(int i = 0; i < mhddata->n_modes; i++){
159 if( includemode != MHD_INCLUDE_ALL && includemode != i ) { continue; }
160 /* Get interpolated values */
161 real a_da[3], phi_dphi[3];
162 interperr += interp1Dcomp_eval_df(a_da, &(mhddata->alpha_nm[i]),
163 rho[0]);
164 interperr += interp1Dcomp_eval_df(phi_dphi, &(mhddata->phi_nm[i]),
165 rho[0]);
166
167 /* The interpolation returns dx/drho but we require dx/dpsi.
168 * The second order derivatives are not needed anywhere */
169 a_da[1] *= rho[1];
170 phi_dphi[1] *= rho[1];
171
172 /* These are used frequently, so store them in separate variables */
173 real mhdarg = mhddata->nmode[i] * ptz[8]
174 - mhddata->mmode[i] * ptz[4]
175 - mhddata->omega_nm[i] * t
176 + mhddata->phase_nm[i];
177 real sinmhd = sin(mhdarg);
178 real cosmhd = cos(mhdarg);
179
180 /* Sum over modes to get alpha, phi */
181 mhd_dmhd[0] += a_da[0] * mhddata->amplitude_nm[i] * cosmhd;
182 mhd_dmhd[5] += phi_dphi[0] * mhddata->amplitude_nm[i] * cosmhd;
183
184 /* Time derivatives */
185 mhd_dmhd[1] += a_da[0] * mhddata->amplitude_nm[i]
186 * mhddata->omega_nm[i] * sinmhd;
187 mhd_dmhd[6] += phi_dphi[0] * mhddata->amplitude_nm[i]
188 * mhddata->omega_nm[i] * sinmhd;
189
190 /* R component of gradients */
191 mhd_dmhd[2] += mhddata->amplitude_nm[i]
192 * ( a_da[1] * ptz[1] * cosmhd
193 + a_da[0] * mhddata->mmode[i] * ptz[5] * sinmhd
194 - a_da[0] * mhddata->nmode[i] * ptz[9] * sinmhd);
195 mhd_dmhd[7] += mhddata->amplitude_nm[i]
196 * ( phi_dphi[1] * ptz[1] * cosmhd
197 + phi_dphi[0] * mhddata->mmode[i] * ptz[5] * sinmhd
198 - phi_dphi[0] * mhddata->nmode[i] * ptz[9] * sinmhd);
199
200 /* phi component of gradients */
201 mhd_dmhd[3] += (1/r) * mhddata->amplitude_nm[i]
202 * ( a_da[1] * ptz[2] * cosmhd
203 + a_da[0] * mhddata->mmode[i] * ptz[6] * sinmhd
204 - a_da[0] * mhddata->nmode[i] * ptz[10] * sinmhd);
205 mhd_dmhd[8] += (1/r) * mhddata->amplitude_nm[i]
206 * ( phi_dphi[1] * ptz[2] * cosmhd
207 + phi_dphi[0] * mhddata->mmode[i] * ptz[6] * sinmhd
208 - phi_dphi[0] * mhddata->nmode[i] * ptz[10] * sinmhd);
209
210 /* z component of gradients */
211 mhd_dmhd[4] += mhddata->amplitude_nm[i]
212 * ( a_da[1] * ptz[3] * cosmhd
213 + a_da[0] * mhddata->mmode[i] * ptz[7] * sinmhd
214 - a_da[0] * mhddata->nmode[i] * ptz[11] * sinmhd);
215 mhd_dmhd[9] += mhddata->amplitude_nm[i]
216 * ( phi_dphi[1] * ptz[3] * cosmhd
217 + phi_dphi[0] * mhddata->mmode[i] * ptz[7] * sinmhd
218 - phi_dphi[0] * mhddata->nmode[i] * ptz[11] * sinmhd);
219 }
220
221 /* Omit evaluation if point outside the boozer or mhd grid. */
222 if(!isinside || interperr) {
223 for(int i=0; i<10; i++) {
224 mhd_dmhd[i] = 0;
225 }
226 }
227 return err;
228}
229
261 real t, int pertonly, int includemode,
262 boozer_data* boozerdata, mhd_stat_data* mhddata,
263 B_field_data* Bdata) {
264 a5err err = 0;
265 real mhd_dmhd[10];
266 if(!err) {
267 err = mhd_stat_eval(mhd_dmhd, r, phi, z, t, includemode, boozerdata,
268 mhddata, Bdata);
269 }
270 /* see example of curl evaluation in step_gc_rk4.c, ydot_gc*/
271 real B_dB[15];
272 if(!err) {
273 err = B_field_eval_B_dB(B_dB, r, phi, z, t, Bdata);
274 }
275
276 if(!err) {
277 real B[3];
278 B[0] = B_dB[0];
279 B[1] = B_dB[4];
280 B[2] = B_dB[8];
281
282 real curlB[3];
283 curlB[0] = B_dB[10]/r - B_dB[7];
284 curlB[1] = B_dB[3] - B_dB[9];
285 curlB[2] = (B[1] - B_dB[2])/r + B_dB[5];
286
287 real gradalpha[3];
288 gradalpha[0] = mhd_dmhd[2];
289 gradalpha[1] = mhd_dmhd[3];
290 gradalpha[2] = mhd_dmhd[4];
291
292 real gradalphacrossB[3];
293
294 math_cross(gradalpha, B, gradalphacrossB);
295
296 pert_field[0] = mhd_dmhd[0]*curlB[0] + gradalphacrossB[0];
297 pert_field[1] = mhd_dmhd[0]*curlB[1] + gradalphacrossB[1];
298 pert_field[2] = mhd_dmhd[0]*curlB[2] + gradalphacrossB[2];
299
300 pert_field[3] = -mhd_dmhd[7] - B[0]*mhd_dmhd[1];
301 pert_field[4] = -mhd_dmhd[8] - B[1]*mhd_dmhd[1];
302 pert_field[5] = -mhd_dmhd[9] - B[2]*mhd_dmhd[1];
303 pert_field[6] = mhd_dmhd[5];
304
305 if(!pertonly) {
306 pert_field[0] += B[0];
307 pert_field[1] += B[1];
308 pert_field[2] += B[2];
309 }
310 }
311
312 return err;
313}
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_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
Header file for B_field.c.
Main header file for ASCOT5.
double real
Definition ascot5.h:85
a5err boozer_eval_psithetazeta(real psithetazeta[12], int *isinside, real r, real phi, real z, B_field_data *Bdata, boozer_data *boozerdata)
Evaluate Boozer coordinates and partial derivatives.
Definition boozer.c:124
Header file for boozer.c.
Error module for ASCOT5.
unsigned long int a5err
Simulation error flag.
Definition error.h:17
Spline interpolation library.
@ NATURALBC
Definition interp.h:37
int interp1Dcomp_setup(interp1D_data *str, real *f, int n_x, int bc_x, real x_min, real x_max)
Set up splines to interpolate 1D scalar data.
a5err interp1Dcomp_eval_df(real *f_df, interp1D_data *str, real x)
Evaluate interpolated value of 1D and its 1st and 2nd derivatives.
Header file for math.c.
#define math_cross(a, b, c)
Calculate cross product for 3D vectors c = a x b.
Definition math.h:31
Header file for mhd.c.
#define MHD_INCLUDE_ALL
includemode parameter to include all modes (default)
Definition mhd.h:19
void mhd_stat_offload(mhd_stat_data *data)
Offload data to the accelerator.
Definition mhd_stat.c:101
a5err mhd_stat_perturbations(real pert_field[7], real r, real phi, real z, real t, int pertonly, int includemode, boozer_data *boozerdata, mhd_stat_data *mhddata, B_field_data *Bdata)
Evaluate perturbed fields Btilde, Etilde and potential Phi explicitly.
Definition mhd_stat.c:260
int mhd_stat_init(mhd_stat_data *data, int nmode, int nrho, real rhomin, real rhomax, int *moden, int *modem, real *amplitude_nm, real *omega_nm, real *phase_nm, real *alpha, real *phi)
Load MHD data.
Definition mhd_stat.c:23
a5err mhd_stat_eval(real mhd_dmhd[10], real r, real phi, real z, real t, int includemode, boozer_data *boozerdata, mhd_stat_data *mhddata, B_field_data *Bdata)
Evaluate the needed quantities from MHD mode for orbit following.
Definition mhd_stat.c:135
void mhd_stat_free(mhd_stat_data *data)
Free allocated resources.
Definition mhd_stat.c:82
Header file for mhd_stat.c.
Macros for printing console output.
#define print_out(v,...)
Print to standard output.
Definition print.h:31
@ VERBOSE_IO
Definition print.h:20
#define print_err(...)
Print to standard error.
Definition print.h:42
Magnetic field simulation data.
Definition B_field.h:41
Data for mapping between the cylindrical and Boozer coordinates.
Definition boozer.h:16
Cubic interpolation struct.
Definition interp.h:56
real * c
Definition interp.h:62
MHD stat parameters on the target.
Definition mhd_stat.h:18
real * omega_nm
Definition mhd_stat.h:25
interp1D_data * alpha_nm
1D splines (rho) for each mode's magnetic eigenfunction
Definition mhd_stat.h:31
real * phase_nm
Definition mhd_stat.h:26
interp1D_data * phi_nm
1D splines (rho) for each mode's electric eigenfunction
Definition mhd_stat.h:36
real * amplitude_nm
Definition mhd_stat.h:24
int * mmode
Definition mhd_stat.h:23
int * nmode
Definition mhd_stat.h:22