Commit efe5840e45d9762efc04cc9dc6bd4afce9b46071
1 parent
a9eed1ff
Exists in
master
Apply some modif. to libcon2020 to improve librairy load
Showing
5 changed files
with
2451 additions
and
0 deletions
Show diff stats
... | ... | @@ -0,0 +1,670 @@ |
1 | +#ifndef __LIBCON2020_H__ | |
2 | +#define __LIBCON2020_H__ | |
3 | +#include <algorithm> | |
4 | +#include <math.h> | |
5 | +#include <stdio.h> | |
6 | +#include <stdlib.h> | |
7 | +#include <string.h> | |
8 | + | |
9 | +#define LIBCON2020_VERSION_MAJOR 0 | |
10 | +#define LIBCON2020_VERSION_MINOR 1 | |
11 | +#define LIBCON2020_VERSION_PATCH 0 | |
12 | + | |
13 | +#define M_PI 3.14159265358979323846 | |
14 | +#define USE_MATH_DEFINES | |
15 | +#define _USE_MATH_DEFINES | |
16 | +#define deg2rad M_PI/180.0 | |
17 | +#define rad2deg 180.0/M_PI | |
18 | + | |
19 | +extern "C" { | |
20 | + /* these wrappers can be used to get the magnetic field vectors */ | |
21 | + void Con2020FieldArray(int n, double *p0, double *p1, double *p2, | |
22 | + double *B0, double *B1, double *B2); | |
23 | + | |
24 | + void Con2020Field(double p0, double p1, double p2, | |
25 | + double *B0, double *B1, double *B2); | |
26 | + | |
27 | + | |
28 | + void GetCon2020Params(double *mui, double *irho, double *r0, double *r1, | |
29 | + double *d, double *xt, double *xp, char *eqtype, | |
30 | + bool *Edwards, bool *ErrChk, bool *CartIn, bool *CartOut, | |
31 | + bool *smooth, double *DeltaRho, double *DeltaZ, | |
32 | + double *g, char *azfunc, double *wO_open, double *wO_om, | |
33 | + double *thetamm, double *dthetamm, double *thetaoc, double *dthetaoc); | |
34 | + | |
35 | + | |
36 | + void SetCon2020Params(double mui, double irho, double r0, double r1, | |
37 | + double d, double xt, double xp, const char *eqtype, | |
38 | + bool Edwards, bool ErrChk, bool CartIn, bool CartOut, | |
39 | + bool smooth, double DeltaRho, double DeltaZ, | |
40 | + double g, const char *azfunc, double wO_open, double wO_om, | |
41 | + double thetamm, double dthetamm, double thetaoc, double dthetaoc); | |
42 | + | |
43 | + void Con2020AnalyticField( int n, double a, | |
44 | + double *rho, double *z, | |
45 | + double *Brho, double *Bz); | |
46 | + | |
47 | + void Con2020AnalyticFieldSmooth( int n, double a, | |
48 | + double *rho, double *z, | |
49 | + double *Brho, double *Bz); | |
50 | + | |
51 | + | |
52 | +/*************************************************************** | |
53 | +* | |
54 | +* NAME : ScalarPotentialSmallRho(rho,z,a,mui2,D) | |
55 | +* | |
56 | +* DESCRIPTION : Calcualte the small rho approximation | |
57 | +* of the scalar potential accoring to Edwards et al., | |
58 | +* 2001 (equation 8). | |
59 | +* | |
60 | +* INPUTS : | |
61 | +* double rho Cylindrical rho coordinate (in disc | |
62 | +* coordinate system, Rj) | |
63 | +* double z z-coordinate, Rj | |
64 | +* double a inner edge of semi-infinite current | |
65 | +* sheet, Rj | |
66 | +* double mui2 mu_0 I_0 /2 parameter (default 139.6 nT) | |
67 | +* double D Current sheet half-thickness, Rj | |
68 | +* | |
69 | +***************************************************************/ | |
70 | + double ScalarPotentialSmallRho( double rho, double z, double a, | |
71 | + double mui2, double D); | |
72 | + | |
73 | + | |
74 | +/*************************************************************** | |
75 | +* | |
76 | +* NAME : ScalarPotentialLargeRho(rho,z,a,mui2,D,deltaz) | |
77 | +* | |
78 | +* DESCRIPTION : Calcualte the large rho approximation | |
79 | +* of the scalar potential accoring to Edwards et al., | |
80 | +* 2001 (equation 12). | |
81 | +* | |
82 | +* INPUTS : | |
83 | +* double rho Cylindrical rho coordinate (in disc | |
84 | +* coordinate system, Rj) | |
85 | +* double z z-coordinate, Rj | |
86 | +* double a inner edge of semi-infinite current | |
87 | +* sheet, Rj | |
88 | +* double mui2 mu_0 I_0 /2 parameter (default 139.6 nT) | |
89 | +* double D Current sheet half-thickness, Rj | |
90 | +* double deltaz Scale length over which to smooth 4th | |
91 | +* term of the equation | |
92 | +* | |
93 | +***************************************************************/ | |
94 | + double ScalarPotentialLargeRho( double rho, double z, double a, | |
95 | + double mui2, double D, double deltaz); | |
96 | + | |
97 | + | |
98 | +/*************************************************************** | |
99 | +* | |
100 | +* NAME : ScalarPotential(rho,z,a,mui2,D,deltarho,deltaz) | |
101 | +* | |
102 | +* DESCRIPTION : Calculate the small/large rho approximation | |
103 | +* of the scalar potential accoring to Edwards et al., | |
104 | +* 2001 (equations 8 & 12). | |
105 | +* | |
106 | +* INPUTS : | |
107 | +* double rho Cylindrical rho coordinate (in disc | |
108 | +* coordinate system, Rj) | |
109 | +* double z z-coordinate, Rj | |
110 | +* double a inner edge of semi-infinite current | |
111 | +* sheet, Rj | |
112 | +* double mui2 mu_0 I_0 /2 parameter (default 139.6 nT) | |
113 | +* double D Current sheet half-thickness, Rj | |
114 | +* double deltarho Scale length to smoothly transition from | |
115 | +* small to large rho approx | |
116 | +* double deltaz Scale length over which to smooth 4th | |
117 | +* term of the equation | |
118 | +* | |
119 | +***************************************************************/ | |
120 | + double ScalarPotential( double rho, double z, double a, | |
121 | + double mui2, double D, | |
122 | + double deltarho, double deltaz); | |
123 | + | |
124 | + /************************************************************* | |
125 | + * | |
126 | + * NAME: f_theta(thetai) | |
127 | + * | |
128 | + * DESCRIPTION: Equation 5 of Cowley et al., 2008 | |
129 | + * | |
130 | + * INPUTS: | |
131 | + * double thetai colatitude of the ionospheric footprint | |
132 | + * in radians! | |
133 | + * | |
134 | + * RETURNS: | |
135 | + * double f_theta 1 + 0.25*tan^2 thetai | |
136 | + * | |
137 | + *************************************************************/ | |
138 | + double f_thetai(double thetai); | |
139 | + | |
140 | + /************************************************************* | |
141 | + * | |
142 | + * NAME: OmegaRatio(thetai,wO_open,wO_om,thetamm,dthetamm, | |
143 | + * thetaoc,dthetaoc) | |
144 | + * | |
145 | + * DESCRIPTION: Ratio of the angular velocity mapped to | |
146 | + * thetai to the planetary rotation. Equation 15 of | |
147 | + * Cowley et al., 2008. | |
148 | + * | |
149 | + * INPUTS: | |
150 | + * double thetai colatitude of the ionospheric footprint | |
151 | + * in radians! | |
152 | + * double wO_open angular velocity ratio of open flux to | |
153 | + * planetary spin | |
154 | + * double wO_om angular velocity ratio of outer magnetosphere | |
155 | + * to planetary spin | |
156 | + * double thetamm ionospheric footprint latitude of the | |
157 | + * middle magnetosphere (where plasma | |
158 | + * goes from rigid corotation to subcorotation) | |
159 | + * in radians. | |
160 | + * double dthetamm width of the middle magnetosphere in radians. | |
161 | + * double thetaoc ionospheric latitude of the open-closed field | |
162 | + * line boundary, in radians. | |
163 | + * double dthetaoc width of the open-closed field line boundary, | |
164 | + * in radians. | |
165 | + * | |
166 | + * RETURNS: | |
167 | + * double wO Ratio of plasma angular veloctiy to Jupiter | |
168 | + * spin. | |
169 | + * | |
170 | + *************************************************************/ | |
171 | + double OmegaRatio( double thetai, double wO_open, double wO_om, | |
172 | + double thetamm, double dthetamm, | |
173 | + double thetaoc, double dthetaoc); | |
174 | + | |
175 | + /************************************************************* | |
176 | + * | |
177 | + * NAME: PedersenCurrent(thetai,g,wO_open,wO_om,thetamm,dthetamm, | |
178 | + * thetaoc,dthetsoc) | |
179 | + * | |
180 | + * DESCRIPTION: Calculate the Pedersen current which maps to a | |
181 | + * given ionospheric latitude using equation 6 of Cowley et | |
182 | + * al., 2008. | |
183 | + * | |
184 | + * INPUTS: | |
185 | + * double thetai colatitude of the ionospheric footprint | |
186 | + * in radians! | |
187 | + * double g dipole coefficient, nT. | |
188 | + * double wO_open angular velocity ratio of open flux to | |
189 | + * planetary spin | |
190 | + * double wO_om angular velocity ratio of outer magnetosphere | |
191 | + * to planetary spin | |
192 | + * double thetamm ionospheric footprint latitude of the | |
193 | + * middle magnetosphere (where plasma | |
194 | + * goes from rigid corotation to subcorotation) | |
195 | + * in radians. | |
196 | + * double dthetamm width of the middle magnetosphere in radians. | |
197 | + * double thetaoc ionospheric latitude of the open-closed field | |
198 | + * line boundary, in radians. | |
199 | + * double dthetaoc width of the open-closed field line boundary, | |
200 | + * in radians. | |
201 | + * RETURNS: | |
202 | + * double Ihp Ionospheric Pedersen current. | |
203 | + * | |
204 | + *************************************************************/ | |
205 | + double PedersenCurrent( double thetai, double g, | |
206 | + double wO_open, double wO_om, | |
207 | + double thetamm, double dthetamm, | |
208 | + double thetaoc, double dthetaoc ); | |
209 | + | |
210 | + /************************************************************* | |
211 | + * | |
212 | + * NAME: ThetaIonosphere(r,theta,g,r0,r1,mui2,D,deltarho,deltaz) | |
213 | + * | |
214 | + * DESCRIPTION: Use the flux functions of the CAN model and a | |
215 | + * dipole field to map the current position to a position | |
216 | + * on the ionosphere. | |
217 | + * | |
218 | + * INPUTS: | |
219 | + * double r radial coordinate, Rj. | |
220 | + * double theta colatitude, radians. | |
221 | + * double g dipole coefficient, nT. | |
222 | + * double r0 Inner edge of the current sheet, Rj. | |
223 | + * double r1 Outer edge of the current sheet, Rj. | |
224 | + * double mui2 current parameter, nT. | |
225 | + * double D half-thickness of the current sheet, Rj. | |
226 | + * double deltarho scale distance of the smoothing between | |
227 | + * inner and outer approximations, Rj. | |
228 | + * double deltaz scale distance to smooth across the | |
229 | + * +/-D boundary, Rj. | |
230 | + * | |
231 | + * RETURNS: | |
232 | + * double thetai Ionospheric latitude in radians. | |
233 | + * | |
234 | + * | |
235 | + *************************************************************/ | |
236 | + double ThetaIonosphere( double r, double theta, double g, | |
237 | + double r0, double r1, | |
238 | + double mui2, double D, | |
239 | + double deltarho, double deltaz); | |
240 | + | |
241 | + /************************************************************* | |
242 | + * | |
243 | + * NAME: BphiLMIC(r,theta,g,r0,r1,mui2,D,deltarho,deltaz, | |
244 | + * wO_open,wO_om,thetamm,dthetamm, | |
245 | + * thetaom,dthetaom) | |
246 | + * | |
247 | + * DESCRIPTION: Calculate the azimuthal field using the LMIC | |
248 | + * model. | |
249 | + * | |
250 | + * INPUTS: | |
251 | + * double r radial coordinate, Rj. | |
252 | + * double theta colatitude, radians. | |
253 | + * double g dipole coefficient, nT. | |
254 | + * double r0 Inner edge of the current sheet, Rj. | |
255 | + * double r1 Outer edge of the current sheet, Rj. | |
256 | + * double mui2 current parameter, nT. | |
257 | + * double D half-thickness of the current sheet, Rj. | |
258 | + * double deltarho scale distance of the smoothing between | |
259 | + * inner and outer approximations, Rj. | |
260 | + * double deltaz scale distance to smooth across the | |
261 | + * +/-D boundary, Rj. | |
262 | + * double wO_open angular velocity ratio of open flux to | |
263 | + * planetary spin | |
264 | + * double wO_om angular velocity ratio of outer magnetosphere | |
265 | + * to planetary spin | |
266 | + * double thetamm ionospheric footprint latitude of the | |
267 | + * middle magnetosphere (where plasma | |
268 | + * goes from rigid corotation to subcorotation) | |
269 | + * in radians. | |
270 | + * double dthetamm width of the middle magnetosphere in radians. | |
271 | + * double thetaoc ionospheric latitude of the open-closed field | |
272 | + * line boundary, in radians. | |
273 | + * double dthetaoc width of the open-closed field line boundary, | |
274 | + * in radians. | |
275 | + * | |
276 | + * RETURNS: | |
277 | + * double Bphi Azimuthal field, nT. | |
278 | + * | |
279 | + *************************************************************/ | |
280 | + double BphiLMIC(double r, double theta, double g, | |
281 | + double r0, double r1, | |
282 | + double mui2, double D, | |
283 | + double deltarho, double deltaz, | |
284 | + double wO_open, double wO_om, | |
285 | + double thetamm, double dthetamm, | |
286 | + double thetaoc, double dthetaoc ); | |
287 | + | |
288 | + /************************************************************* | |
289 | + * | |
290 | + * NAME: BphiIonosphere(thetai,g,wO_open,wO_om,thetamm,dthetamm, | |
291 | + * thetaom,dthetaom) | |
292 | + * | |
293 | + * DESCRIPTION: Calculate the ionospheric azimuthal field using the LMIC | |
294 | + * model. | |
295 | + * | |
296 | + * INPUTS: | |
297 | + * double thetai ionospheric colatitude, radians. | |
298 | + * double g dipole coefficient, nT. | |
299 | + * double wO_open angular velocity ratio of open flux to | |
300 | + * planetary spin | |
301 | + * double wO_om angular velocity ratio of outer magnetosphere | |
302 | + * to planetary spin | |
303 | + * double thetamm ionospheric footprint latitude of the | |
304 | + * middle magnetosphere boundary (where plasma | |
305 | + * goes from rigid corotation to subcorotation) | |
306 | + * in radians. | |
307 | + * double dthetamm width of the middle magnetosphere boundary | |
308 | + * in radians. | |
309 | + * double thetaoc ionospheric latitude of the open-closed field | |
310 | + * line boundary, in radians. | |
311 | + * double dthetaoc width of the open-closed field line boundary, | |
312 | + * in radians. | |
313 | + * | |
314 | + * RETURNS: | |
315 | + * double Bphi Azimuthal field, nT. | |
316 | + * | |
317 | + *************************************************************/ | |
318 | + double BphiIonosphere( double thetai, double g, | |
319 | + double wO_open, double wO_om, | |
320 | + double thetamm, double dthetamm, | |
321 | + double thetaoc, double dthetaoc ); | |
322 | +} | |
323 | + | |
324 | + | |
325 | +/*********************************************************************** | |
326 | + * NAME : j0(x) | |
327 | + * | |
328 | + * DESCRIPTION : Fucntion to calculate an estimate of the Bessel | |
329 | + * function j0 using code based on the Cephes C library | |
330 | + * (Cephes Mathematical Functions Library, http://www.netlib.org/cephes/). | |
331 | + * | |
332 | + * INPUTS : | |
333 | + * double x position to calculate J0 at. | |
334 | + * | |
335 | + * RETURNS : | |
336 | + * double j j0 function evaluated at x. | |
337 | + * | |
338 | + * ********************************************************************/ | |
339 | +double j0(double x); | |
340 | + | |
341 | +/*********************************************************************** | |
342 | + * NAME : j1(x) | |
343 | + * | |
344 | + * DESCRIPTION : Fucntion to calculate an estimate of the Bessel | |
345 | + * function j1 using code based on the Cephes C library | |
346 | + * (Cephes Mathematical Functions Library, http://www.netlib.org/cephes/). | |
347 | + * | |
348 | + * INPUTS : | |
349 | + * double x position to calculate J1 at. | |
350 | + * | |
351 | + * RETURNS : | |
352 | + * double j j1 function evaluated at x. | |
353 | + * | |
354 | + * ********************************************************************/ | |
355 | +double j1(double x); | |
356 | + | |
357 | +/*********************************************************************** | |
358 | + * NAME : j0(n,x,j) | |
359 | + * | |
360 | + * DESCRIPTION : Fucntion to calculate an estimate of the Bessel | |
361 | + * function j0 using code based on the Cephes C library | |
362 | + * (Cephes Mathematical Functions Library, http://www.netlib.org/cephes/). | |
363 | + * | |
364 | + * INPUTS : | |
365 | + * int n Number of elements in x | |
366 | + * double *x position to calculate J0 at. | |
367 | + * | |
368 | + * OUTPUTS : | |
369 | + * double *j j0 function evaluated at x. | |
370 | + * | |
371 | + * ********************************************************************/ | |
372 | +void j0(int n, double *x, double *j); | |
373 | + | |
374 | +/*********************************************************************** | |
375 | + * NAME : j1(n,x,j) | |
376 | + * | |
377 | + * DESCRIPTION : Fucntion to calculate an estimate of the Bessel | |
378 | + * function j1 using code based on the Cephes C library | |
379 | + * (Cephes Mathematical Functions Library, http://www.netlib.org/cephes/). | |
380 | + * | |
381 | + * INPUTS : | |
382 | + * int n Number of elements in x | |
383 | + * double *x position to calculate J1 at. | |
384 | + * | |
385 | + * OUTPUTS : | |
386 | + * double *j j1 function evaluated at x. | |
387 | + * | |
388 | + * ********************************************************************/ | |
389 | +void j1(int n, double *x, double *j); | |
390 | + | |
391 | +/*********************************************************************** | |
392 | + * NAME : j0(n,x,multx,j) | |
393 | + * | |
394 | + * DESCRIPTION : Fucntion to calculate an estimate of the Bessel | |
395 | + * function j0 using code based on the Cephes C library | |
396 | + * (Cephes Mathematical Functions Library, http://www.netlib.org/cephes/). | |
397 | + * | |
398 | + * INPUTS : | |
399 | + * int n Number of elements in x | |
400 | + * double *x position to calculate J0(x*multx) at. | |
401 | + * double multx Constant to multiply x by | |
402 | + * | |
403 | + * OUTPUTS : | |
404 | + * double *j j0 function evaluated at x*multx. | |
405 | + * | |
406 | + * ********************************************************************/ | |
407 | +void j0(int n, double *x, double multx, double *j); | |
408 | + | |
409 | +/*********************************************************************** | |
410 | + * NAME : j1(n,x,multx,j) | |
411 | + * | |
412 | + * DESCRIPTION : Fucntion to calculate an estimate of the Bessel | |
413 | + * function j1 using code based on the Cephes C library | |
414 | + * (Cephes Mathematical Functions Library, http://www.netlib.org/cephes/). | |
415 | + * | |
416 | + * INPUTS : | |
417 | + * int n Number of elements in x | |
418 | + * double *x position to calculate J1(x*multx) at. | |
419 | + * double multx Constant to multiply x by | |
420 | + * | |
421 | + * OUTPUTS : | |
422 | + * double *j j1 function evaluated at x*multx. | |
423 | + * | |
424 | + * ********************************************************************/ | |
425 | +void j1(int n, double *x, double multx, double *j); | |
426 | + | |
427 | + | |
428 | +template <typename T> T clip(T x, T mn, T mx) { | |
429 | + return std::min(mx,std::max(x,mn)); | |
430 | +} | |
431 | + | |
432 | +/* function pointer for input conversion */ | |
433 | +class Con2020; /*this is needed for the pointer below */ | |
434 | +typedef void (Con2020::*InputConvFunc)(int,double*,double*,double*, | |
435 | + double*,double*,double*,double*,double*, | |
436 | + double*,double*,double*,double*); | |
437 | +/* Output conversion */ | |
438 | +typedef void (Con2020::*OutputConvFunc)(int,double*,double*,double*, | |
439 | + double*,double*,double*,double*, | |
440 | + double*,double*,double*, | |
441 | + double*,double*,double*); | |
442 | + | |
443 | +/* Model function */ | |
444 | +typedef void (Con2020::*ModelFunc)(double,double,double,double*,double*,double*); | |
445 | + | |
446 | +/* analytical approximation equations */ | |
447 | +typedef void (Con2020::*Approx)(double,double,double,double,double,double*,double*); | |
448 | + | |
449 | +/* azimuthal function */ | |
450 | +typedef void (Con2020::*AzimFunc)(double,double,double,double*); | |
451 | + | |
452 | +class Con2020 { | |
453 | + public: | |
454 | + /* constructors */ | |
455 | + Con2020(); | |
456 | + Con2020(double,double,double,double,double,double,double,const char*,bool,bool,bool,bool); | |
457 | + | |
458 | + /* destructor */ | |
459 | + ~Con2020(); | |
460 | + | |
461 | + /* these functions will be used to set the equations used, if | |
462 | + * they need to be changed post-initialisation */ | |
463 | + | |
464 | + // BRE - 10/10/2023 - Add method to init integrals | |
465 | + void Init(); | |
466 | + //---------- | |
467 | + | |
468 | + void SetEdwardsEqs(bool); | |
469 | + void SetEqType(const char*); | |
470 | + void SetAzCurrentParameter(double); | |
471 | + void SetRadCurrentParameter(double); | |
472 | + void SetR0(double); | |
473 | + void SetR1(double); | |
474 | + void SetCSHalfThickness(double); | |
475 | + void SetCSTilt(double); | |
476 | + void SetCSTiltAzimuth(double); | |
477 | + void SetErrCheck(bool); | |
478 | + void SetCartIn(bool); | |
479 | + void SetCartOut(bool); | |
480 | + void SetSmooth(bool); | |
481 | + void SetDeltaRho(double); | |
482 | + void SetDeltaZ(double); | |
483 | + void SetOmegaOpen(double); | |
484 | + void SetOmegaOM(double); | |
485 | + void SetThetaMM(double); | |
486 | + void SetdThetaMM(double); | |
487 | + void SetThetaOC(double); | |
488 | + void SetdThetaOC(double); | |
489 | + void SetG(double); | |
490 | + void SetAzimuthalFunc(const char*); | |
491 | + | |
492 | + /* these mamber functions will be the "getter" version of the | |
493 | + * above setters */ | |
494 | + bool GetEdwardsEqs(); | |
495 | + void GetEqType(char*); | |
496 | + double GetAzCurrentParameter(); | |
497 | + double GetRadCurrentParameter(); | |
498 | + double GetR0(); | |
499 | + double GetR1(); | |
500 | + double GetCSHalfThickness(); | |
501 | + double GetCSTilt(); | |
502 | + double GetCSTiltAzimuth(); | |
503 | + bool GetErrCheck(); | |
504 | + bool GetCartIn(); | |
505 | + bool GetCartOut(); | |
506 | + bool GetSmooth(); | |
507 | + double GetDeltaRho(); | |
508 | + double GetDeltaZ(); | |
509 | + double GetOmegaOpen(); | |
510 | + double GetOmegaOM(); | |
511 | + double GetThetaMM(); | |
512 | + double GetdThetaMM(); | |
513 | + double GetThetaOC(); | |
514 | + double GetdThetaOC(); | |
515 | + double GetG(); | |
516 | + void GetAzimuthalFunc(char *); | |
517 | + | |
518 | + /* This function will be used to call the model, it is overloaded | |
519 | + * so that we have one for arrays, one for scalars */ | |
520 | + void Field(int,double*,double*,double*,double*,double*,double*); | |
521 | + void Field(double,double,double,double*,double*,double*); | |
522 | + | |
523 | + /* a function for testing purposes...*/ | |
524 | + void AnalyticField(double,double,double,double*,double*); | |
525 | + void AnalyticFieldSmooth(double,double,double,double*,double*); | |
526 | + | |
527 | + private: | |
528 | + /* model parameters */ | |
529 | + double mui_,irho_,r0_,r1_,d_,xt_,xp_,disctilt_,discshift_; | |
530 | + double r0sq_, r1sq_; | |
531 | + double cosxp_,sinxp_,cosxt_,sinxt_; | |
532 | + char eqtype_[9]; | |
533 | + bool Edwards_, ErrChk_; | |
534 | + bool CartIn_,CartOut_; | |
535 | + double deltaz_,deltarho_; | |
536 | + bool smooth_; | |
537 | + | |
538 | + /* LMIC parameters*/ | |
539 | + double wO_open_, wO_om_, thetamm_, dthetamm_, thetaoc_, dthetaoc_, g_; | |
540 | + char azfunc_[10]; | |
541 | + | |
542 | + /* Bessel function arrays - arrays prefixed with r and z are | |
543 | + * to be used for integrals which calcualte Brho and Bz, | |
544 | + * respectively */ | |
545 | + int *rnbes_; /* number of elements for each Bessel function (rho)*/ | |
546 | + int *znbes_; /* same as above for z */ | |
547 | + double **rlambda_;/* Lambda array to integrate over rho*/ | |
548 | + double **zlambda_;/* Lambda array to integrate over z*/ | |
549 | + double **rj0_lambda_r0_; /* j0(lambda*r0) */ | |
550 | + double **rj1_lambda_rho_;/* j1(lambda*rho) */ | |
551 | + double **zj0_lambda_r0_; /* j0(lambda*r0) */ | |
552 | + double **zj0_lambda_rho_;/* j0(lambda*rho) */ | |
553 | + | |
554 | + /* arrays to multiply be stuff to be integrated */ | |
555 | + /* these arrays will store the parts of equations 14, 15, 17 | |
556 | + * and 18 of Connerny 1981 which only need to be calculated once*/ | |
557 | + double **Eq14_; /* j0(lambda*r0)*sinh(lamba*d)/lambda */ | |
558 | + double **Eq15_; /* j0(lambda*r0)*sinh(lamba*d)/lambda */ | |
559 | + double **Eq17_; /* j0(lambda*r0)*exp(-lamba*d)/lambda */ | |
560 | + double **Eq18_; /* j0(lambda*r0)/lambda */ | |
561 | + double **ExpLambdaD_; | |
562 | + | |
563 | + /* integration step sizes */ | |
564 | + static constexpr double dlambda_ = 1e-4; | |
565 | + static constexpr double dlambda_brho_ = 1e-4; | |
566 | + static constexpr double dlambda_bz_ = 5e-5; | |
567 | + | |
568 | + /* Arrays containing maximum lambda values */ | |
569 | + double rlmx_array_[6]; | |
570 | + double zlmx_array_[6]; | |
571 | + | |
572 | + /* coordinate conversions for positions */ | |
573 | + InputConvFunc _ConvInput; | |
574 | + void _SysIII2Mag(int,double*,double*,double*, | |
575 | + double*,double*,double*,double*,double*, | |
576 | + double*,double*,double*,double*); | |
577 | + void _PolSysIII2Mag(int,double*,double*,double*, | |
578 | + double*,double*,double*,double*,double*, | |
579 | + double*,double*,double*,double*); | |
580 | + | |
581 | + /* coordinate conversion for magnetic field vector */ | |
582 | + OutputConvFunc _ConvOutput; | |
583 | + void _BMag2SysIII(int,double*,double*,double*, | |
584 | + double*,double*,double*,double*, | |
585 | + double*,double*,double*, | |
586 | + double*,double*,double*); | |
587 | + void _BMag2PolSysIII(int,double*,double*,double*, | |
588 | + double*,double*,double*,double*, | |
589 | + double*,double*,double*, | |
590 | + double*,double*,double*); | |
591 | + | |
592 | + /* Functions to update function pointers */ | |
593 | + void _SetIOFunctions(); | |
594 | + void _SetModelFunctions(); | |
595 | + ModelFunc _Model; | |
596 | + | |
597 | + /* Azimuthal field */ | |
598 | + AzimFunc _AzimuthalField; | |
599 | + void _BphiConnerney(int,double*,double*,double*,double*); | |
600 | + void _BphiConnerney(double,double,double,double*); | |
601 | + void _BphiLMIC(double,double,double,double*); | |
602 | + Approx _LargeRho; | |
603 | + Approx _SmallRho; | |
604 | + /* analytic equations */ | |
605 | + void _Analytic(double,double,double,double*,double*,double*); | |
606 | + void _AnalyticSmooth(double,double,double,double*,double*,double*); | |
607 | + void _SolveAnalytic(int,double*,double*,double,double*,double*); | |
608 | + void _AnalyticInner(double,double,double*,double*); | |
609 | + void _AnalyticOuter(double,double,double*,double*); | |
610 | + void _AnalyticInnerSmooth(double,double,double*,double*); | |
611 | + void _AnalyticOuterSmooth(double,double,double*,double*); | |
612 | + void _LargeRhoConnerney(double,double,double,double,double,double*,double*); | |
613 | + void _SmallRhoConnerney(double,double,double,double,double,double*,double*); | |
614 | + void _LargeRhoEdwards(double,double,double,double,double,double*,double*); | |
615 | + void _LargeRhoEdwardsSmooth(double,double,double,double,double,double*,double*); | |
616 | + void _SmallRhoEdwards(double,double,double,double,double,double*,double*); | |
617 | + | |
618 | + /* integral-related functions */ | |
619 | + void _Integral(double,double,double,double*,double*,double*); | |
620 | + void _IntegralInner(double, double, double, double*, double*); | |
621 | + void _InitIntegrals(); | |
622 | + void _RecalcIntegrals(); | |
623 | + void _DeleteIntegrals(); | |
624 | + void _IntegralChecks(int,double*,int*,int[]); | |
625 | + void _IntegralCheck(double,int*); | |
626 | + void _SolveIntegral(int,double*,double*,double*,double*,double*); | |
627 | + void _IntegrateEq14(int,double,double,double,double*); | |
628 | + void _IntegrateEq15(int,double,double,double*); | |
629 | + void _IntegrateEq17(int,double,double,double*); | |
630 | + void _IntegrateEq18(int,double,double,double*); | |
631 | + | |
632 | + /* hybrid */ | |
633 | + void _Hybrid(double,double,double,double*,double*,double*); | |
634 | +}; | |
635 | + | |
636 | +/* we want to initialize the model objects with its parameters */ | |
637 | +extern Con2020 con2020; | |
638 | + | |
639 | + | |
640 | +double polyeval(double x, double *c, int d); | |
641 | + | |
642 | +double pol1eval(double x, double *c, int d); | |
643 | + | |
644 | +/*********************************************************************** | |
645 | + * NAME : smoothd(z,dz,d) | |
646 | + * | |
647 | + * DESCRIPTION : Smooth fucntion for crossing the current sheet | |
648 | + * (replaces the last bit of equation 12 in Edwards et al 2000). | |
649 | + * | |
650 | + * INPUTS : | |
651 | + * double z z-coordinate in dipole coordinate system (Rj) | |
652 | + * double dz Scale of the transition to use (Rj) | |
653 | + * double d Half thickness of the current sheet. | |
654 | + * | |
655 | + * RETURNS : | |
656 | + * double out Smoothed function across the current sheet. | |
657 | + * | |
658 | + * ********************************************************************/ | |
659 | +double smoothd(double z, double dz, double d); | |
660 | + | |
661 | + | |
662 | +double trap(int n, double *x, double *y); | |
663 | +double trapc(int n, double dx, double *y); | |
664 | + | |
665 | +template <typename T> T sgn(T x) { | |
666 | + return (x > 0) - (x < 0); | |
667 | +} | |
668 | + | |
669 | + | |
670 | +#endif | ... | ... |
... | ... | @@ -0,0 +1,1381 @@ |
1 | +#include "con2020.h" | |
2 | + | |
3 | +Con2020::Con2020() { | |
4 | + /* set all model parameters to their default values */ | |
5 | + mui_ = 139.6; | |
6 | + irho_ = 16.7; | |
7 | + r0_ = 7.8; | |
8 | + r0sq_ = r0_*r0_; | |
9 | + r1_ = 51.4; | |
10 | + r1sq_ = r1_*r1_; | |
11 | + d_ = 3.6; | |
12 | + xt_ = 9.3; | |
13 | + xp_ = 155.8; | |
14 | + strcpy(eqtype_,"hybrid"); | |
15 | + Edwards_ = true; | |
16 | + ErrChk_ = true; | |
17 | + CartIn_ = true; | |
18 | + CartOut_ = true; | |
19 | + deltarho_ = 1.0; | |
20 | + deltaz_ = 0.1; | |
21 | + smooth_ = false; | |
22 | + wO_open_ = 0.1; | |
23 | + wO_om_ = 0.35; | |
24 | + thetamm_ = 16.1*deg2rad; | |
25 | + dthetamm_ = 0.5*deg2rad; | |
26 | + thetaoc_ = 10.716*deg2rad; | |
27 | + dthetaoc_ = 0.125*deg2rad; | |
28 | + g_ = 417659.3836476442; | |
29 | + strcpy(azfunc_,"connerney"); | |
30 | + | |
31 | + /* some other values which will only need calculating once */ | |
32 | + discshift_ = (xp_-180.0)*deg2rad; | |
33 | + disctilt_ = xt_*deg2rad; | |
34 | + cosxp_ = cos(discshift_); | |
35 | + sinxp_ = sin(discshift_); | |
36 | + cosxt_ = cos(disctilt_); | |
37 | + sinxt_ = sin(disctilt_); | |
38 | + | |
39 | + // BRE - 10/10/2023 - Do not init integrals in constructor to improve library load | |
40 | + /* initialize some things used for integration */ | |
41 | + init_ = false; | |
42 | + //_InitIntegrals(); | |
43 | + //------------------------- | |
44 | + | |
45 | + /* set appropriate coord conversion functions*/ | |
46 | + _SetIOFunctions(); | |
47 | + _SetModelFunctions(); | |
48 | + | |
49 | +} | |
50 | + | |
51 | +Con2020::Con2020(double mui, double irho, double r0, double r1, | |
52 | + double d, double xt, double xp, const char *eqtype, | |
53 | + bool Edwards, bool ErrChk, bool CartIn, bool CartOut) { | |
54 | + /* set non-boolean model parameters to their default values */ | |
55 | + mui_ = 139.6; | |
56 | + irho_ = 16.7; | |
57 | + r0_ = 7.8; | |
58 | + r0sq_ = r0_*r0_; | |
59 | + r1_ = 51.4; | |
60 | + r1sq_ = r1_*r1_; | |
61 | + d_ = 3.6; | |
62 | + xt_ = 9.3; | |
63 | + xp_ = 155.8; | |
64 | + strcpy(eqtype_,"hybrid"); | |
65 | + Edwards_ = Edwards; | |
66 | + ErrChk_ = ErrChk; | |
67 | + CartIn_ = CartIn; | |
68 | + CartOut_ = CartOut; | |
69 | + deltarho_ = 1.0; | |
70 | + deltaz_ = 0.01; | |
71 | + smooth_ = false; | |
72 | + wO_open_ = 0.1; | |
73 | + wO_om_ = 0.35; | |
74 | + thetamm_ = 16.1*deg2rad; | |
75 | + dthetamm_ = 0.5*deg2rad; | |
76 | + thetaoc_ = 10.716*deg2rad; | |
77 | + dthetaoc_ = 0.125*deg2rad; | |
78 | + g_ = 417659.3836476442; | |
79 | + strcpy(azfunc_,"connerney"); | |
80 | + | |
81 | + /* apply custom values if they are valid */ | |
82 | + SetAzCurrentParameter(mui); | |
83 | + SetRadCurrentParameter(irho); | |
84 | + SetR0(r0); | |
85 | + SetR1(r1); | |
86 | + SetCSHalfThickness(d); | |
87 | + SetCSTilt(xt); | |
88 | + SetCSTiltAzimuth(xp); | |
89 | + | |
90 | + | |
91 | + /* some other values which will only need calculating once */ | |
92 | + discshift_ = (xp_-180.0)*deg2rad; | |
93 | + disctilt_ = xt_*deg2rad; | |
94 | + | |
95 | + // BRE - 10/10/2023 - Do not init integrals in constructor to improve library load | |
96 | + /* initialize some things used for integration */ | |
97 | + init_ = false; | |
98 | + //_InitIntegrals(); | |
99 | + //------------------------- | |
100 | + | |
101 | + /* set appropriate coord conversion functions*/ | |
102 | + _SetIOFunctions(); | |
103 | + _SetModelFunctions(); | |
104 | + | |
105 | +} | |
106 | +Con2020::~Con2020() { | |
107 | + // BRE - 10/10/2023 - Delete integrals only if init | |
108 | + if (init_) | |
109 | + _DeleteIntegrals(); | |
110 | + //------------------------- | |
111 | +} | |
112 | + | |
113 | + | |
114 | +// BRE - 10/10/2023 - Add method to init integrals | |
115 | +void Con2020::Init() { | |
116 | + | |
117 | + if (init_) | |
118 | + return; | |
119 | + | |
120 | + /* initialize some things used for integration */ | |
121 | + _InitIntegrals(); | |
122 | + | |
123 | + init_ = true; | |
124 | +} | |
125 | +//------------------------- | |
126 | + | |
127 | +void Con2020::_SetIOFunctions() { | |
128 | + | |
129 | + if (CartIn_) { | |
130 | + _ConvInput = &Con2020::_SysIII2Mag; | |
131 | + } else { | |
132 | + _ConvInput = &Con2020::_PolSysIII2Mag; | |
133 | + } | |
134 | + if (CartOut_) { | |
135 | + _ConvOutput = &Con2020::_BMag2SysIII; | |
136 | + } else { | |
137 | + _ConvOutput = &Con2020::_BMag2PolSysIII; | |
138 | + } | |
139 | +} | |
140 | + | |
141 | +void Con2020::_SetModelFunctions() { | |
142 | + | |
143 | + /* firstly set whether we are using the Edwards or Connerney | |
144 | + * analytical functions */ | |
145 | + if (Edwards_) { | |
146 | + if (smooth_) { | |
147 | + _LargeRho = &Con2020::_LargeRhoEdwardsSmooth; | |
148 | + } else { | |
149 | + _LargeRho = &Con2020::_LargeRhoEdwards; | |
150 | + } | |
151 | + _SmallRho = &Con2020::_SmallRhoEdwards; | |
152 | + } else { | |
153 | + _LargeRho = &Con2020::_LargeRhoConnerney; | |
154 | + _SmallRho = &Con2020::_SmallRhoConnerney; | |
155 | + } | |
156 | + | |
157 | + /* now we need to set which model functions we will use | |
158 | + * (analytic, intergral or hybrid) */ | |
159 | + if (strcmp(eqtype_,"analytic") == 0) { | |
160 | + if (smooth_) { | |
161 | + _Model = &Con2020::_AnalyticSmooth; | |
162 | + } else { | |
163 | + _Model = &Con2020::_Analytic; | |
164 | + } | |
165 | + } else if (strcmp(eqtype_,"integral") == 0) { | |
166 | + _Model = &Con2020::_Integral; | |
167 | + } else if (strcmp(eqtype_,"hybrid") == 0) { | |
168 | + _Model = &Con2020::_Hybrid; | |
169 | + } else { | |
170 | + printf("What's going on here then?\n"); | |
171 | + } | |
172 | + | |
173 | + /* set the azimuthal function */ | |
174 | + if (strcmp(azfunc_,"connerney") == 0) { | |
175 | + _AzimuthalField = &Con2020::_BphiConnerney; | |
176 | + } else if (strcmp(azfunc_,"lmic") == 0) { | |
177 | + _AzimuthalField = &Con2020::_BphiLMIC; | |
178 | + } else { | |
179 | + printf("Azimuthal function %s not recognised\n",azfunc_); | |
180 | + } | |
181 | + | |
182 | +} | |
183 | + | |
184 | +void Con2020::_SysIII2Mag(int n, double *x0, double *y0, double *z0, | |
185 | + double *x1, double *y1, double *z1, double *rho, double *absz, | |
186 | + double *cost, double *sint, double *cosp, double *sinp) { | |
187 | + | |
188 | + | |
189 | + /* some temporary variables which get used more than once */ | |
190 | + double xt, theta, phi, r, rho0, rho0_sq; | |
191 | + | |
192 | + | |
193 | + int i; | |
194 | + for (i=0;i<n;i++) { | |
195 | + /*calculate some angles and stuff*/ | |
196 | + rho0_sq = x0[i]*x0[i] + y0[i]*y0[i]; | |
197 | + rho0 = sqrt(rho0_sq); | |
198 | + r = sqrt(rho0_sq + z0[i]*z0[i]); | |
199 | + | |
200 | + cost[i] = z0[i]/r; | |
201 | + sint[i] = rho0/r; | |
202 | + sinp[i] = y0[i]/rho0; | |
203 | + cosp[i] = x0[i]/rho0; | |
204 | + | |
205 | + /*rotate about z0 for the correct longitude */ | |
206 | + xt = rho0*(cosp[i]*cosxp_ + sinp[i]*sinxp_); | |
207 | + y1[i] = rho0*(sinp[i]*cosxp_ - cosp[i]*sinxp_); | |
208 | + | |
209 | + /*align with the current sheet */ | |
210 | + x1[i] = xt*cosxt_ + z0[i]*sinxt_; | |
211 | + z1[i] = z0[i]*cosxt_ - xt*sinxt_; | |
212 | + | |
213 | + /* calculate rho and abs(z) */ | |
214 | + rho[i] = sqrt(x1[i]*x1[i] + y1[i]*y1[i]); | |
215 | + absz[i] = fabs(z1[i]); | |
216 | + | |
217 | + } | |
218 | + | |
219 | + | |
220 | +} | |
221 | + | |
222 | +void Con2020::_PolSysIII2Mag(int n, double *r, double *t, double *p, | |
223 | + double *x1, double *y1, double *z1, double *rho, double *absz, | |
224 | + double *cost, double *sint, double *cosp, double *sinp) { | |
225 | + | |
226 | + | |
227 | + /* some temporary variables which get used more than once */ | |
228 | + double x, z; | |
229 | + | |
230 | + int i; | |
231 | + for (i=0;i<n;i++) { | |
232 | + /* temporary variables */ | |
233 | + sint[i] = sin(t[i]); | |
234 | + cost[i] = cos(t[i]); | |
235 | + sinp[i] = sin(p[i]); | |
236 | + cosp[i] = cos(p[i]); | |
237 | + | |
238 | + /*faster conversion code from con2020 */ | |
239 | + x = r[i]*sint[i]*(cosp[i]*cosxp_ + sinp[i]*sinxp_); | |
240 | + y1[i] = r[i]*sint[i]*(sinp[i]*cosxp_ - cosp[i]*sinxp_); | |
241 | + z = r[i]*cost[i]; | |
242 | + | |
243 | + /*newly rotated coords */ | |
244 | + x1[i] = x*cosxt_ + z*sinxt_; | |
245 | + z1[i] = z*cosxt_ - x*sinxt_; | |
246 | + | |
247 | + rho[i] = sqrt(x1[i]*x1[i] + y1[i]*y1[i]); | |
248 | + absz[i] = fabs(z1[i]); | |
249 | + | |
250 | + } | |
251 | + | |
252 | + | |
253 | +} | |
254 | + | |
255 | +void Con2020::_BMag2SysIII(int n, double *x1, double *y1, double *rho1, | |
256 | + double *cost, double *sint, double *cosp, double *sinp, | |
257 | + double *Brho1, double *Bphi1, double *Bz1, | |
258 | + double *Bx0, double *By0, double *Bz0) { | |
259 | + | |
260 | + double cosp1, sinp1, Bx, Bx1, By1; | |
261 | + | |
262 | + int i; | |
263 | + for (i=0;i<n;i++) { | |
264 | + /* rotating longitude */ | |
265 | + cosp1 = x1[i]/rho1[i]; | |
266 | + sinp1 = y1[i]/rho1[i]; | |
267 | + Bx1 = Brho1[i]*cosp1 - Bphi1[i]*sinp1; | |
268 | + By1 = Brho1[i]*sinp1 + Bphi1[i]*cosp1; | |
269 | + | |
270 | + /* rotate back by dipole tilt */ | |
271 | + Bx = Bx1*cosxt_ - Bz1[i]*sinxt_; | |
272 | + Bz0[i] = Bx1*sinxt_ + Bz1[i]*cosxt_; | |
273 | + | |
274 | + /* shift to System III */ | |
275 | + Bx0[i] = Bx*cosxp_ - By1*sinxp_; | |
276 | + By0[i] = By1*cosxp_ + Bx*sinxp_; | |
277 | + | |
278 | + } | |
279 | + | |
280 | +} | |
281 | + | |
282 | +void Con2020::_BMag2PolSysIII(int n, double *x1, double *y1, double *rho1, | |
283 | + double *cost, double *sint, double *cosp, double *sinp, | |
284 | + double *Brho1, double *Bphi1, double *Bz1, | |
285 | + double *Br0, double *Bt0, double *Bp0) { | |
286 | + | |
287 | + double cosp1, sinp1, Bx, Bz, Bx1, By1, Bx2, By2; | |
288 | + | |
289 | + | |
290 | + int i; | |
291 | + for (i=0;i<n;i++) { | |
292 | + | |
293 | + /* rotating longitude */ | |
294 | + cosp1 = x1[i]/rho1[i]; | |
295 | + sinp1 = y1[i]/rho1[i]; | |
296 | + Bx1 = Brho1[i]*cosp1 - Bphi1[i]*sinp1; | |
297 | + By1 = Brho1[i]*sinp1 + Bphi1[i]*cosp1; | |
298 | + | |
299 | + /* rotate back by dipole tilt */ | |
300 | + Bx = Bx1*cosxt_ - Bz1[i]*sinxt_; | |
301 | + Bz = Bx1*sinxt_ + Bz1[i]*cosxt_; | |
302 | + | |
303 | + /* shift to System III */ | |
304 | + Bx2 = Bx*cosxp_ - By1*sinxp_; | |
305 | + By2 = By1*cosxp_ + Bx*sinxp_; | |
306 | + | |
307 | + /* convert to polar */ | |
308 | + Br0[i] = Bx2*sint[i]*cosp[i] + By2*sint[i]*sinp[i] + Bz*cost[i]; | |
309 | + Bt0[i] = Bx2*cost[i]*cosp[i] + By2*cost[i]*sinp[i] - Bz*sint[i]; | |
310 | + Bp0[i] = -Bx2*sinp[i] + By2*cosp[i]; | |
311 | + | |
312 | + } | |
313 | + | |
314 | +} | |
315 | + | |
316 | +void Con2020::_BphiConnerney(int n, double *rho, double *z, double *absz, double *Bphi) { | |
317 | + | |
318 | + int i; | |
319 | + for (i=0;i<n;i++) { | |
320 | + Bphi[i] = 2.7975*irho_/rho[i]; | |
321 | + | |
322 | + if (absz[i] < d_) { | |
323 | + Bphi[i] = Bphi[i]*absz[i]/d_; | |
324 | + } | |
325 | + | |
326 | + if (z[i] > 0.0) { | |
327 | + Bphi[i] = -Bphi[i]; | |
328 | + } | |
329 | + | |
330 | + } | |
331 | +} | |
332 | + | |
333 | +void Con2020::_BphiConnerney(double rho, double absz, double z, double *Bphi) { | |
334 | + | |
335 | + Bphi[0] = 2.7975*irho_/rho; | |
336 | + | |
337 | + if (absz < d_) { | |
338 | + Bphi[0] = Bphi[0]*absz/d_; | |
339 | + } | |
340 | + | |
341 | + if (z > 0.0) { | |
342 | + Bphi[0] = -Bphi[0]; | |
343 | + } | |
344 | +} | |
345 | + | |
346 | +void Con2020::_BphiLMIC(double rho, double absz, double z, double *Bphi) { | |
347 | + | |
348 | + double r = sqrt(rho*rho + z*z); | |
349 | + double theta = asin(rho/r); | |
350 | + | |
351 | + Bphi[0] = BphiLMIC(r,theta,g_,r0_,r1_,mui_,d_,deltarho_,deltaz_, | |
352 | + wO_open_,wO_om_,thetamm_,dthetamm_,thetaoc_,dthetaoc_); | |
353 | + | |
354 | +} | |
355 | + | |
356 | +void Con2020::Field(double p0, double p1, double p2, | |
357 | + double *B0, double *B1, double *B2) { | |
358 | + | |
359 | + /* create a bunch of empty variables */ | |
360 | + double x, y, z, rho, absz; | |
361 | + double cost, sint, cosp, sinp; | |
362 | + double Brho, Bphi, Bz; | |
363 | + | |
364 | + /* convert the input coordinates */ | |
365 | + (this->*_ConvInput)(1,&p0,&p1,&p2,&x,&y,&z,&rho,&absz,&cost,&sint,&cosp,&sinp); | |
366 | + | |
367 | + /* calculate the mode field */ | |
368 | + (this->*_Model)(rho,absz,z,&Brho,&Bphi,&Bz); | |
369 | + | |
370 | + /*convert the output field */ | |
371 | + (this->*_ConvOutput)(1,&x,&y,&rho,&cost,&sint,&cosp,&sinp,&Brho,&Bphi,&Bz,B0,B1,B2); | |
372 | +} | |
373 | + | |
374 | + | |
375 | +void Con2020::Field(int n, double *p0, double *p1, double *p2, | |
376 | + double *B0, double *B1, double *B2) { | |
377 | + | |
378 | + int i; | |
379 | + | |
380 | + /* allocate arrays to store model coordinates and fields */ | |
381 | + double *x = new double[n]; | |
382 | + double *y = new double[n]; | |
383 | + double *z = new double[n]; | |
384 | + double *absz = new double[n]; | |
385 | + double *sint = new double[n]; | |
386 | + double *sinp = new double[n]; | |
387 | + double *cost = new double[n]; | |
388 | + double *cosp = new double[n]; | |
389 | + double *rho = new double[n]; | |
390 | + double *Brho = new double[n]; | |
391 | + double *Bphi = new double[n]; | |
392 | + double *Bz = new double[n]; | |
393 | + | |
394 | + /* convert input coordinates to the coordinate system used by the model */ | |
395 | + (this->*_ConvInput)(n,p0,p1,p2,x,y,z,rho,absz,cost,sint,cosp,sinp); | |
396 | + | |
397 | + /* call the model */ | |
398 | + for (i=0;i<n;i++) { | |
399 | + (this->*_Model)(rho[i],absz[i],z[i],&Brho[i],&Bphi[i],&Bz[i]); | |
400 | + } | |
401 | + | |
402 | + /* convert B field back to appropriate coordinate system */ | |
403 | + (this->*_ConvOutput)(n,x,y,rho,cost,sint,cosp,sinp,Brho,Bphi,Bz,B0,B1,B2); | |
404 | + | |
405 | + /* delete temporary variables */ | |
406 | + delete[] x; | |
407 | + delete[] y; | |
408 | + delete[] z; | |
409 | + delete[] absz; | |
410 | + delete[] rho; | |
411 | + delete[] sint; | |
412 | + delete[] sinp; | |
413 | + delete[] cost; | |
414 | + delete[] cosp; | |
415 | + delete[] Brho; | |
416 | + delete[] Bphi; | |
417 | + delete[] Bz; | |
418 | + | |
419 | + | |
420 | +} | |
421 | + | |
422 | + | |
423 | + | |
424 | + | |
425 | + | |
426 | + | |
427 | +void Con2020::AnalyticFieldSmooth(double a, | |
428 | + double rho, double z, | |
429 | + double *Brho, double *Bz) { | |
430 | + | |
431 | + /* define a few required variables */ | |
432 | + double zpd = z + d_; | |
433 | + double zmd = z - d_; | |
434 | + | |
435 | + /* define some temporary variables */ | |
436 | + double Brho0, Brho1, Bz0, Bz1; | |
437 | + double tanhrho, C0, C1; | |
438 | + double asq = a*a; | |
439 | + | |
440 | + /* calculate small and large rho approximations | |
441 | + * NOTE: Add smoothed functions for small and large rho */ | |
442 | + (this->*_LargeRho)(rho,z,zmd,zpd,asq,&Brho1,&Bz1); | |
443 | + (this->*_SmallRho)(rho,z,zmd,zpd,asq,&Brho0,&Bz0); | |
444 | + | |
445 | + /* calculate the tanh smoothing parameters */ | |
446 | + tanhrho = tanh((rho-a)/deltarho_); | |
447 | + C0 = (1-tanhrho)/2.0; | |
448 | + C1 = (1+tanhrho)/2.0; | |
449 | + | |
450 | + /* splice together as suggested by Stan */ | |
451 | + *Brho = Brho0*C0 + Brho1*C1; | |
452 | + *Bz = Bz0*C0 + Bz1*C1; | |
453 | + | |
454 | + | |
455 | +} | |
456 | + | |
457 | +void Con2020::AnalyticField(double a, | |
458 | + double rho, double z, | |
459 | + double *Brho, double *Bz) { | |
460 | + | |
461 | + /* define a few required variables */ | |
462 | + double zpd = z + d_; | |
463 | + double zmd = z - d_; | |
464 | + | |
465 | + /* define some temporary variables */ | |
466 | + double asq = a*a; | |
467 | + | |
468 | + /* calculate small and large rho approximations */ | |
469 | + if (rho >= a) { | |
470 | + (this->*_LargeRho)(rho,z,zmd,zpd,asq,Brho,Bz); | |
471 | + } else { | |
472 | + (this->*_SmallRho)(rho,z,zmd,zpd,asq,Brho,Bz); | |
473 | + } | |
474 | + | |
475 | + | |
476 | + | |
477 | +} | |
478 | + | |
479 | +void Con2020::_Analytic(double rho, double absz, double z, | |
480 | + double *Brho, double *Bphi, double *Bz) { | |
481 | + | |
482 | + /* calculate the inner contribution to Brho and Bz */ | |
483 | + _AnalyticInner(rho,z,Brho,Bz); | |
484 | + | |
485 | + /* also the azimuthal field */ | |
486 | + (this->*_AzimuthalField)(rho,absz,z,Bphi); | |
487 | + | |
488 | + /* we need to calculate the outer edge contribution */ | |
489 | + double oBrho, oBz; | |
490 | + _AnalyticOuter(rho,z,&oBrho,&oBz); | |
491 | + | |
492 | + /*subtract it */ | |
493 | + Brho[0] -= oBrho; | |
494 | + Bz[0] -= oBz; | |
495 | + | |
496 | +} | |
497 | + | |
498 | +void Con2020::_AnalyticSmooth(double rho, double absz, double z, | |
499 | + double *Brho, double *Bphi, double *Bz) { | |
500 | + | |
501 | + /* calculate the inner contribution to Brho and Bz */ | |
502 | + _AnalyticInnerSmooth(rho,z,Brho,Bz); | |
503 | + | |
504 | + /* also the azimuthal field */ | |
505 | + (this->*_AzimuthalField)(rho,absz,z,Bphi); | |
506 | + | |
507 | + /* we need to calculate the outer edge contribution */ | |
508 | + double oBrho, oBz; | |
509 | + _AnalyticOuterSmooth(rho,z,&oBrho,&oBz); | |
510 | + | |
511 | + /*subtract it */ | |
512 | + Brho[0] -= oBrho; | |
513 | + Bz[0] -= oBz; | |
514 | + | |
515 | +} | |
516 | + | |
517 | +void Con2020::_AnalyticInner( double rho, double z, | |
518 | + double *Brho, double *Bz) { | |
519 | + | |
520 | + /* define a few required variables */ | |
521 | + double zpd = z + d_; | |
522 | + double zmd = z - d_; | |
523 | + | |
524 | + if (rho >= r0_) { | |
525 | + (this->*_LargeRho)(rho,z,zmd,zpd,r0sq_,Brho,Bz); | |
526 | + } else { | |
527 | + (this->*_SmallRho)(rho,z,zmd,zpd,r0sq_,Brho,Bz); | |
528 | + } | |
529 | + | |
530 | +} | |
531 | + | |
532 | +void Con2020::_AnalyticInnerSmooth( double rho, double z, | |
533 | + double *Brho, double *Bz) { | |
534 | + | |
535 | + /* define a few required variables */ | |
536 | + double zpd = z + d_; | |
537 | + double zmd = z - d_; | |
538 | + | |
539 | + /* define some temporary variables */ | |
540 | + double Brho0, Brho1, Bz0, Bz1; | |
541 | + double tanhrho, C0, C1; | |
542 | + | |
543 | + /* calculate small and large rho approximations | |
544 | + * NOTE: Add smoothed functions for small and large rho */ | |
545 | + (this->*_LargeRho)(rho,z,zmd,zpd,r0sq_,&Brho1,&Bz1); | |
546 | + (this->*_SmallRho)(rho,z,zmd,zpd,r0sq_,&Brho0,&Bz0); | |
547 | + | |
548 | + /* calculate the tanh smoothing parameters */ | |
549 | + tanhrho = tanh((rho-r0_)/deltarho_); | |
550 | + C0 = (1-tanhrho)/2.0; | |
551 | + C1 = (1+tanhrho)/2.0; | |
552 | + | |
553 | + /* splice together as suggested by Stan */ | |
554 | + *Brho = Brho0*C0 + Brho1*C1; | |
555 | + *Bz = Bz0*C0 + Bz1*C1; | |
556 | + | |
557 | + | |
558 | +} | |
559 | + | |
560 | +void Con2020::_AnalyticOuter( double rho, double z, | |
561 | + double *Brho, double *Bz) { | |
562 | + | |
563 | + /* define a few required variables */ | |
564 | + double zpd = z + d_; | |
565 | + double zmd = z - d_; | |
566 | + | |
567 | + if (rho >= r1_) { | |
568 | + (this->*_LargeRho)(rho,z,zmd,zpd,r1sq_,Brho,Bz); | |
569 | + } else { | |
570 | + (this->*_SmallRho)(rho,z,zmd,zpd,r1sq_,Brho,Bz); | |
571 | + } | |
572 | + | |
573 | +} | |
574 | + | |
575 | + | |
576 | +void Con2020::_AnalyticOuterSmooth( double rho, double z, | |
577 | + double *Brho, double *Bz) { | |
578 | + | |
579 | + /* define a few required variables */ | |
580 | + double zpd = z + d_; | |
581 | + double zmd = z - d_; | |
582 | + | |
583 | + /* define some temporary variables */ | |
584 | + double Brho0, Brho1, Bz0, Bz1; | |
585 | + double tanhrho, C0, C1; | |
586 | + | |
587 | + /* calculate small and large rho approximations | |
588 | + * NOTE: Add smoothed functions for small and large rho */ | |
589 | + (this->*_LargeRho)(rho,z,zmd,zpd,r1sq_,&Brho1,&Bz1); | |
590 | + (this->*_SmallRho)(rho,z,zmd,zpd,r1sq_,&Brho0,&Bz0); | |
591 | + | |
592 | + /* calculate the tanh smoothing parameters */ | |
593 | + tanhrho = tanh((rho-r1_)/deltarho_); | |
594 | + C0 = (1-tanhrho)/2.0; | |
595 | + C1 = (1+tanhrho)/2.0; | |
596 | + | |
597 | + /* splice together as suggested by Stan */ | |
598 | + *Brho = Brho0*C0 + Brho1*C1; | |
599 | + *Bz = Bz0*C0 + Bz1*C1; | |
600 | + | |
601 | + | |
602 | +} | |
603 | + | |
604 | + | |
605 | +void Con2020::_LargeRhoConnerney(double rho, double z, double zmd, | |
606 | + double zpd, double a2, double *Brho, double *Bz) { | |
607 | + | |
608 | + /* some common variables */ | |
609 | + double zmd2 = zmd*zmd; | |
610 | + double zpd2 = zpd*zpd; | |
611 | + double rho2 = rho*rho; | |
612 | + double f1 = sqrt(zmd2 + rho2); | |
613 | + double f2 = sqrt(zpd2 + rho2); | |
614 | + double f1cubed = f1*f1*f1; | |
615 | + double f2cubed = f2*f2*f2; | |
616 | + | |
617 | + /* Equation A7 */ | |
618 | + double termr0 = (1.0/rho)*(f1 -f2 + 2*clip(z,-d_,d_)); | |
619 | + double termr1 = (a2*rho/4.0)*(1/f1cubed - 1/f2cubed); | |
620 | + Brho[0] = mui_*(termr0 - termr1); | |
621 | + | |
622 | + /* Equation A8 */ | |
623 | + double termz0 = 2*d_/sqrt(z*z + rho*rho); | |
624 | + double termz1 = (a2/4.0)*(zmd/f1cubed - zpd/f2cubed); | |
625 | + Bz[0] = mui_*(termz0 - termz1); | |
626 | + | |
627 | +} | |
628 | + | |
629 | +void Con2020::_SmallRhoConnerney(double rho, double z, double zmd, double zpd, | |
630 | + double a2, double *Brho, double *Bz) { | |
631 | + | |
632 | + double zmd2 = zmd*zmd; | |
633 | + double zpd2 = zpd*zpd; | |
634 | + double f1 = sqrt(zmd2 + a2); | |
635 | + double f2 = sqrt(zpd2 + a2); | |
636 | + double f1cubed = f1*f1*f1; | |
637 | + double f2cubed = f2*f2*f2; | |
638 | + | |
639 | + /* Equation A1 */ | |
640 | + Brho[0] = mui_*(rho/2.0)*(1.0/f1 - 1.0/f2); | |
641 | + | |
642 | + /* Equation A2 */ | |
643 | + Bz[0] = mui_*(2*d_*(1/sqrt(z*z + a2)) - ((rho*rho)/4)*((zmd/f1cubed) - (zpd/f2cubed))); | |
644 | + | |
645 | +} | |
646 | + | |
647 | + | |
648 | +void Con2020::_LargeRhoEdwards(double rho, double z, double zmd, | |
649 | + double zpd, double a2,double *Brho, double *Bz) { | |
650 | + | |
651 | + | |
652 | + /* some common variables */ | |
653 | + double zmd2 = zmd*zmd; | |
654 | + double zpd2 = zpd*zpd; | |
655 | + double rho2 = rho*rho; | |
656 | + double f1 = sqrt(zmd2 + rho2); | |
657 | + double f2 = sqrt(zpd2 + rho2); | |
658 | + double f1cubed = f1*f1*f1; | |
659 | + double f2cubed = f2*f2*f2; | |
660 | + | |
661 | + /* equation 13a */ | |
662 | + double terma0 = (1.0/rho)*(f1 - f2); | |
663 | + double terma1 = (rho*a2/4)*(1.0/f2cubed - 1.0/f1cubed); | |
664 | + double terma2 = (2.0/rho)*clip(z,-d_,d_); | |
665 | + Brho[0] = mui_*(terma0 + terma1 + terma2); | |
666 | + | |
667 | + /* equation 13b */ | |
668 | + double termb0 = log((zpd + f2)/(zmd + f1)); | |
669 | + double termb1 = (a2/4.0)*(zpd/f2cubed - zmd/f1cubed); | |
670 | + Bz[0] = mui_*(termb0 + termb1); | |
671 | +} | |
672 | + | |
673 | +void Con2020::_LargeRhoEdwardsSmooth(double rho, double z, double zmd, | |
674 | + double zpd, double a2,double *Brho, double *Bz) { | |
675 | + | |
676 | + /* some common variables */ | |
677 | + double zmd2 = zmd*zmd; | |
678 | + double zpd2 = zpd*zpd; | |
679 | + double rho2 = rho*rho; | |
680 | + double f1 = sqrt(zmd2 + rho2); | |
681 | + double f2 = sqrt(zpd2 + rho2); | |
682 | + double f1cubed = f1*f1*f1; | |
683 | + double f2cubed = f2*f2*f2; | |
684 | + | |
685 | + /* equation 13a */ | |
686 | + double terma0 = (1.0/rho)*(f1 - f2); | |
687 | + double terma1 = (rho*a2/4)*(1.0/f2cubed - 1.0/f1cubed); | |
688 | + double terma2 = (2.0/rho)*smoothd(z,deltaz_,d_); | |
689 | + Brho[0] = mui_*(terma0 + terma1 + terma2); | |
690 | + | |
691 | + /* equation 13b */ | |
692 | + double termb0 = log((zpd + f2)/(zmd + f1)); | |
693 | + double termb1 = (a2/4.0)*(zpd/f2cubed - zmd/f1cubed); | |
694 | + Bz[0] = mui_*(termb0 + termb1); | |
695 | +} | |
696 | + | |
697 | + | |
698 | +void Con2020::_SmallRhoEdwards(double rho, double z, double zmd, double zpd, | |
699 | + double a2, double *Brho, double *Bz) { | |
700 | + | |
701 | + double zmd2 = zmd*zmd; | |
702 | + double zpd2 = zpd*zpd; | |
703 | + double f1 = sqrt(zmd2 + a2); | |
704 | + double f2 = sqrt(zpd2 + a2); | |
705 | + double f1cubed = f1*f1*f1; | |
706 | + double f2cubed = f2*f2*f2; | |
707 | + | |
708 | + /* calculate some of the common terms from equations 9a and 9b */ | |
709 | + double rhoov2 = rho/2.0; | |
710 | + double rho2ov4 = rhoov2*rhoov2; | |
711 | + double rho3ov16 = rho2ov4*rhoov2/2.0; | |
712 | + | |
713 | + /* equation 9a */ | |
714 | + double f3a = f1*f1; | |
715 | + double f4a = f2*f2; | |
716 | + double f3 = (a2 - 2*zmd2)/(f3a*f3a*f1); | |
717 | + double f4 = (a2 - 2*zpd2)/(f4a*f4a*f2); | |
718 | + | |
719 | + double terma0 = rhoov2*(1.0/f1 - 1.0/f2); | |
720 | + double terma1 = rho3ov16*(f3 - f4); | |
721 | + | |
722 | + Brho[0] = mui_*(terma0 + terma1); | |
723 | + | |
724 | + /* equation 9b */ | |
725 | + double termb0 = log((zpd + f2)/(zmd + f1)); | |
726 | + double termb1 = rho2ov4*(zpd/f2cubed - zmd/f1cubed); | |
727 | + Bz[0] = mui_*(termb0 + termb1); | |
728 | +} | |
729 | + | |
730 | + | |
731 | +void Con2020::_InitIntegrals() { | |
732 | + | |
733 | + /* the lambda max values for brho and bz */ | |
734 | + double lmx_brho, lmx_bz; | |
735 | + rlmx_array_[0] = 4.0; | |
736 | + rlmx_array_[1] = 4.0; | |
737 | + rlmx_array_[2] = 40.0; | |
738 | + rlmx_array_[3] = 40.0; | |
739 | + rlmx_array_[4] = 100.0; | |
740 | + rlmx_array_[5] = 100.0; | |
741 | + zlmx_array_[0] = 100.0; | |
742 | + zlmx_array_[1] = 20.0; | |
743 | + zlmx_array_[2] = 100.0; | |
744 | + zlmx_array_[3] = 20.0; | |
745 | + zlmx_array_[4] = 100.0; | |
746 | + zlmx_array_[5] = 20.0; | |
747 | + | |
748 | + | |
749 | + /* initialize the bessel functions which do not change */ | |
750 | + rnbes_ = new int[6]; | |
751 | + znbes_ = new int[6]; | |
752 | + rlambda_ = new double*[6]; | |
753 | + zlambda_ = new double*[6]; | |
754 | + rj0_lambda_r0_ = new double*[6]; | |
755 | + zj0_lambda_r0_ = new double*[6]; | |
756 | + | |
757 | + /*These functions do change and will need reassigning | |
758 | + * for each run of the integral function*/ | |
759 | + rj1_lambda_rho_ = new double*[6]; | |
760 | + zj0_lambda_rho_ = new double*[6]; | |
761 | + | |
762 | + /*these will store bits of the Connerney et al 1981 equations which | |
763 | + * don't change*/ | |
764 | + Eq14_ = new double*[6]; | |
765 | + Eq15_ = new double*[6]; | |
766 | + Eq17_ = new double*[6]; | |
767 | + Eq18_ = new double*[6]; | |
768 | + ExpLambdaD_ = new double*[6]; | |
769 | + | |
770 | + | |
771 | + /* initialize the second dimensions */ | |
772 | + int zcase, i; | |
773 | + double ld; | |
774 | + for (zcase=0;zcase<6;zcase++) { | |
775 | + /* calculate the length of the arrays for each case */ | |
776 | + rnbes_[zcase] = (int) (rlmx_array_[zcase]/dlambda_brho_) - 1; | |
777 | + znbes_[zcase] = (int) (zlmx_array_[zcase]/dlambda_bz_) - 1; | |
778 | + | |
779 | + /* allocate the second dimension */ | |
780 | + rlambda_[zcase] = new double[rnbes_[zcase]]; | |
781 | + zlambda_[zcase] = new double[znbes_[zcase]]; | |
782 | + rj0_lambda_r0_[zcase] = new double[rnbes_[zcase]]; | |
783 | + zj0_lambda_r0_[zcase] = new double[znbes_[zcase]]; | |
784 | + rj1_lambda_rho_[zcase] = new double[rnbes_[zcase]]; | |
785 | + zj0_lambda_rho_[zcase] = new double[znbes_[zcase]]; | |
786 | + Eq14_[zcase] = new double[rnbes_[zcase]]; | |
787 | + Eq15_[zcase] = new double[znbes_[zcase]]; | |
788 | + Eq17_[zcase] = new double[rnbes_[zcase]]; | |
789 | + Eq18_[zcase] = new double[znbes_[zcase]]; | |
790 | + ExpLambdaD_[zcase] = new double[znbes_[zcase]]; | |
791 | + } | |
792 | + | |
793 | + _RecalcIntegrals(); | |
794 | +} | |
795 | + | |
796 | +void Con2020::_RecalcIntegrals(){ | |
797 | + | |
798 | + int zcase, i; | |
799 | + double ld; | |
800 | + for (zcase=0;zcase<6;zcase++) { | |
801 | + /* initialize lambda for z and rho cases */ | |
802 | + for (i=0;i<rnbes_[zcase];i++) { | |
803 | + rlambda_[zcase][i] = (i+1)*dlambda_brho_; | |
804 | + } | |
805 | + for (i=0;i<znbes_[zcase];i++) { | |
806 | + zlambda_[zcase][i] = (i+1)*dlambda_bz_; | |
807 | + } | |
808 | + | |
809 | + /* calculate j0(r0*lambda) */ | |
810 | + j0(rnbes_[zcase],&rlambda_[zcase][0],r0_,&rj0_lambda_r0_[zcase][0]); | |
811 | + j0(znbes_[zcase],&zlambda_[zcase][0],r0_,&zj0_lambda_r0_[zcase][0]); | |
812 | + | |
813 | + /* equations */ | |
814 | + for (i=0;i<rnbes_[zcase];i++) { | |
815 | + ld = d_*rlambda_[zcase][i]; | |
816 | + Eq14_[zcase][i] = rj0_lambda_r0_[zcase][i]*sinh(ld)/rlambda_[zcase][i]; | |
817 | + Eq17_[zcase][i] = rj0_lambda_r0_[zcase][i]*exp(-ld)/rlambda_[zcase][i]; | |
818 | + } | |
819 | + for (i=0;i<znbes_[zcase];i++) { | |
820 | + ld = d_*zlambda_[zcase][i]; | |
821 | + Eq15_[zcase][i] = zj0_lambda_r0_[zcase][i]*sinh(ld)/zlambda_[zcase][i]; | |
822 | + Eq18_[zcase][i] = zj0_lambda_r0_[zcase][i]/zlambda_[zcase][i]; | |
823 | + ExpLambdaD_[zcase][i] = exp(-ld); | |
824 | + } | |
825 | + } | |
826 | + | |
827 | + | |
828 | +} | |
829 | + | |
830 | +void Con2020::_DeleteIntegrals() { | |
831 | + | |
832 | + int i; | |
833 | + for (i=0;i<6;i++) { | |
834 | + delete[] rlambda_[i]; | |
835 | + delete[] zlambda_[i]; | |
836 | + delete[] rj0_lambda_r0_[i]; | |
837 | + delete[] rj1_lambda_rho_[i]; | |
838 | + delete[] zj0_lambda_r0_[i]; | |
839 | + delete[] zj0_lambda_rho_[i]; | |
840 | + delete[] Eq14_[i]; | |
841 | + delete[] Eq15_[i]; | |
842 | + delete[] Eq17_[i]; | |
843 | + delete[] Eq18_[i]; | |
844 | + delete[] ExpLambdaD_[i]; | |
845 | + } | |
846 | + | |
847 | + delete[] rlambda_; | |
848 | + delete[] zlambda_; | |
849 | + delete[] rj0_lambda_r0_; | |
850 | + delete[] rj1_lambda_rho_; | |
851 | + delete[] zj0_lambda_r0_; | |
852 | + delete[] zj0_lambda_rho_; | |
853 | + delete[] Eq14_; | |
854 | + delete[] Eq15_; | |
855 | + delete[] Eq17_; | |
856 | + delete[] Eq18_; | |
857 | + delete[] ExpLambdaD_; | |
858 | + delete[] rnbes_; | |
859 | + delete[] znbes_; | |
860 | +} | |
861 | + | |
862 | +void Con2020::_Integral(double rho, double absz, double z, | |
863 | + double *Brho, double *Bphi, double *Bz) { | |
864 | + | |
865 | + /* calculate the inner contribution to Brho and Bz */ | |
866 | + _IntegralInner(rho,absz,z,Brho,Bz); | |
867 | + | |
868 | + /* also the azimuthal field */ | |
869 | + (this->*_AzimuthalField)(rho,absz,z,Bphi); | |
870 | + | |
871 | + /* we need to calculate the outer edge contribution */ | |
872 | + double oBrho, oBz; | |
873 | + _AnalyticOuter(rho,z,&oBrho,&oBz); | |
874 | + | |
875 | + /*subtract it */ | |
876 | + Brho[0] -= oBrho; | |
877 | + Bz[0] -= oBz; | |
878 | + | |
879 | +} | |
880 | + | |
881 | + | |
882 | +void Con2020::_IntegralChecks(int n, double *absz, int *chind, int ncase[]) { | |
883 | + | |
884 | + int i; | |
885 | + double check1; | |
886 | + bool check2; | |
887 | + | |
888 | + for (i=0;i<6;i++) { | |
889 | + ncase[i] = 0; | |
890 | + } | |
891 | + | |
892 | + for (i=0;i<n;i++) { | |
893 | + check1 = fabs(absz[i] - d_); | |
894 | + check2 = (absz[i] < d_*1.1); | |
895 | + | |
896 | + if (check1 >= 0.7) { | |
897 | + chind[i] = 1; | |
898 | + } else if (check1 < 0.1) { | |
899 | + chind[i] = 5; | |
900 | + } else { | |
901 | + chind[i] = 3; | |
902 | + } | |
903 | + chind[i] -= ((int) check2); | |
904 | + ncase[chind[i]]++; | |
905 | + } | |
906 | + | |
907 | +} | |
908 | + | |
909 | +void Con2020::_IntegralCheck(double absz, int *chind) { | |
910 | + | |
911 | + int i; | |
912 | + double check1; | |
913 | + bool check2; | |
914 | + | |
915 | + | |
916 | + check1 = fabs(absz - d_); | |
917 | + check2 = (absz < d_*1.1); | |
918 | + | |
919 | + if (check1 >= 0.7) { | |
920 | + chind[0] = 1; | |
921 | + } else if (check1 < 0.1) { | |
922 | + chind[0] = 5; | |
923 | + } else { | |
924 | + chind[0] = 3; | |
925 | + } | |
926 | + chind[0] -= ((int) check2); | |
927 | + | |
928 | + | |
929 | +} | |
930 | + | |
931 | +void Con2020::_SolveIntegral(int n, double *rho, double *z, | |
932 | + double *absz, double *Brho, double *Bz) { | |
933 | + | |
934 | + int i, zcase, ncase[6]; | |
935 | + | |
936 | + | |
937 | + /* calculate the "checks" */ | |
938 | + int *chind = new int[n]; | |
939 | + _IntegralChecks(n,absz,chind,ncase); | |
940 | + | |
941 | + /* loop through each position */ | |
942 | + double br, bz; | |
943 | + for (i=0;i<n;i++) { | |
944 | + if (absz[i] > d_) { | |
945 | + /* in this case we want to use equations 14 and 15 outside | |
946 | + * of the finite current sheet */ | |
947 | + _IntegrateEq14(chind[i],rho[i],z[i],absz[i],&Brho[i]); | |
948 | + _IntegrateEq15(chind[i],rho[i],absz[i],&Bz[i]); | |
949 | + | |
950 | + } else { | |
951 | + /* here we are inside the current sheet and should integrate | |
952 | + * equations 17 and 18 */ | |
953 | + _IntegrateEq17(chind[i],rho[i],z[i],&Brho[i]); | |
954 | + _IntegrateEq18(chind[i],rho[i],z[i],&Bz[i]); | |
955 | + } | |
956 | + } | |
957 | + | |
958 | + delete[] chind; | |
959 | + | |
960 | +} | |
961 | + | |
962 | +void Con2020::_IntegralInner( double rho, double absz, double z, | |
963 | + double *Brho, double *Bz) { | |
964 | + //printf("\n_IntegralInner\n"); | |
965 | + int chind; | |
966 | + /* check which set of integral parameters we need to use*/ | |
967 | + _IntegralCheck(absz,&chind); | |
968 | + | |
969 | + if (absz > d_) { | |
970 | + /* in this case we want to use equations 14 and 15 outside | |
971 | + * of the finite current sheet */ | |
972 | + _IntegrateEq14(chind,rho,z,absz,Brho); | |
973 | + _IntegrateEq15(chind,rho,absz,Bz); | |
974 | + } else { | |
975 | + /* here we are inside the current sheet and should integrate | |
976 | + * equations 17 and 18 */ | |
977 | + _IntegrateEq17(chind,rho,z,Brho); | |
978 | + _IntegrateEq18(chind,rho,z,Bz); | |
979 | + } | |
980 | + | |
981 | +} | |
982 | + | |
983 | +void Con2020::_IntegrateEq14(int zcase, double rho, double z, double absz, double *Brho) { | |
984 | + | |
985 | + /* create an array to integrate over */ | |
986 | + int n = rnbes_[zcase]; | |
987 | + double *func = new double[n]; | |
988 | + double *j1lr = new double[n]; | |
989 | + | |
990 | + /* calculate the other bessel function */ | |
991 | + j1(n,&rlambda_[zcase][0],rho,j1lr); | |
992 | + | |
993 | + | |
994 | + /* calculate the function */ | |
995 | + int i; | |
996 | + for (i=0;i<n;i++) { | |
997 | + func[i] = Eq14_[zcase][i]*j1lr[i]*exp(-rlambda_[zcase][i]*absz); | |
998 | + } | |
999 | + | |
1000 | + /* integrate it */ | |
1001 | + Brho[0] = sgn(z)*2.0*mui_*trapc(n,dlambda_brho_,func); | |
1002 | + | |
1003 | + delete[] func; | |
1004 | + delete[] j1lr; | |
1005 | + | |
1006 | +} | |
1007 | + | |
1008 | + | |
1009 | +void Con2020::_IntegrateEq15(int zcase, double rho, double absz, double *Bz) { | |
1010 | + | |
1011 | + /* create an array to integrate over */ | |
1012 | + int n = znbes_[zcase]; | |
1013 | + double *func = new double[n]; | |
1014 | + double *j0lr = new double[n]; | |
1015 | + | |
1016 | + /* calculate the other bessel function */ | |
1017 | + j0(n,&zlambda_[zcase][0],rho,j0lr); | |
1018 | + | |
1019 | + | |
1020 | + /* calculate the function */ | |
1021 | + int i; | |
1022 | + for (i=0;i<n;i++) { | |
1023 | + func[i] = Eq15_[zcase][i]*j0lr[i]*exp(-zlambda_[zcase][i]*absz); | |
1024 | + } | |
1025 | + | |
1026 | + /* integrate it */ | |
1027 | + Bz[0] = 2.0*mui_*trapc(n,dlambda_bz_,func); | |
1028 | + | |
1029 | + delete[] func; | |
1030 | + delete[] j0lr; | |
1031 | + | |
1032 | +} | |
1033 | + | |
1034 | + | |
1035 | + | |
1036 | +void Con2020::_IntegrateEq17(int zcase, double rho, double z, double *Brho) { | |
1037 | + | |
1038 | + /* create an array to integrate over */ | |
1039 | + int n = rnbes_[zcase]; | |
1040 | + double *func = new double[n]; //these arrays can be pre-allocated for overwriting | |
1041 | + double *j1lr = new double[n]; | |
1042 | + | |
1043 | + /* calculate the other bessel function */ | |
1044 | + j1(n,&rlambda_[zcase][0],rho,j1lr); | |
1045 | + | |
1046 | + | |
1047 | + /* calculate the function */ | |
1048 | + int i; | |
1049 | + for (i=0;i<n;i++) { | |
1050 | + func[i] = Eq17_[zcase][i]*j1lr[i]*sinh(rlambda_[zcase][i]*z); | |
1051 | + } | |
1052 | + | |
1053 | + /* integrate it */ | |
1054 | + Brho[0] = 2.0*mui_*trapc(n,dlambda_brho_,func); | |
1055 | + | |
1056 | + delete[] func; | |
1057 | + delete[] j1lr; | |
1058 | + | |
1059 | +} | |
1060 | + | |
1061 | + | |
1062 | +void Con2020::_IntegrateEq18(int zcase, double rho, double z, double *Bz) { | |
1063 | + | |
1064 | + /* create an array to integrate over */ | |
1065 | + int n = znbes_[zcase]; | |
1066 | + double *func = new double[n]; | |
1067 | + double *j0lr = new double[n]; | |
1068 | + | |
1069 | + /* calculate the other bessel function */ | |
1070 | + j0(n,&zlambda_[zcase][0],rho,j0lr); | |
1071 | + | |
1072 | + | |
1073 | + /* calculate the function */ | |
1074 | + int i; | |
1075 | + for (i=0;i<n;i++) { | |
1076 | + func[i] = Eq18_[zcase][i]*j0lr[i]*(1.0 - ExpLambdaD_[zcase][i]*cosh(zlambda_[zcase][i]*z)); | |
1077 | + } | |
1078 | + | |
1079 | + /* integrate it */ | |
1080 | + Bz[0] = 2.0*mui_*trapc(n,dlambda_bz_,func); | |
1081 | + | |
1082 | + delete[] func; | |
1083 | + delete[] j0lr; | |
1084 | + | |
1085 | +} | |
1086 | + | |
1087 | + | |
1088 | +void Con2020::_Hybrid(double rho, double absz, double z, | |
1089 | + double *Brho, double *Bphi, double *Bz) { | |
1090 | + | |
1091 | + | |
1092 | + /* calculate the inner contribution to Brho and Bz */ | |
1093 | + if ((absz <= 1.5*d_) && (fabs(rho - r0_) <= 2.0)) { | |
1094 | + /* use integration */ | |
1095 | + _IntegralInner(rho,absz,z,Brho,Bz); | |
1096 | + } else { | |
1097 | + /* use analytical */ | |
1098 | + _AnalyticInner(rho,z,Brho,Bz); | |
1099 | + } | |
1100 | + | |
1101 | + /* also the azimuthal field */ | |
1102 | + (this->*_AzimuthalField)(rho,absz,z,Bphi); | |
1103 | + | |
1104 | + /* we need to calculate the outer edge contribution */ | |
1105 | + double oBrho, oBz; | |
1106 | + _AnalyticOuter(rho,z,&oBrho,&oBz); | |
1107 | + | |
1108 | + /*subtract it */ | |
1109 | + Brho[0] -= oBrho; | |
1110 | + Bz[0] -= oBz; | |
1111 | + | |
1112 | +} | |
1113 | + | |
1114 | + | |
1115 | +void Con2020::SetEdwardsEqs(bool Edwards) { | |
1116 | + Edwards_ = Edwards; | |
1117 | + | |
1118 | + /* reset function pointers */ | |
1119 | + _SetModelFunctions(); | |
1120 | +} | |
1121 | + | |
1122 | +bool Con2020::GetEdwardsEqs() { | |
1123 | + return Edwards_; | |
1124 | +} | |
1125 | + | |
1126 | +void Con2020::SetEqType(const char *eqtype) { | |
1127 | + | |
1128 | + if ( (strcmp(eqtype,"analytic") == 0) || | |
1129 | + (strcmp(eqtype,"integral") == 0) || | |
1130 | + (strcmp(eqtype,"hybrid") == 0)) { | |
1131 | + /* this is a valid string - update it */ | |
1132 | + strcpy(eqtype_,eqtype); | |
1133 | + | |
1134 | + _SetModelFunctions(); | |
1135 | + } else { | |
1136 | + printf("eqtype '%s' not recognised - ignoring\n",eqtype); | |
1137 | + } | |
1138 | + | |
1139 | +} | |
1140 | + | |
1141 | +void Con2020::SetSmooth(bool smooth) { | |
1142 | + smooth_ = smooth; | |
1143 | + _SetModelFunctions(); | |
1144 | +} | |
1145 | + | |
1146 | +bool Con2020::GetSmooth() { | |
1147 | + | |
1148 | + return smooth_; | |
1149 | +} | |
1150 | + | |
1151 | + | |
1152 | +void Con2020::GetEqType(char *eqtype) { | |
1153 | + strcpy(eqtype,eqtype_); | |
1154 | +} | |
1155 | + | |
1156 | +void Con2020::SetAzCurrentParameter(double mui) { | |
1157 | + | |
1158 | + if (std::isfinite(mui)) { | |
1159 | + /* good value (hopefully) */ | |
1160 | + mui_ = mui; | |
1161 | + } else { | |
1162 | + printf("Non-finite value - ignoring\n"); | |
1163 | + } | |
1164 | +} | |
1165 | + | |
1166 | +double Con2020::GetAzCurrentParameter() { | |
1167 | + return mui_; | |
1168 | +} | |
1169 | + | |
1170 | +void Con2020::SetRadCurrentParameter(double irho) { | |
1171 | + if (std::isfinite(irho)) { | |
1172 | + /* good value (hopefully) */ | |
1173 | + irho_ = irho; | |
1174 | + } else { | |
1175 | + printf("Non-finite value - ignoring\n"); | |
1176 | + } | |
1177 | +} | |
1178 | + | |
1179 | +double Con2020::GetRadCurrentParameter() { | |
1180 | + return irho_; | |
1181 | +} | |
1182 | + | |
1183 | +void Con2020::SetR0(double r0) { | |
1184 | + if (std::isfinite(r0) && (r0 >= 0.0)) { | |
1185 | + /* good value (hopefully) */ | |
1186 | + r0_ = r0; | |
1187 | + r0sq_ = r0_*r0_; | |
1188 | + } else if (!std::isfinite(r0)) { | |
1189 | + printf("Non-finite value - ignoring\n"); | |
1190 | + } else { | |
1191 | + printf("r0 must have a positive value\n"); | |
1192 | + } | |
1193 | +} | |
1194 | + | |
1195 | +double Con2020::GetR0() { | |
1196 | + return r0_; | |
1197 | +} | |
1198 | + | |
1199 | +void Con2020::SetR1(double r1) { | |
1200 | + if (std::isfinite(r1) && (r1 >= 0.0)) { | |
1201 | + /* good value (hopefully) */ | |
1202 | + r1_ = r1; | |
1203 | + r1sq_ = r1_*r1_; | |
1204 | + } else if (!std::isfinite(r1)) { | |
1205 | + printf("Non-finite value - ignoring\n"); | |
1206 | + } else { | |
1207 | + printf("r1 must have a positive value\n"); | |
1208 | + } | |
1209 | +} | |
1210 | + | |
1211 | +double Con2020::GetR1() { | |
1212 | + return r1_; | |
1213 | +} | |
1214 | + | |
1215 | +void Con2020::SetCSHalfThickness(double d) { | |
1216 | + | |
1217 | + if (std::isfinite(d) && (d >= 0.0)) { | |
1218 | + /* good value (hopefully) */ | |
1219 | + d_ = d; | |
1220 | + } else if (!std::isfinite(d)) { | |
1221 | + printf("Non-finite value - ignoring\n"); | |
1222 | + } else { | |
1223 | + printf("d must have a positive value\n"); | |
1224 | + } | |
1225 | +} | |
1226 | + | |
1227 | +double Con2020::GetCSHalfThickness() { | |
1228 | + return d_; | |
1229 | +} | |
1230 | + | |
1231 | +void Con2020::SetCSTilt(double xt) { | |
1232 | + | |
1233 | + if (std::isfinite(xt)) { | |
1234 | + /* good value (hopefully) */ | |
1235 | + xt_ = xt; | |
1236 | + disctilt_ = xt_*deg2rad; | |
1237 | + cosxt_ = cos(disctilt_); | |
1238 | + sinxt_ = sin(disctilt_); | |
1239 | + } else { | |
1240 | + printf("Non-finite value - ignoring\n"); | |
1241 | + } | |
1242 | +} | |
1243 | + | |
1244 | +double Con2020::GetCSTilt() { | |
1245 | + return xt_; | |
1246 | +} | |
1247 | + | |
1248 | +void Con2020::SetCSTiltAzimuth(double xp) { | |
1249 | + if (std::isfinite(xp)) { | |
1250 | + /* good value (hopefully) */ | |
1251 | + xp_ = xp; | |
1252 | + discshift_ = (xp_ - 180.0)*deg2rad; | |
1253 | + cosxp_ = cos(discshift_); | |
1254 | + sinxp_ = sin(discshift_); | |
1255 | + } else { | |
1256 | + printf("Non-finite value - ignoring\n"); | |
1257 | + } | |
1258 | +} | |
1259 | + | |
1260 | +double Con2020::GetCSTiltAzimuth() { | |
1261 | + return xp_; | |
1262 | +} | |
1263 | + | |
1264 | +void Con2020::SetErrCheck(bool ErrChk) { | |
1265 | + ErrChk_ = ErrChk; | |
1266 | +} | |
1267 | + | |
1268 | +bool Con2020::GetErrCheck() { | |
1269 | + return ErrChk_; | |
1270 | +} | |
1271 | + | |
1272 | +void Con2020::SetCartIn(bool CartIn) { | |
1273 | + CartIn_ = CartIn; | |
1274 | + _SetIOFunctions(); | |
1275 | +} | |
1276 | + | |
1277 | +bool Con2020::GetCartIn() { | |
1278 | + return CartIn_; | |
1279 | +} | |
1280 | + | |
1281 | +void Con2020::SetCartOut(bool CartOut) { | |
1282 | + CartOut_ = CartOut; | |
1283 | + _SetIOFunctions(); | |
1284 | +} | |
1285 | + | |
1286 | +bool Con2020::GetCartOut() { | |
1287 | + return CartOut_; | |
1288 | +} | |
1289 | + | |
1290 | +void Con2020::SetDeltaRho(double DeltaRho) { | |
1291 | + deltarho_ = DeltaRho; | |
1292 | +} | |
1293 | + | |
1294 | +double Con2020::GetDeltaRho() { | |
1295 | + return deltarho_; | |
1296 | +} | |
1297 | + | |
1298 | +void Con2020::SetDeltaZ(double DeltaZ) { | |
1299 | + deltaz_ = DeltaZ; | |
1300 | +} | |
1301 | + | |
1302 | +double Con2020::GetDeltaZ() { | |
1303 | + return deltaz_; | |
1304 | +} | |
1305 | + | |
1306 | +void Con2020::SetOmegaOpen(double OmegaOpen) { | |
1307 | + wO_open_ = OmegaOpen; | |
1308 | +} | |
1309 | + | |
1310 | +double Con2020::GetOmegaOpen() { | |
1311 | + return wO_open_; | |
1312 | +} | |
1313 | + | |
1314 | +void Con2020::SetOmegaOM(double OmegaOM) { | |
1315 | + wO_om_ = OmegaOM; | |
1316 | +} | |
1317 | + | |
1318 | +double Con2020::GetOmegaOM() { | |
1319 | + return wO_om_; | |
1320 | +} | |
1321 | + | |
1322 | +void Con2020::SetThetaMM(double ThetaMM) { | |
1323 | + /* we need this to be in radians, but will accept it in degrees */ | |
1324 | + thetamm_ = ThetaMM*deg2rad; | |
1325 | +} | |
1326 | + | |
1327 | +double Con2020::GetThetaMM() { | |
1328 | + /* convert back to degrees*/ | |
1329 | + return thetamm_*rad2deg; | |
1330 | +} | |
1331 | + | |
1332 | +void Con2020::SetdThetaMM(double dThetaMM) { | |
1333 | + /* we need this to be in radians, but will accept it in degrees */ | |
1334 | + dthetamm_ = dThetaMM*deg2rad; | |
1335 | +} | |
1336 | + | |
1337 | +double Con2020::GetdThetaMM() { | |
1338 | + /* convert back to degrees*/ | |
1339 | + return dthetamm_*rad2deg; | |
1340 | +} | |
1341 | + | |
1342 | +void Con2020::SetThetaOC(double ThetaOC) { | |
1343 | + /* we need this to be in radians, but will accept it in degrees */ | |
1344 | + thetaoc_ = ThetaOC*deg2rad; | |
1345 | +} | |
1346 | + | |
1347 | +double Con2020::GetThetaOC() { | |
1348 | + /* convert back to degrees*/ | |
1349 | + return thetaoc_*rad2deg; | |
1350 | +} | |
1351 | + | |
1352 | +void Con2020::SetdThetaOC(double dThetaOC) { | |
1353 | + /* we need this to be in radians, but will accept it in degrees */ | |
1354 | + dthetaoc_ = dThetaOC*deg2rad; | |
1355 | +} | |
1356 | + | |
1357 | +double Con2020::GetdThetaOC() { | |
1358 | + /* convert back to degrees*/ | |
1359 | + return dthetaoc_*rad2deg; | |
1360 | +} | |
1361 | + | |
1362 | +void Con2020::SetG(double g) { | |
1363 | + g_ = g; | |
1364 | +} | |
1365 | + | |
1366 | +double Con2020::GetG() { | |
1367 | + return g_; | |
1368 | +} | |
1369 | + | |
1370 | +void Con2020::SetAzimuthalFunc(const char* azfunc) { | |
1371 | + if (strcmp(azfunc,"connerney") || strcmp(azfunc,"lmic")) { | |
1372 | + strcpy(azfunc_,azfunc); | |
1373 | + _SetModelFunctions(); | |
1374 | + } else { | |
1375 | + printf("Azimuthal function %s not recognised\n",azfunc); | |
1376 | + } | |
1377 | +} | |
1378 | + | |
1379 | +void Con2020::GetAzimuthalFunc(char* azfunc) { | |
1380 | + strcpy(azfunc,azfunc_); | |
1381 | +} | ... | ... |
... | ... | @@ -0,0 +1,227 @@ |
1 | +#ifndef __CON2020_H__ | |
2 | +#define __CON2020_H__ | |
3 | +#include <stdio.h> | |
4 | +#include <stdlib.h> | |
5 | +#include <string.h> | |
6 | +#define _USE_MATH_DEFINES | |
7 | +#include <math.h> | |
8 | +#include "bessel.h" | |
9 | +#include "sgn.h" | |
10 | +#include "clip.h" | |
11 | +#include "smoothd.h" | |
12 | +#include "trap.h" | |
13 | +#include "lmic.h" | |
14 | +#define deg2rad M_PI/180.0 | |
15 | +#define rad2deg 180.0/M_PI | |
16 | + | |
17 | + | |
18 | +/* function pointer for input conversion */ | |
19 | +class Con2020; /*this is needed for the pointer below */ | |
20 | +typedef void (Con2020::*InputConvFunc)(int,double*,double*,double*, | |
21 | + double*,double*,double*,double*,double*, | |
22 | + double*,double*,double*,double*); | |
23 | +/* Output conversion */ | |
24 | +typedef void (Con2020::*OutputConvFunc)(int,double*,double*,double*, | |
25 | + double*,double*,double*,double*, | |
26 | + double*,double*,double*, | |
27 | + double*,double*,double*); | |
28 | + | |
29 | +/* Model function */ | |
30 | +typedef void (Con2020::*ModelFunc)(double,double,double,double*,double*,double*); | |
31 | + | |
32 | +/* analytical approximation equations */ | |
33 | +typedef void (Con2020::*Approx)(double,double,double,double,double,double*,double*); | |
34 | + | |
35 | +/* azimuthal function */ | |
36 | +typedef void (Con2020::*AzimFunc)(double,double,double,double*); | |
37 | + | |
38 | +class Con2020 { | |
39 | + public: | |
40 | + /* constructors */ | |
41 | + Con2020(); | |
42 | + Con2020(double,double,double,double,double,double,double,const char*,bool,bool,bool,bool); | |
43 | + | |
44 | + /* destructor */ | |
45 | + ~Con2020(); | |
46 | + | |
47 | + // BRE - 10/10/2023 - Add method to init integrals | |
48 | + void Init(); | |
49 | + //---------- | |
50 | + | |
51 | + /* these functions will be used to set the equations used, if | |
52 | + * they need to be changed post-initialisation */ | |
53 | + void SetEdwardsEqs(bool); | |
54 | + void SetEqType(const char*); | |
55 | + void SetAzCurrentParameter(double); | |
56 | + void SetRadCurrentParameter(double); | |
57 | + void SetR0(double); | |
58 | + void SetR1(double); | |
59 | + void SetCSHalfThickness(double); | |
60 | + void SetCSTilt(double); | |
61 | + void SetCSTiltAzimuth(double); | |
62 | + void SetErrCheck(bool); | |
63 | + void SetCartIn(bool); | |
64 | + void SetCartOut(bool); | |
65 | + void SetSmooth(bool); | |
66 | + void SetDeltaRho(double); | |
67 | + void SetDeltaZ(double); | |
68 | + void SetOmegaOpen(double); | |
69 | + void SetOmegaOM(double); | |
70 | + void SetThetaMM(double); | |
71 | + void SetdThetaMM(double); | |
72 | + void SetThetaOC(double); | |
73 | + void SetdThetaOC(double); | |
74 | + void SetG(double); | |
75 | + void SetAzimuthalFunc(const char*); | |
76 | + | |
77 | + /* these mamber functions will be the "getter" version of the | |
78 | + * above setters */ | |
79 | + bool GetEdwardsEqs(); | |
80 | + void GetEqType(char*); | |
81 | + double GetAzCurrentParameter(); | |
82 | + double GetRadCurrentParameter(); | |
83 | + double GetR0(); | |
84 | + double GetR1(); | |
85 | + double GetCSHalfThickness(); | |
86 | + double GetCSTilt(); | |
87 | + double GetCSTiltAzimuth(); | |
88 | + bool GetErrCheck(); | |
89 | + bool GetCartIn(); | |
90 | + bool GetCartOut(); | |
91 | + bool GetSmooth(); | |
92 | + double GetDeltaRho(); | |
93 | + double GetDeltaZ(); | |
94 | + double GetOmegaOpen(); | |
95 | + double GetOmegaOM(); | |
96 | + double GetThetaMM(); | |
97 | + double GetdThetaMM(); | |
98 | + double GetThetaOC(); | |
99 | + double GetdThetaOC(); | |
100 | + double GetG(); | |
101 | + void GetAzimuthalFunc(char *); | |
102 | + | |
103 | + /* This function will be used to call the model, it is overloaded | |
104 | + * so that we have one for arrays, one for scalars */ | |
105 | + void Field(int,double*,double*,double*,double*,double*,double*); | |
106 | + void Field(double,double,double,double*,double*,double*); | |
107 | + | |
108 | + /* a function for testing purposes...*/ | |
109 | + void AnalyticField(double,double,double,double*,double*); | |
110 | + void AnalyticFieldSmooth(double,double,double,double*,double*); | |
111 | + | |
112 | + private: | |
113 | + | |
114 | + bool init_; | |
115 | + | |
116 | + /* model parameters */ | |
117 | + double mui_,irho_,r0_,r1_,d_,xt_,xp_,disctilt_,discshift_; | |
118 | + double r0sq_, r1sq_; | |
119 | + double cosxp_,sinxp_,cosxt_,sinxt_; | |
120 | + char eqtype_[9]; | |
121 | + bool Edwards_, ErrChk_; | |
122 | + bool CartIn_,CartOut_; | |
123 | + double deltaz_,deltarho_; | |
124 | + bool smooth_; | |
125 | + | |
126 | + /* LMIC parameters*/ | |
127 | + double wO_open_, wO_om_, thetamm_, dthetamm_, thetaoc_, dthetaoc_, g_; | |
128 | + char azfunc_[10]; | |
129 | + | |
130 | + /* Bessel function arrays - arrays prefixed with r and z are | |
131 | + * to be used for integrals which calcualte Brho and Bz, | |
132 | + * respectively */ | |
133 | + int *rnbes_; /* number of elements for each Bessel function (rho)*/ | |
134 | + int *znbes_; /* same as above for z */ | |
135 | + double **rlambda_;/* Lambda array to integrate over rho*/ | |
136 | + double **zlambda_;/* Lambda array to integrate over z*/ | |
137 | + double **rj0_lambda_r0_; /* j0(lambda*r0) */ | |
138 | + double **rj1_lambda_rho_;/* j1(lambda*rho) */ | |
139 | + double **zj0_lambda_r0_; /* j0(lambda*r0) */ | |
140 | + double **zj0_lambda_rho_;/* j0(lambda*rho) */ | |
141 | + | |
142 | + | |
143 | + /* arrays to multiply be stuff to be integrated */ | |
144 | + /* these arrays will store the parts of equations 14, 15, 17 | |
145 | + * and 18 of Connerny 1981 which only need to be calculated once*/ | |
146 | + double **Eq14_; /* j0(lambda*r0)*sinh(lamba*d)/lambda */ | |
147 | + double **Eq15_; /* j0(lambda*r0)*sinh(lamba*d)/lambda */ | |
148 | + double **Eq17_; /* j0(lambda*r0)*exp(-lamba*d)/lambda */ | |
149 | + double **Eq18_; /* j0(lambda*r0)/lambda */ | |
150 | + double **ExpLambdaD_; | |
151 | + | |
152 | + | |
153 | + /* integration step sizes */ | |
154 | + static constexpr double dlambda_ = 1e-4; | |
155 | + static constexpr double dlambda_brho_ = 1e-4; | |
156 | + static constexpr double dlambda_bz_ = 5e-5; | |
157 | + | |
158 | + /* Arrays containing maximum lambda values */ | |
159 | + double rlmx_array_[6]; | |
160 | + double zlmx_array_[6]; | |
161 | + | |
162 | + | |
163 | + /* coordinate conversions for positions */ | |
164 | + InputConvFunc _ConvInput; | |
165 | + void _SysIII2Mag(int,double*,double*,double*, | |
166 | + double*,double*,double*,double*,double*, | |
167 | + double*,double*,double*,double*); | |
168 | + void _PolSysIII2Mag(int,double*,double*,double*, | |
169 | + double*,double*,double*,double*,double*, | |
170 | + double*,double*,double*,double*); | |
171 | + | |
172 | + | |
173 | + /* coordinate conversion for magnetic field vector */ | |
174 | + OutputConvFunc _ConvOutput; | |
175 | + void _BMag2SysIII(int,double*,double*,double*, | |
176 | + double*,double*,double*,double*, | |
177 | + double*,double*,double*, | |
178 | + double*,double*,double*); | |
179 | + void _BMag2PolSysIII(int,double*,double*,double*, | |
180 | + double*,double*,double*,double*, | |
181 | + double*,double*,double*, | |
182 | + double*,double*,double*); | |
183 | + | |
184 | + /* Functions to update function pointers */ | |
185 | + void _SetIOFunctions(); | |
186 | + void _SetModelFunctions(); | |
187 | + ModelFunc _Model; | |
188 | + | |
189 | + /* Azimuthal field */ | |
190 | + AzimFunc _AzimuthalField; | |
191 | + void _BphiConnerney(int,double*,double*,double*,double*); | |
192 | + void _BphiConnerney(double,double,double,double*); | |
193 | + void _BphiLMIC(double,double,double,double*); | |
194 | + Approx _LargeRho; | |
195 | + Approx _SmallRho; | |
196 | + /* analytic equations */ | |
197 | + void _Analytic(double,double,double,double*,double*,double*); | |
198 | + void _AnalyticSmooth(double,double,double,double*,double*,double*); | |
199 | + void _SolveAnalytic(int,double*,double*,double,double*,double*); | |
200 | + void _AnalyticInner(double,double,double*,double*); | |
201 | + void _AnalyticOuter(double,double,double*,double*); | |
202 | + void _AnalyticInnerSmooth(double,double,double*,double*); | |
203 | + void _AnalyticOuterSmooth(double,double,double*,double*); | |
204 | + void _LargeRhoConnerney(double,double,double,double,double,double*,double*); | |
205 | + void _SmallRhoConnerney(double,double,double,double,double,double*,double*); | |
206 | + void _LargeRhoEdwards(double,double,double,double,double,double*,double*); | |
207 | + void _LargeRhoEdwardsSmooth(double,double,double,double,double,double*,double*); | |
208 | + void _SmallRhoEdwards(double,double,double,double,double,double*,double*); | |
209 | + | |
210 | + /* integral-related functions */ | |
211 | + void _Integral(double,double,double,double*,double*,double*); | |
212 | + void _IntegralInner(double, double, double, double*, double*); | |
213 | + void _InitIntegrals(); | |
214 | + void _RecalcIntegrals(); | |
215 | + void _DeleteIntegrals(); | |
216 | + void _IntegralChecks(int,double*,int*,int[]); | |
217 | + void _IntegralCheck(double,int*); | |
218 | + void _SolveIntegral(int,double*,double*,double*,double*,double*); | |
219 | + void _IntegrateEq14(int,double,double,double,double*); | |
220 | + void _IntegrateEq15(int,double,double,double*); | |
221 | + void _IntegrateEq17(int,double,double,double*); | |
222 | + void _IntegrateEq18(int,double,double,double*); | |
223 | + | |
224 | + /* hybrid */ | |
225 | + void _Hybrid(double,double,double,double*,double*,double*); | |
226 | +}; | |
227 | +#endif | ... | ... |
... | ... | @@ -0,0 +1,123 @@ |
1 | +#include "libcon2020.h" | |
2 | + | |
3 | +// BRE - Due to this global variable, the Con2020 constructor is called on library load | |
4 | +// => the init integrals is a little bit long so the call of this method has been moved outside of the constructor | |
5 | +Con2020 con2020; | |
6 | + | |
7 | +// BRE - 10/10/2023 - Add method to init integrals | |
8 | +void Con2020Init() { | |
9 | + con2020.Init(); | |
10 | +} | |
11 | +//------------------------- | |
12 | + | |
13 | +void Con2020FieldArray(int n, double *p0, double *p1, double *p2, | |
14 | + double *B0, double *B1, double *B2) { | |
15 | + | |
16 | + /* could create a separate function for default model */ | |
17 | + con2020.Field(n,p0,p1,p2,B0,B1,B2); | |
18 | + | |
19 | +} | |
20 | + | |
21 | +void Con2020Field(double p0, double p1, double p2, | |
22 | + double *B0, double *B1, double *B2) { | |
23 | + | |
24 | + /* could create a separate function for default model */ | |
25 | + con2020.Field(p0,p1,p2,B0,B1,B2); | |
26 | + | |
27 | +} | |
28 | + | |
29 | +void GetCon2020Params(double *mui, double *irho, double *r0, double *r1, | |
30 | + double *d, double *xt, double *xp, char *eqtype, | |
31 | + bool *Edwards, bool *ErrChk, bool *CartIn, bool *CartOut, | |
32 | + bool *smooth, double *DeltaRho, double *DeltaZ, | |
33 | + double *g, char *azfunc, double *wO_open, double *wO_om, | |
34 | + double *thetamm, double *dthetamm, double *thetaoc, double *dthetaoc) { | |
35 | + | |
36 | + mui[0] = con2020.GetAzCurrentParameter(); | |
37 | + irho[0] = con2020.GetRadCurrentParameter(); | |
38 | + r0[0] = con2020.GetR0(); | |
39 | + r1[0] = con2020.GetR1(); | |
40 | + d[0] = con2020.GetCSHalfThickness(); | |
41 | + xt[0] = con2020.GetCSTilt(); | |
42 | + xp[0] = con2020.GetCSTiltAzimuth(); | |
43 | + Edwards[0] = con2020.GetEdwardsEqs(); | |
44 | + ErrChk[0] = con2020.GetErrCheck(); | |
45 | + CartIn[0] = con2020.GetCartIn(); | |
46 | + CartOut[0] = con2020.GetCartOut(); | |
47 | + con2020.GetEqType(eqtype); | |
48 | + smooth[0] = con2020.GetSmooth(); | |
49 | + DeltaRho[0] = con2020.GetDeltaRho(); | |
50 | + DeltaZ[0] = con2020.GetDeltaZ(); | |
51 | + | |
52 | + /* new LMIC parameters */ | |
53 | + g[0] = con2020.GetG(); | |
54 | + con2020.GetAzimuthalFunc(azfunc); | |
55 | + wO_open[0] = con2020.GetOmegaOpen(); | |
56 | + wO_om[0] = con2020.GetOmegaOM(); | |
57 | + thetamm[0] = con2020.GetThetaMM(); | |
58 | + dthetamm[0] = con2020.GetdThetaMM(); | |
59 | + thetaoc[0] = con2020.GetThetaOC(); | |
60 | + dthetaoc[0] = con2020.GetdThetaOC(); | |
61 | + | |
62 | + | |
63 | +} | |
64 | +void SetCon2020Params(double mui, double irho, double r0, double r1, | |
65 | + double d, double xt, double xp, const char *eqtype, | |
66 | + bool Edwards, bool ErrChk, bool CartIn, bool CartOut, | |
67 | + bool smooth, double DeltaRho, double DeltaZ, | |
68 | + double g, const char *azfunc, double wO_open, double wO_om, | |
69 | + double thetamm, double dthetamm, double thetaoc, double dthetaoc) { | |
70 | + | |
71 | + con2020.SetAzCurrentParameter(mui); | |
72 | + con2020.SetRadCurrentParameter(irho); | |
73 | + con2020.SetR0(r0); | |
74 | + con2020.SetR1(r1); | |
75 | + con2020.SetCSHalfThickness(d); | |
76 | + con2020.SetCSTilt(xt); | |
77 | + con2020.SetCSTiltAzimuth(xp); | |
78 | + con2020.SetEdwardsEqs(Edwards); | |
79 | + con2020.SetErrCheck(ErrChk); | |
80 | + con2020.SetCartIn(CartIn); | |
81 | + con2020.SetCartOut(CartOut); | |
82 | + con2020.SetEqType(eqtype); | |
83 | + con2020.SetSmooth(smooth); | |
84 | + con2020.SetDeltaRho(DeltaRho); | |
85 | + con2020.SetDeltaZ(DeltaZ); | |
86 | + | |
87 | + /*set LMIC parameters */ | |
88 | + con2020.SetG(g); | |
89 | + con2020.SetAzimuthalFunc(azfunc); | |
90 | + con2020.SetOmegaOpen(wO_open); | |
91 | + con2020.SetOmegaOM(wO_om); | |
92 | + con2020.SetThetaMM(thetamm); | |
93 | + con2020.SetdThetaMM(dthetamm); | |
94 | + con2020.SetThetaOC(thetaoc); | |
95 | + con2020.SetdThetaOC(dthetaoc); | |
96 | +} | |
97 | + | |
98 | +void Con2020AnalyticField( int n, double a, | |
99 | + double *rho, double *z, | |
100 | + double *Brho, double *Bz) { | |
101 | + | |
102 | + /* define a few required variables */ | |
103 | + int i; | |
104 | + | |
105 | + for (i=0;i<n;i++) { | |
106 | + con2020.AnalyticField(a,rho[i],z[i],&Brho[i],&Bz[i]); | |
107 | + } | |
108 | + | |
109 | +} | |
110 | + | |
111 | + | |
112 | +void Con2020AnalyticFieldSmooth( int n, double a, | |
113 | + double *rho, double *z, | |
114 | + double *Brho, double *Bz) { | |
115 | + | |
116 | + /* define a few required variables */ | |
117 | + int i; | |
118 | + | |
119 | + for (i=0;i<n;i++) { | |
120 | + con2020.AnalyticFieldSmooth(a,rho[i],z[i],&Brho[i],&Bz[i]); | |
121 | + } | |
122 | + | |
123 | +} | ... | ... |
... | ... | @@ -0,0 +1,50 @@ |
1 | +#ifndef __LIBCON2020_H__ | |
2 | +#define __LIBCON2020_H__ | |
3 | +#include <stdio.h> | |
4 | +#include <stdlib.h> | |
5 | +#include "con2020.h" | |
6 | +#include <string.h> | |
7 | + | |
8 | + | |
9 | + | |
10 | +/* we want to initialize the model objects with its parameters */ | |
11 | +extern Con2020 con2020; | |
12 | + | |
13 | +extern "C" { | |
14 | + // BRE - 10/10/2023 - Add method to init integrals | |
15 | + void Con2020Init(); | |
16 | + //---------- | |
17 | + | |
18 | + /* these wrappers can be used to get the magnetic field vectors */ | |
19 | + void Con2020FieldArray(int n, double *p0, double *p1, double *p2, | |
20 | + double *B0, double *B1, double *B2); | |
21 | + | |
22 | + void Con2020Field(double p0, double p1, double p2, | |
23 | + double *B0, double *B1, double *B2); | |
24 | + | |
25 | + | |
26 | + void GetCon2020Params(double *mui, double *irho, double *r0, double *r1, | |
27 | + double *d, double *xt, double *xp, char *eqtype, | |
28 | + bool *Edwards, bool *ErrChk, bool *CartIn, bool *CartOut, | |
29 | + bool *smooth, double *DeltaRho, double *DeltaZ, | |
30 | + double *g, char *azfunc, double *wO_open, double *wO_om, | |
31 | + double *thetamm, double *dthetamm, double *thetaoc, double *dthetaoc); | |
32 | + | |
33 | + | |
34 | + void SetCon2020Params(double mui, double irho, double r0, double r1, | |
35 | + double d, double xt, double xp, const char *eqtype, | |
36 | + bool Edwards, bool ErrChk, bool CartIn, bool CartOut, | |
37 | + bool smooth, double DeltaRho, double DeltaZ, | |
38 | + double g, const char *azfunc, double wO_open, double wO_om, | |
39 | + double thetamm, double dthetamm, double thetaoc, double dthetaoc); | |
40 | + | |
41 | + void Con2020AnalyticField( int n, double a, | |
42 | + double *rho, double *z, | |
43 | + double *Brho, double *Bz); | |
44 | + | |
45 | + void Con2020AnalyticFieldSmooth( int n, double a, | |
46 | + double *rho, double *z, | |
47 | + double *Brho, double *Bz); | |
48 | + | |
49 | +} | |
50 | +#endif | ... | ... |