Commit efe5840e45d9762efc04cc9dc6bd4afce9b46071

Authored by Benjamin Renard
1 parent a9eed1ff
Exists in master

Apply some modif. to libcon2020 to improve librairy load

libcon2020/modif/include/con2020.h 0 → 100644
... ... @@ -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
... ...
libcon2020/modif/src/con2020.cc 0 → 100644
... ... @@ -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 +}
... ...
libcon2020/modif/src/con2020.h 0 → 100644
... ... @@ -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
... ...
libcon2020/modif/src/libcon2020.cc 0 → 100644
... ... @@ -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 +}
... ...
libcon2020/modif/src/libcon2020.h 0 → 100644
... ... @@ -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
... ...