raytracing_yp

PURPOSE ^

C/C++ source

SYNOPSIS ^

C/C++ source

DESCRIPTION ^

C/C++ source

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 /*
0002  
0003  raytracing.c    MEX file implementation of a universal ray-tracing for electron waves
0004  
0005  call -> [tout, yout, yproc] = raytracing_yp(rayparam,equil,y0)
0006  
0007  INPUT:
0008  
0009  - rayparam: parameters for ray-tracing structure [1,1]
0010  - equil: numerical equilibrium structure [1,1]
0011  - y0: ray initial conditions [1,1]
0012  
0013  OUTPUT:
0014  
0015  - tout: returned integration time points (row-vector).
0016  - yout: returned solution, one solution column-vector per tout-value.
0017  - yproc: returned processed data, one set of data as column-vector per tout-value.
0018  
0019  WARNING: none
0020  
0021  REFERENCE: none
0022  
0023  by Y.PEYSSON (CEA-IRFM)  <yves.peysson@cea.fr>, Joan Decker (CEA-IRFM) <joan.decker@cea.fr> and Laurent Colas (CEA-IRFM) <laurent.colas@cea.fr>
0024  Guillaume Brochard <guillaume.brochard@cea.fr>*/
0025 
0026 #define DUMP(u) mexPrintf("%s = %e\n", #u, u)
0027 
0028 #include <complex.h>
0029 #include <math.h>
0030 #include "mex.h"
0031 #include "structures_raytracing_yp.h"
0032 
0033 /* Input Arguments */
0034 
0035 #define RAYPARAM_IN  prhs[0]
0036 #define EQUIL_IN     prhs[1]
0037 #define Y0_IN    prhs[2]
0038 #define DISTRI_IN prhs[3]
0039 #define FLUCT_IN prhs[4]
0040 #define FLAG_IN prhs[5]
0041 
0042 
0043 /* Output Arguments */
0044 
0045 #define T_OUT   plhs[0]
0046 #define Y_OUT   plhs[1]
0047 #define Y_PROC  plhs[2]
0048 
0049 #define MC 8
0050 #define MPROC 26
0051 #define SAFETY 0.8
0052 #define PGROW 0.2
0053 #define PSHRINK 0.25
0054 #define PI 3.14159265358979
0055 #define CLUM 299792458 /*Speed of light (m/s) */
0056 
0057 /* Fehlberg coefficients fro the 45 Runge-Kutta integration */
0058 
0059 static double alpha[5] = { 1.0/4.0,  3.0/8.0,  12.0/13.0,  1.0,  1.0/2.0 };
0060 
0061 static double beta[5][5] = {
0062     { 1.0/4.0, 3.0/32.0,  1932.0/2197.0,   8341.0/4104.0,  -6080.0/20520.0 },
0063     {     0.0, 9.0/32.0, -7200.0/2197.0, -32832.0/4104.0,  41040.0/20520.0 },
0064     {     0.0,      0.0,  7296.0/2197.0,  29440.0/4104.0, -28352.0/20520.0 },
0065     {     0.0,      0.0,            0.0,   -845.0/4104.0,   9295.0/20520.0 },
0066     {     0.0,      0.0,            0.0,             0.0,  -5643.0/20520.0 }
0067 };
0068 
0069 static double gama[6][2] = {
0070     {   902880.0/7618050.0,   -2090.0/752400.0 },
0071     {                  0.0,                0.0 },
0072     {  3953664.0/7618050.0,   22528.0/752400.0 },
0073     {  3855735.0/7618050.0,   21970.0/752400.0 },
0074     { -1371249.0/7618050.0,  -15048.0/752400.0 },
0075     {   277020.0/7618050.0,  -27360.0/752400.0 }
0076 };
0077 
0078 
0079 void mexFunction(   int     nlhs, mxArray *plhs[], int     nrhs, const mxArray   *prhs[]) {
0080     
0081     rayparam_format rayparam;
0082     equilparam_format equilparam;
0083     fluctparam_format fluctparam;
0084     raymagnetic_format raymagnetic;
0085     rayprofiles_format rayprofiles;
0086     susceptibilitytensor_format X;
0087     rayfluctuations_format rayfluctuations;
0088     rayequil_format rayequil;
0089     distriparam_format distriparam;
0090     raydistri_format raydistri;
0091     
0092     double flag,flag_proc = 1;
0093     
0094     register int i,j;
0095     int flag_fluct = 1,flag_f0 = 1,flag_metric = 1;
0096     int fmode,nss,iss,ns;
0097     double dummy,dummy10[3],dummy11[4],dummy12[4];
0098     
0099     mxArray *tmp;
0100     
0101     /* For Runge-Kutta integration */
0102     
0103     double  *tout,*yout,*yproc;
0104     double  *toutp,*youtp;
0105     double  *y0,*y1,*yinit,*y0_in,*y0dot;
0106     double  tau_lim;
0107     
0108     register unsigned int  m,kk,ii=0;
0109     register int k=-1;
0110     
0111     int flag1,iimax=200000, kmax;
0112     
0113     double *s0,*s1,*s2,*s3,*s4,*s5,*s6;
0114     double *tempt,*temp0,*temp1,*temp2,*temp3,*temp4,*temp5,*temp6,*temp7;
0115     
0116     double ymax,tau,delta,h,hmax,hmin;
0117     
0118     double ydel[MC],ys[7];
0119     
0120     double t1,t2,ts,rho1,rho2,theta1,theta2,z1,z2,krho1,krho2,m1,m2,kz1,kz2,omega1,omega2;
0121     
0122     double rhodot,thetadot,zdot,krhodot,mdot,kzdot,omegadot,Sdot;
0123     
0124     double S1,S2,S_step,Sdot1,Sdot2,Sdot3,Sdot4,Sdot5,Sdot6;
0125     
0126     double *rayproc,**temp_proc;
0127     double dS,depth=0.0,alpha1=0.0,alpha2,absphi;
0128     
0129     double alpha_rho,alpha_theta,alpha_z,acc,krho1_dsolve;
0130     
0131     /* Check out input and output arguments */
0132     
0133     if (nrhs < 3 || nrhs > 6) mexErrMsgTxt("Wrong number of input arguments for raytracing_yp.mex");/* The number of input arguments is fixed */
0134     
0135     if (!mxIsStruct(prhs[0])) mexErrMsgTxt("1st input argument of raytracing_yp.mex must be a structure (rayparam)");
0136     
0137     if (nrhs == 3) {
0138         flag = 0;
0139         flag_f0 = 0;
0140         flag_fluct = 0;
0141         if (!mxIsStruct(prhs[1])) mexErrMsgTxt("2nd input argument of raytracing_yp.mex must be a structure (equil_fit)");
0142     }
0143     
0144     if (nrhs == 4) {
0145         flag = 0;/* Numerical toroidal MHD equilibrium */
0146         flag_fluct = 0;/* No fluctuations */
0147         if (!mxIsStruct(prhs[1])) mexErrMsgTxt("2nd input argument of raytracing_yp.mex must be a structure (equil_fit)");
0148         if (!mxIsStruct(prhs[3])) flag_f0 = 0;/* fourth input argument must be a structure for wave damping on a non-maxwellian distribution */
0149         if (mxIsEmpty(prhs[3])) flag_f0 = 0;/* if empty, wave damping on maxwellian distribution only */
0150     }
0151     
0152     if (nrhs > 4) {
0153         if (!mxIsStruct(prhs[3])) flag_f0 = 0;/* fourth input argument must be a structure for wave damping on a non-maxwellian distribution */
0154         if (mxIsEmpty(prhs[3])) flag_f0 = 0;/* if empty, wave damping on maxwellian distribution only */
0155         if (!mxIsStruct(prhs[4])) flag_fluct = 0;/* fifth input argument must be a structure for plasma fluctuations */
0156         if (mxIsEmpty(prhs[4])) flag_fluct = 0;/* if empty, no plasma fluctuations */
0157         
0158         if (nrhs == 5) {
0159             flag = 0;/* Numerical toroidal MHD equilibrium */
0160             if (!mxIsStruct(prhs[1])) mexErrMsgTxt("2nd input argument of raytracing_yp.mex must be a structure (equil_fit)");
0161         } else {
0162             if (mxIsEmpty(prhs[5])) {
0163                 flag = 0;/* Numerical toroidal MHD equilibrium */
0164             } else {
0165                 flag = *(mxGetPr(FLAG_IN));/* Numerical toroidal MHD equilibrium or analytical tests */
0166             }
0167             if (fabs(flag) > 0) {
0168                 mexPrintf("WARNING: Plasma fluctuations are incompatible with the analytical toroidal MHD magnetic equilibrium option.\n");
0169                 flag_f0 = 0;
0170                 flag_fluct = 0;
0171             }
0172         }
0173     }
0174     
0175     /* mexPrintf("flag : %d\n",abs(flag)); */
0176     
0177     if (nlhs < 2 || nlhs > 3) mexErrMsgTxt("Wrong number of output arguments for raytracing_yp.mex***");
0178     if (nlhs == 2) flag_proc = 0;/* flag for calculating additional ray data */
0179     
0180     /*
0181      double complex iBn,iBnp,iBnpp;
0182      modBessel(-5.4,(double complex)(3.0 +1.2*I),&iBn,&iBnp,&iBnpp);
0183      mexPrintf("Bessel(-5.4,3.+1.2*i),Bp,Bpp:%g,%g,%g,%g,%g,%g\n",iBn,iBnp,iBnpp);
0184      */
0185     
0186     /* Get Input Arguments */
0187     
0188     rayparam = load_ray_param(RAYPARAM_IN);
0189     
0190     if (isinf(rayparam.tau_lim[0])) {
0191         tau_lim = -1.0;
0192     } else {
0193         tau_lim = rayparam.tau_lim[0];
0194     }
0195     kmax = (int)rayparam.kmax[0];
0196     
0197     y0_in = mxGetPr(Y0_IN);
0198     
0199     if (flag == 0) {/* numerical toroidal MHD equilibrium */
0200         equilparam = load_equil_param(EQUIL_IN);
0201         
0202         if ((isinf(equilparam.Rp[0]) == 1) & (flag_fluct > 0)) {
0203             mexPrintf("WARNING: Plasma fluctuations are incompatible with the cylindrical toroidal MHD magnetic equilibrium.\n");
0204             flag_f0 = 0;
0205             flag_fluct = 0;
0206         }
0207         
0208         ns = equilparam.ns[0];/* number of species for memory allocation */
0209         
0210         if (equilparam.zZi[0] > 0) {/*Vacuum case otherwise (no density, temperature...)*/
0211             rayequil.Te_fit = load_profile_1D(EQUIL_IN,"Te_fit");
0212             rayequil.ne_fit = load_profile_1D(EQUIL_IN,"ne_fit");
0213             rayequil.zTi_fit = load_profile_1D(EQUIL_IN,"zTi_fit");
0214             rayequil.zni_fit = load_profile_1D(EQUIL_IN,"zni_fit");
0215         }
0216         
0217         rayequil.x_fit = load_grid_2D(EQUIL_IN,"x_fit",0);
0218         rayequil.y_fit = load_grid_2D(EQUIL_IN,"y_fit",0);
0219         rayequil.r_fit = load_grid_2D(EQUIL_IN,"r_fit",0);
0220         rayequil.calpha_fit = load_grid_2D(EQUIL_IN,"calpha_fit",0);
0221         rayequil.salpha_fit = load_grid_2D(EQUIL_IN,"salpha_fit",0);
0222         rayequil.gradrho_fit = load_grid_2D(EQUIL_IN,"gradrho_fit",0);
0223         
0224         rayequil.Bx_fit = load_grid_2D(EQUIL_IN,"Bx_fit",0);
0225         rayequil.By_fit = load_grid_2D(EQUIL_IN,"By_fit",0);
0226         rayequil.Bz_fit = load_grid_2D(EQUIL_IN,"Bz_fit",0);
0227         rayequil.BP_fit = load_grid_2D(EQUIL_IN,"BP_fit",0);
0228         rayequil.B_fit = load_grid_2D(EQUIL_IN,"B_fit",0);
0229         
0230         if (flag_f0 == 1) {
0231             distriparam = load_distri_param(DISTRI_IN);
0232             raydistri.f0_fit = load_profile_1D(DISTRI_IN,"XXf0_fit");
0233             raydistri.PSI_fit = load_grid_2D(DISTRI_IN,"PSI_fit",0);
0234         }
0235         
0236         if (flag_fluct == 1) {
0237             fluctparam = load_fluct_param(FLUCT_IN);
0238             rayfluctuations.L_rho = load_value_0D(FLUCT_IN,"L_rho");
0239             rayfluctuations.xq_fit = load_profile_1D(FLUCT_IN,"xq_fit");
0240             rayfluctuations.xL_theta_fit = load_profile_1D(FLUCT_IN,"xL_theta_fit");
0241             rayfluctuations.xL_perp_fit = load_profile_1D(FLUCT_IN,"xL_perp_fit");
0242             rayfluctuations.XL_phi_fit = load_grid_2D(FLUCT_IN,"XL_phi_fit",0);
0243             rayfluctuations.Xcm_fit = load_grid_2D(FLUCT_IN,"Xcm_fit",0);
0244             rayfluctuations.Xcn_fit = load_grid_2D(FLUCT_IN,"Xcn_fit",0);
0245             
0246             if (fluctparam.ne_nmodel[0]) {
0247                 tmp = mxGetField(FLUCT_IN, 0,"ne_fit");
0248                 nss = fmax(mxGetDimensions(tmp)[0],mxGetDimensions(tmp)[1]);
0249             }
0250             
0251             if (fluctparam.B_nmodel[0]) {
0252                 tmp = mxGetField(FLUCT_IN, 0,"B_fit");
0253                 nss = fmax(mxGetDimensions(tmp)[0],mxGetDimensions(tmp)[1]);
0254                 
0255                 rayfluctuations.B_sfx_fit = mxCalloc(nss,sizeof(pp_2D_format));
0256                 rayfluctuations.B_sfy_fit = mxCalloc(nss,sizeof(pp_2D_format));
0257                 rayfluctuations.B_sfz_fit = mxCalloc(nss,sizeof(pp_2D_format));/* here z stands for phi, the toroidal direction */
0258                 
0259                 for (iss = 0;iss < nss; iss++) {
0260                     rayfluctuations.B_sfx_fit[iss] = load_grid_2D(tmp,"Xfx_fit",iss);
0261                     rayfluctuations.B_sfy_fit[iss] = load_grid_2D(tmp,"Xfy_fit",iss);
0262                     rayfluctuations.B_sfz_fit[iss] = load_grid_2D(tmp,"Xfz_fit",iss);/* here z stands for phi, the toroidal direction */
0263                 }
0264             }
0265             
0266         } else {
0267             fluctparam.ne_nmodel = mxCalloc(1,sizeof(int));/* automatic set to zero by default */
0268             fluctparam.B_nmodel = mxCalloc(1,sizeof(int));/* automatic set to zero by default */
0269         }
0270     } else {
0271         
0272         load_idealequil_test(flag,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&dummy,&ns,dummy10,dummy11,dummy12,&dummy);/* number of species for memory allocation */
0273         
0274         equilparam.zZi = mxCalloc(ns,sizeof(double));
0275         equilparam.zmi = mxCalloc(ns,sizeof(double));
0276         equilparam.ns = mxCalloc(1,sizeof(int));
0277         equilparam.Rp = mxCalloc(1,sizeof(double));
0278         equilparam.ap = mxCalloc(1,sizeof(double));
0279         equilparam.Zp = mxCalloc(1,sizeof(double));
0280         equilparam.psia_apRp = mxCalloc(1,sizeof(double));
0281         
0282         fluctparam.ne_nmodel = mxCalloc(1,sizeof(int));/* automatic set to zero by default */
0283         fluctparam.B_nmodel = mxCalloc(1,sizeof(int));/* automatic set to zero by default */
0284     }
0285     
0286     
0287     /* Memory allocation */
0288     
0289     raymagnetic.rn = mxCalloc(1,sizeof(double));
0290     raymagnetic.xn = mxCalloc(1,sizeof(double));
0291     raymagnetic.yn = mxCalloc(1,sizeof(double));
0292     raymagnetic.Brhon = mxCalloc(1,sizeof(double));
0293     raymagnetic.Bsn = mxCalloc(1,sizeof(double));
0294     raymagnetic.Bzn = mxCalloc(1,sizeof(double));
0295     raymagnetic.B = mxCalloc(1,sizeof(double));
0296     raymagnetic.salpha = mxCalloc(1,sizeof(double));
0297     raymagnetic.calpha = mxCalloc(1,sizeof(double));
0298     raymagnetic.gradrhon = mxCalloc(1,sizeof(double));
0299     raymagnetic.rhorip = mxCalloc(1,sizeof(double));
0300     raymagnetic.Upsilonn = mxCalloc(1,sizeof(double));
0301     
0302     raymagnetic.drndY = mxCalloc(MC,sizeof(double));
0303     raymagnetic.dxndY = mxCalloc(MC,sizeof(double));
0304     raymagnetic.dyndY = mxCalloc(MC,sizeof(double));
0305     raymagnetic.dBrhondY = mxCalloc(MC,sizeof(double));
0306     raymagnetic.dBsndY = mxCalloc(MC,sizeof(double));
0307     raymagnetic.dBzndY = mxCalloc(MC,sizeof(double));
0308     raymagnetic.dBdY = mxCalloc(MC,sizeof(double));
0309     raymagnetic.dsalphadY = mxCalloc(MC,sizeof(double));
0310     raymagnetic.dcalphadY = mxCalloc(MC,sizeof(double));
0311     raymagnetic.dgradrhondY = mxCalloc(MC,sizeof(double));
0312     raymagnetic.drhoripdY = mxCalloc(MC,sizeof(double));
0313     raymagnetic.dUpsilonndY = mxCalloc(MC,sizeof(double));
0314     
0315     raymagnetic.d2rndY2 = mxCalloc(MC,sizeof(double));
0316     raymagnetic.d2xndY2 = mxCalloc(MC,sizeof(double));
0317     raymagnetic.d2yndY2 = mxCalloc(MC,sizeof(double));
0318     raymagnetic.d2BrhondY2 = mxCalloc(MC,sizeof(double));
0319     raymagnetic.d2BsndY2 = mxCalloc(MC,sizeof(double));
0320     raymagnetic.d2BzndY2 = mxCalloc(MC,sizeof(double));
0321     raymagnetic.d2BdY2 = mxCalloc(MC,sizeof(double));
0322     raymagnetic.d2salphadY2 = mxCalloc(MC,sizeof(double));
0323     raymagnetic.d2calphadY2 = mxCalloc(MC,sizeof(double));
0324     raymagnetic.d2gradrhondY2 = mxCalloc(MC,sizeof(double));
0325     raymagnetic.d2rhoripdY2 = mxCalloc(MC,sizeof(double));
0326     raymagnetic.d2UpsilonndY2 = mxCalloc(MC,sizeof(double));
0327     
0328     for (i = 0;i < MC; i++) {/*initialisation */
0329         raymagnetic.drndY[i] = 0.0;
0330         raymagnetic.dxndY[i] = 0.0;
0331         raymagnetic.dyndY[i] = 0.0;
0332         raymagnetic.dsalphadY[i] = 0.0;
0333         raymagnetic.dcalphadY[i] = 0.0;
0334         raymagnetic.dgradrhondY[i] = 0.0;
0335         raymagnetic.dBrhondY[i] = 0.0;
0336         raymagnetic.dBsndY[i] = 0.0;
0337         raymagnetic.dBzndY[i] = 0.0;
0338         raymagnetic.dBdY[i] = 0.0;
0339         raymagnetic.drhoripdY[i] = 0.0;
0340         raymagnetic.dUpsilonndY[i] = 0.0;
0341         
0342         raymagnetic.d2rndY2[i] = 0.0;
0343         raymagnetic.d2xndY2[i] = 0.0;
0344         raymagnetic.d2yndY2[i] = 0.0;
0345         raymagnetic.d2salphadY2[i] = 0.0;
0346         raymagnetic.d2calphadY2[i] = 0.0;
0347         raymagnetic.d2gradrhondY2[i] = 0.0;
0348         raymagnetic.d2BrhondY2[i] = 0.0;
0349         raymagnetic.d2BsndY2[i] = 0.0;
0350         raymagnetic.d2BzndY2[i] = 0.0;
0351         raymagnetic.d2BdY2[i] = 0.0;
0352         raymagnetic.d2rhoripdY2[i] = 0.0;
0353         raymagnetic.d2UpsilonndY2[i] = 0.0;
0354     }
0355     
0356     rayprofiles.Te = mxCalloc(1,sizeof(double));
0357     rayprofiles.ne = mxCalloc(1,sizeof(double));
0358     
0359     rayprofiles.dTedY = mxCalloc(MC,sizeof(double));
0360     rayprofiles.dnedY = mxCalloc(MC,sizeof(double));
0361     rayprofiles.d2TedY2 = mxCalloc(MC,sizeof(double));
0362     rayprofiles.d2nedY2 = mxCalloc(MC,sizeof(double));
0363     
0364     rayprofiles.zTi = mxCalloc(ns,sizeof(double));
0365     rayprofiles.zni = mxCalloc(ns,sizeof(double));
0366     
0367     rayprofiles.dzTidY = mxCalloc(ns,sizeof(double *));
0368     rayprofiles.dznidY = mxCalloc(ns,sizeof(double *));
0369     rayprofiles.d2zTidY2 = mxCalloc(ns,sizeof(double *));
0370     rayprofiles.d2znidY2 = mxCalloc(ns,sizeof(double *));
0371     
0372     for (i = 0;i < ns; i++) {
0373         rayprofiles.dzTidY[i] = mxCalloc(MC,sizeof(double));
0374         rayprofiles.dznidY[i] = mxCalloc(MC,sizeof(double));
0375         rayprofiles.d2zTidY2[i] = mxCalloc(MC,sizeof(double));
0376         rayprofiles.d2znidY2[i] = mxCalloc(MC,sizeof(double));
0377     }
0378     
0379     /* Array initialisation */
0380     
0381     for (i = 0;i < MC; i++) {
0382         rayprofiles.dTedY[i] = 0.0;
0383         rayprofiles.dnedY[i] = 0.0;
0384         rayprofiles.d2TedY2[i] = 0.0;
0385         rayprofiles.d2nedY2[i] = 0.0;
0386         
0387         for (j=0;jdouble complex));
0396     X.Xxy = mxCalloc(1,sizeof(double complex));
0397     X.Xxz = mxCalloc(1,sizeof(double complex));
0398     X.Xyy = mxCalloc(1,sizeof(double complex));
0399     X.Xyz = mxCalloc(1,sizeof(double complex));
0400     X.Xzz = mxCalloc(1,sizeof(double complex));
0401     
0402     X.dXxxdNperp = mxCalloc(1,sizeof(double complex));
0403     X.dXxydNperp = mxCalloc(1,sizeof(double complex));
0404     X.dXxzdNperp = mxCalloc(1,sizeof(double complex));
0405     X.dXyydNperp = mxCalloc(1,sizeof(double complex));
0406     X.dXyzdNperp = mxCalloc(1,sizeof(double complex));
0407     X.dXzzdNperp = mxCalloc(1,sizeof(double complex));
0408     
0409     X.dXxxdNpar = mxCalloc(1,sizeof(double complex));
0410     X.dXxydNpar = mxCalloc(1,sizeof(double complex));
0411     X.dXxzdNpar = mxCalloc(1,sizeof(double complex));
0412     X.dXyydNpar = mxCalloc(1,sizeof(double complex));
0413     X.dXyzdNpar = mxCalloc(1,sizeof(double complex));
0414     X.dXzzdNpar = mxCalloc(1,sizeof(double complex));
0415     
0416     X.dXxxdY = mxCalloc(MC,sizeof(double complex));
0417     X.dXxydY = mxCalloc(MC,sizeof(double complex));
0418     X.dXxzdY = mxCalloc(MC,sizeof(double complex));
0419     X.dXyydY = mxCalloc(MC,sizeof(double complex));
0420     X.dXyzdY = mxCalloc(MC,sizeof(double complex));
0421     X.dXzzdY = mxCalloc(MC,sizeof(double complex));
0422     
0423     for (i=0;i/*initialisation */
0424         X.dXxxdY[i] = 0.0;
0425         X.dXxydY[i] = 0.0;
0426         X.dXxzdY[i] = 0.0;
0427         X.dXyydY[i] = 0.0;
0428         X.dXyzdY[i] = 0.0;
0429         X.dXzzdY[i] = 0.0;
0430     }
0431     
0432     /* Create arguments for calling user function */
0433     
0434     tempt = mxCalloc(rayparam.kmax[0],sizeof(double));
0435     temp0 = mxCalloc(rayparam.kmax[0],sizeof(double));
0436     temp1 = mxCalloc(rayparam.kmax[0],sizeof(double));
0437     temp2 = mxCalloc(rayparam.kmax[0],sizeof(double));
0438     temp3 = mxCalloc(rayparam.kmax[0],sizeof(double));
0439     temp4 = mxCalloc(rayparam.kmax[0],sizeof(double));
0440     temp5 = mxCalloc(rayparam.kmax[0],sizeof(double));
0441     temp6 = mxCalloc(rayparam.kmax[0],sizeof(double));
0442     temp7 = mxCalloc(rayparam.kmax[0],sizeof(double));
0443     
0444     y0 = mxCalloc(MC,sizeof(double));
0445     yinit = mxCalloc(MC,sizeof(double));
0446     y0dot = mxCalloc(MC,sizeof(double));
0447     y1 = mxCalloc(MC,sizeof(double));
0448     s0 = mxCalloc(MC,sizeof(double));
0449     s1 = mxCalloc(MC,sizeof(double));
0450     s2 = mxCalloc(MC,sizeof(double));
0451     s3 = mxCalloc(MC,sizeof(double));
0452     s4 = mxCalloc(MC,sizeof(double));
0453     s5 = mxCalloc(MC,sizeof(double));
0454     s6 = mxCalloc(MC,sizeof(double));
0455     
0456     if (flag_proc == 1) {
0457         
0458         rayproc = mxCalloc(MPROC+2*ns,sizeof(double));;
0459         
0460         temp_proc = mxCalloc(MPROC+2*ns+1,sizeof(double *));
0461         for (i = 0;i < MPROC+2*ns+1; i++) {
0462             temp_proc[i] = mxCalloc(rayparam.kmax[0],sizeof(double));
0463         }
0464         
0465         for (i = 0;i < MPROC+2*ns+1; i++) {/*initialisation */
0466             for (kk = 0;kk < rayparam.kmax[0]; kk++) {
0467                 temp_proc[i][kk] = 0.0;
0468             }
0469         }
0470         
0471     }
0472     
0473     /* Test Input Arguments */
0474     
0475     if (rayparam.testmode[0] > 0) testparam(rayparam,equilparam,fluctparam,raymagnetic,rayprofiles,rayequil,rayfluctuations,distriparam,raydistri,flag_fluct,flag_f0,flag,y0_in);
0476     /***************************************************************************/
0477     /******************************* Runge-Kutta  ******************************/
0478     /***************************************************************************/
0479     
0480     
0481     /* Create and Initialize Return Arguments */
0482     
0483     y0[0] = y0_in[0];/* Necessary to separe data from mex and matlab */
0484     y0[1] = y0_in[1];
0485     y0[2] = y0_in[2];
0486     y0[3] = y0_in[3];
0487     y0[4] = y0_in[4];
0488     y0[5] = y0_in[5];
0489     y0[6] = y0_in[6];
0490     
0491     
0492     t1 = rayparam.t0[0];
0493     
0494     rho1 = y0[0];
0495     theta1 = y0[1];
0496     z1 = y0[2];
0497     krho1 = y0[3];
0498     m1 = y0[4];
0499     kz1 = y0[5];
0500     omega1 = y0[6];
0501     
0502     
0503     yinit[0] = y0[0];
0504     yinit[1] = y0[1];
0505     yinit[2] = y0[2];
0506     yinit[3] = y0[3];
0507     yinit[4] = y0[4];
0508     yinit[5] = y0[5];
0509     yinit[6] = y0[6];
0510     
0511     S1 = 0.0; /* initial value of path length */
0512     S_step = S1;/* initial path position */
0513     
0514     /* Solves the dispersion relation internally to remove numerical errors from initial conditions */
0515     
0516     
0517     if (flag == 0) {
0518         interpequil(rayparam,raymagnetic,rayprofiles,equilparam,fluctparam,yinit,y0,rayequil,rayfluctuations,flag_fluct,flag_metric);
0519     } else {
0520         interpequil_test(raymagnetic,rayprofiles,equilparam,yinit,flag);
0521     }
0522     
0523     
0524     alpha_rho = raymagnetic.gradrhon[0]*raymagnetic.drhoripdY[0];
0525     alpha_theta = raymagnetic.drhoripdY[1]/raymagnetic.rn[0];
0526     alpha_z = raymagnetic.drhoripdY[2]/raymagnetic.Upsilonn[0];
0527     
0528     acc = raymagnetic.Brhon[0]*(alpha_rho - alpha_theta*raymagnetic.salpha[0]) + raymagnetic.Bsn[0]*alpha_theta*raymagnetic.calpha[0] + alpha_z*raymagnetic.Bzn[0];
0529     
0530     mexPrintf("Initial accuracy :%g\n",acc);
0531     
0532     if ((fabs(flag) > 0) || (acc != 0)){
0533         /* mexPrintf("krho1:%g\n",krho1); */
0534         
0535         dsolve(1,ns,&krho1_dsolve,yinit,y0,raymagnetic,rayprofiles,X,rayparam,equilparam,fluctparam,rayequil,rayfluctuations,flag,flag_fluct);
0536         
0537         if (acc != 0) mexPrintf("The dispersion relation is first solved internally to remove numerical errors from initial conditions.\n");
0538         
0539         if (fabs((krho1_dsolve - krho1)/krho1) > 1e-3) {
0540             mexPrintf("WARNING: The relative difference between initial krho and krho after dsolve exceeds 1e-3.\n");
0541             mexPrintf("krho1,krho1_dsolve:%g,%g\n",krho1,krho1_dsolve);
0542             krho1 = krho1_dsolve;
0543         }
0544     }
0545     /* Initialization */
0546     ts = 100.0*rayparam.tfinal[0];
0547     h = rayparam.dt0[0];
0548     /* The main loop */
0549     while ((t1 < rayparam.tfinal[0]) && (k < kmax)) {
0550         ii++;
0551         /*mexPrintf("ii,k:%d,%d\n",ii,k);*/
0552         if ((t1 + h) > rayparam.tfinal[0]) {
0553             h = rayparam.tfinal[0] - t1;
0554         }
0555         if (ii > iimax) {
0556             mexPrintf("iimax is reached");
0557             goto Endloop;
0558             flag1 = 2;
0559         }
0560         /*mexPrintf("S1:%g\n",S1);*/
0561         
0562         /*
0563          ##############################################
0564          Redifinition of the metric system if necessary
0565          ##############################################
0566          */
0567 
0568         /*------------------------- Switching condition set around rho = 0.1 -----------------------------------*/
0569         if((int)rayparam.metricmode[0] == 2)
0570         {
0571         
0572         if (flag_metric == 1 && rho1 < rayparam.rhoswitch[0]*(1 - rayparam.deltaswitch[0]))
0573             {
0574                 mexPrintf("%s \n","Switching on cartesian system");
0575                 rhotheta2xy(rayparam,rayequil,equilparam,&rho1,&theta1,&krho1,&m1);
0576                 mexPrintf("%s = %d\n", "Total number of saved iterations", k);
0577                 mexPrintf("%s = %d\n", "Total number of iterations", ii);
0578                 flag_metric = 2;
0579             }
0580 
0581             if (flag_metric == 2)
0582             {
0583                 double rho,theta,t[2];
0584                 t[0]=rho1;
0585                 t[1]=theta1;
0586                 substitution(rayequil,rayparam,equilparam,&rho,&theta,&t);
0587                 if(rho > rayparam.rhoswitch[0]*(1 + rayparam.deltaswitch[0]))
0588                 {
0589                     mexPrintf("%s \n","Switching off cartesian system");
0590                     xy2rhotheta(rayparam,rayequil,equilparam,&rho1,&theta1,&krho1,&m1);
0591                     mexPrintf("%s = %d\n", "Total number of saved iterations", k);
0592                     mexPrintf("%s = %d\n", "Total number of iterations", ii);
0593                     flag_metric = 1;
0594                 }
0595             }
0596 
0597         }
0598 
0599         /*------------------------------------------------------------------------------------------------------*/
0600 
0601         if (k == -1 || fabs(S1 - S_step) >= rayparam.dS[0]){/*step stored in Matlab memory */
0602             
0603             k++;
0604             
0605             if(flag_metric == 2)/*Reset to flux coordinates for saveguard purposes if in cartesian coordinates*/
0606             {
0607                 xy2rhotheta(rayparam,rayequil,equilparam,&rho1,&theta1,&krho1,&m1);
0608             }
0609             
0610             tempt[k] = t1;
0611             temp0[k] = rho1;
0612             temp1[k] = theta1;
0613             temp2[k] = z1;
0614             temp3[k] = krho1;
0615             temp4[k] = m1;
0616             temp5[k] = kz1;
0617             temp6[k] = omega1;
0618             temp7[k] = S1;
0619             
0620             if(flag_metric == 2)/*Reset to cartesian coordinates for raytracing calculations if initially in cartesian coordinates*/
0621             {
0622                 rhotheta2xy(rayparam,rayequil,equilparam,&rho1,&theta1,&krho1,&m1);
0623             }
0624             
0625             if (flag_proc == 1) { /* calculate additional ray parameters if required */
0626                 
0627                 dS = S1 - S_step; /* ray path from k-1 to k position */
0628                 /*y0 needs to be expressed in the current metric system*/
0629                 y0[0] = rho1;
0630                 y0[1] = theta1;
0631                 y0[2] = temp2[k];
0632                 y0[3] = krho1;
0633                 y0[4] = m1;
0634                 y0[5] = temp5[k];
0635                 y0[6] = temp6[k];
0636                 
0637                 if (equilparam.zZi[0] > 0) {/*no absorption in vacuum*/
0638                     
0639                     rayprocess(ns,rayproc,rayparam,raymagnetic,rayprofiles,X,equilparam,fluctparam,yinit,y0,rayequil,rayfluctuations,distriparam,raydistri,flag_f0,flag,flag_fluct,flag_metric);
0640                     /* mexPrintf("y[0],y[1],y[2],y[3],y[4],y[5],y[6]:%g,%g,%g,%g,%g,%g,%g\n",yinit[0],yinit[1],yinit[2],yinit[3],yinit[4],yinit[5],yinit[6]);*/
0641                     /* mexPrintf("y[0],y[1],y[2],y[3],y[4],y[5],y[6]:%g,%g,%g,%g,%g,%g,%g\n",yinit[0],yinit[1],yinit[2],yinit[3],yinit[4],yinit[5],yinit[6]); */
0642                     /*return;*/
0643                     /* Stop here for debug and uncomment the calculation of Dtot which should be very close to zero*/
0644                     
0645                     
0646                     for (i=0;i/* absphi = sqrt(fabs(phix2) + fabs(phiy2) + fabs(phiz2)); */
0651                     absphi = sqrt(fabs(rayproc[9]*rayproc[9]) + fabs(rayproc[10]*rayproc[10]) + fabs(rayproc[11]*rayproc[11]));
0652                     
0653                     /* alpha = alphaphi*equilparam.ap[0]*y0[6]/CLUM/absphi; */
0654                     alpha2 = rayproc[12]*equilparam.ap[0]*y0[6]/CLUM/absphi;
0655                     
0656                     /* Optical depth */
0657                     
0658                     depth = depth + (alpha1 + alpha2)*dS/2;
0659                     
0660                     /*
0661                      if (fmod(k,200) == 0) {
0662                      mexPrintf("t,k,rho,tau:%g,%d,%g,%g\n",t1,k,y0[0],depth);
0663                      } */
0664                     
0665                     temp_proc[MPROC+2*ns][k] = depth;
0666                     
0667                     
0668                     if (tau_lim > 0.0 && depth > tau_lim) { /* The power is fully absorbed. */
0669                         mexPrintf("The wave is fully linearly damped at k = %i\n",k);
0670                         
0671                         kmax = (int)fmin((double)kmax,(double)k + rayparam.kextra[0]);
0672                         
0673                         mexPrintf("----> Calculation stopped at k = %i\n",kmax);
0674                         tau_lim = 0.0;
0675                         
0676                     }
0677                     
0678                     alpha1 = alpha2;
0679                 }
0680             }
0681             
0682             S_step = S1;
0683         }
0684         /*
0685          Compute the slopes
0686          */
0687         
0688         /* ts = t  and  s0 = y */
0689         
0690         
0691         s0[0] = rho1;
0692         s0[1] = theta1;
0693         s0[2] = z1;
0694         s0[3] = krho1;
0695         s0[4] = m1;
0696         s0[5] = kz1;
0697         s0[6] = omega1;
0698         
0699         for  (m = 0; m < MC; m++) {
0700             y1[m] = s0[m];
0701         }
0702         
0703         ray(ns,X,s1,&Sdot1,yinit,y1,raymagnetic,rayprofiles,rayparam,equilparam,fluctparam,rayequil,rayfluctuations,flag,flag_fluct,flag_metric);
0704         /* s2 = feval(F, t+h*alpha(1), y1+h*s1*beta(1,1), param); */
0705         
0706         
0707         for  (m = 0; m < MC-2; m++) {/* only the first six coordinates are evolving (rho,theta,phi,krho,m,n) */
0708             y1[m] = s0[m]+h*s1[m]*beta[0][0];
0709         }
0710         
0711         
0712         ray(ns,X,s2,&Sdot2,yinit,y1,raymagnetic,rayprofiles,rayparam,equilparam,fluctparam,rayequil,rayfluctuations,flag,flag_fluct,flag_metric);
0713         /* s3 = feval(F, t+h*alpha(2), y1+h*[s1*beta(2,1)+s2*beta(2,2)], param); */
0714         
0715         for  (m = 0; m < MC-2; m++) {
0716             y1[m] = s0[m]+h*(s1[m]*beta[0][1] + s2[m]*beta[1][1]);
0717         }
0718         
0719         ray(ns,X,s3,&Sdot3,yinit,y1,raymagnetic,rayprofiles,rayparam,equilparam,fluctparam,rayequil,rayfluctuations,flag,flag_fluct,flag_metric);
0720         
0721         /* s4 = feval(F, t+h*alpha(3), y1+h*[s1*beta(3,1)+s2*beta(3,2)+...], param); */
0722         
0723         for  (m = 0; m < MC-2; m++) {
0724             y1[m] = s0[m]+h*(s1[m]*beta[0][2] + s2[m]*beta[1][2] + s3[m]*beta[2][2]);
0725         }
0726         
0727         ray(ns,X,s4,&Sdot4,yinit,y1,raymagnetic,rayprofiles,rayparam,equilparam,fluctparam,rayequil,rayfluctuations,flag,flag_fluct,flag_metric);
0728         
0729         /* s5 = feval(F, t+h*alpha(4), y1+h*[s1*beta(4,1)+s2*beta(4,2)+...], param); */
0730         
0731         for  (m = 0; m < MC-2; m++) {
0732             y1[m] = s0[m]+h*(s1[m]*beta[0][3] + s2[m]*beta[1][3] + s3[m]*beta[2][3] + s4[m]*beta[3][3]);
0733         }
0734         
0735         
0736         ray(ns,X,s5,&Sdot5,yinit,y1,raymagnetic,rayprofiles,rayparam,equilparam,fluctparam,rayequil,rayfluctuations,flag,flag_fluct,flag_metric);
0737         
0738         /* s6 = feval(F, t+h*alpha(5), y1+h*[s1*beta(5,1)+s2*beta(5,2)+...], param); */
0739         
0740         for  (m = 0; m < MC-2; m++) {
0741             y1[m] = s0[m]+h*(s1[m]*beta[0][4] + s2[m]*beta[1][4] + s3[m]*beta[2][4] + s4[m]*beta[3][4] + s5[m]*beta[4][4]);
0742         }
0743         
0744         ray(ns,X,s6,&Sdot6,yinit,y1,raymagnetic,rayprofiles,rayparam,equilparam,fluctparam,rayequil,rayfluctuations,flag,flag_fluct,flag_metric);
0745         
0746         /*
0747          Estimate the error and the acceptable error
0748          */
0749 
0750         for  (m = 0; m < MC; m++) {
0751             ydel[m] = h*(s1[m]*gama[0][1] + s2[m]*gama[1][1] + s3[m]*gama[2][1] + s4[m]*gama[3][1] + s5[m]*gama[4][1] + s6[m]*gama[5][1]);
0752             ys[0] = s0[m];
0753             ys[1] = s1[m];
0754             ys[2] = s2[m];
0755             ys[3] = s3[m];
0756             ys[4] = s4[m];
0757             ys[5] = s5[m];
0758             ys[6] = s6[m];
0759             
0760             /*  mexPrintf("m,s0[m],s1[m],s2[m],s3[m],s4[m],s5[m],s6[m]:%d,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g\n",m,s0[m],s1[m],s2[m],s3[m],s4[m],s5[m],s6[m]); */
0761             
0762             
0763             ymax = inf_norm(ys,MC-1);
0764             ydel[m] = ydel[m]/ymax;
0765             
0766             /* mexPrintf("ys[0],ys[1],ys[2],ys[3],ys[4],ys[5],ys[6],ymax,ydel[m]:%g,%g,%g,%g,%g,%g,%g,%g,%g\n",ys[0],ys[1],ys[2],ys[3],ys[4],ys[5],ys[6],ymax,ydel[m]); */
0767             
0768         }
0769         
0770         
0771         /* mexPrintf("ydel[0],ydel[1],ydel[2],ydel[3],ydel[4],ydel[5],ydel[6]:%g,%g,%g,%g,%g,%g,%g\n",ydel[0],ydel[1],ydel[2],ydel[3],ydel[4],ydel[5],ydel[6]); */
0772         
0773         delta = inf_norm(ydel,MC-2);/* only the first six coordinates are evolving (rho,theta,phi,krho,m,n) */
0774         tau = rayparam.tol[0];
0775         
0776         /*
0777          Update the solution only if the error is acceptable
0778          */
0779         
0780         /*mexPrintf("k,kmax,t1,delta,ymax,h,rho1,theta1,z1,krho1,m1,kz1:%d,%d,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g\n",k,kmax,t1,delta,ymax,h,rho1,theta1,z1,krho1,m1,kz1);*/
0781         
0782         
0783         if (delta <= tau) {
0784             t2 = t1 + h;
0785             
0786             rhodot = s1[0]*gama[0][0] + s2[0]*gama[1][0] + s3[0]*gama[2][0] + s4[0]*gama[3][0] + s5[0]*gama[4][0] + s6[0]*gama[5][0];
0787             thetadot = s1[1]*gama[0][0] + s2[1]*gama[1][0] + s3[1]*gama[2][0] + s4[1]*gama[3][0] + s5[1]*gama[4][0] + s6[1]*gama[5][0];
0788             zdot = s1[2]*gama[0][0] + s2[2]*gama[1][0] + s3[2]*gama[2][0] + s4[2]*gama[3][0] + s5[2]*gama[4][0] + s6[2]*gama[5][0];
0789             krhodot = s1[3]*gama[0][0] + s2[3]*gama[1][0] + s3[3]*gama[2][0] + s4[3]*gama[3][0] + s5[3]*gama[4][0] + s6[3]*gama[5][0];
0790             mdot = s1[4]*gama[0][0] + s2[4]*gama[1][0] + s3[4]*gama[2][0] + s4[4]*gama[3][0] + s5[4]*gama[4][0] + s6[4]*gama[5][0];
0791             kzdot = s1[5]*gama[0][0] + s2[5]*gama[1][0] + s3[5]*gama[2][0] + s4[5]*gama[3][0] + s5[5]*gama[4][0] + s6[5]*gama[5][0];
0792             omegadot = 0.0;
0793             
0794             Sdot = Sdot1*gama[0][0] + Sdot2*gama[1][0] + Sdot3*gama[2][0] + Sdot4*gama[3][0] + Sdot5*gama[4][0] + Sdot6*gama[5][0];
0795             
0796             rho2 = rho1 + h*rhodot;
0797             theta2 = theta1 + h*thetadot;
0798             z2 = z1 + h*zdot;
0799             krho2 = krho1 + h*krhodot;
0800             m2 = m1 + h*mdot;
0801             kz2 = kz1 + h*kzdot;
0802             omega2 = omega1 + h*omegadot;
0803             S2 = S1 + h*Sdot;
0804 
0805             /* mexPrintf("t2,rho2,theta2,z2,krho2,m2,kz2:%g,%g,%g,%g,%g,%g,%g\n",t2,rho2,theta2,z2,krho2,m2,kz2);*/
0806             
0807             if(flag_metric==1)/*In order that the condition rho2 > 1.0 is always false in cartesian metric*/
0808             {
0809                 if (rho2 > 1.0) {/* Wave reflexion at rho = 1  */
0810                     if (rayparam.reflection[0] >=1.0) {/* The reflection is always enforced */
0811                         mexPrintf("********************************** Wave reflection is enforced at rho = %g**********************************\n",rho1);
0812                         rho2 = rho1;
0813                         z2 = z1;
0814                         theta2 = theta1;
0815                         omega2 = omega1;
0816                         /* S2 = S1;  */
0817                         
0818                         if (reflection(flag,X,rayparam,equilparam,fluctparam,raymagnetic,rayprofiles,&krho2,&m2,&kz2,yinit,s0,rayequil,rayfluctuations,flag_fluct) == -1) {goto Endloop;}
0819                     } else {/* The code calculates if the reflection must takes place. It calculates kpsi for vacuum (keeping the magnetic field) ray leaves the plasma only if kspi is real.*/
0820                         s0[0] = rho1;
0821                         s0[1] = theta1;
0822                         s0[2] = z1;
0823                         s0[3] = krho1;
0824                         s0[4] = m1;
0825                         s0[5] = kz1;
0826                         s0[6] = omega1;
0827                         dsolve(0,ns,&krho2,yinit,s0,raymagnetic,rayprofiles,X,rayparam,equilparam,fluctparam,rayequil,rayfluctuations,flag,flag_fluct);
0828                         /*                    mexPrintf("test2a,krho2,cimag(krho2):%g,%g,%g\n",krho2,cimag(krho2));*/
0829                         if (cimag(krho2) == 0.0) {/* ray may propagate in vacuum. Propagation is stopped */
0830                             mexPrintf("********************************** The wave leaves the plasma at rho = %g**********************************\n",rho1);
0831                             flag1 = 1;
0832                             goto Endloop;
0833                         } else {/* ray may not propagate in vacuum. Wave reflection is performed at plasma edge */
0834                             mexPrintf("********************************** Wave reflection takes place at rho = %g**********************************\n",rho1);
0835                             rho2 = rho1;
0836                             z2 = z1;
0837                             theta2 = theta1;
0838                             if (reflection(flag,X,rayparam,equilparam,fluctparam,raymagnetic,rayprofiles,&krho2,&m2,&kz2,yinit,s0,rayequil,rayfluctuations,flag_fluct) == -1) {goto Endloop;}
0839                         }
0840                     }
0841                 }
0842 
0843             }
0844             
0845             t1 = t2;
0846             rho1 = rho2;
0847             theta1 = theta2;
0848             z1 = z2;
0849             krho1 = krho2;
0850             m1 = m2;
0851             kz1 = kz2;
0852             omega1 = omega2;
0853             
0854             S1 = S2;
0855              
0856         }
0857         
0858         /*
0859          Update the step size
0860          */
0861         
0862         if (delta) {
0863             if (delta < tau) {
0864                 h = SAFETY*h*pow(tau/delta,PGROW);
0865             } else {
0866                 h = SAFETY*h*pow(tau/delta,PSHRINK);
0867             }
0868             
0869             
0870             /* mexPrintf("k,delta,tau,rho1,krho1,S1,h:%d,%g,%g,%g,%g,%g,%g\n",k,delta,tau,rho1,krho1,S1,h); */
0871             
0872         } else {
0873             mexPrintf("WARNING delta :%g, the loop is stopped.\n",delta);
0874             if (flag1 == 0) {
0875                 mexPrintf("---> The maximum number of iteration is reached.\n",delta);
0876             }
0877             if (flag1 == 1) {
0878                 mexPrintf("---> The ray leaves the plasma.\n",delta);
0879             }
0880             if (flag1 == 2) {
0881                 mexPrintf("WARNING: the code has reached a stationary point. Exit forced at %i steps.\n",iimax);
0882             }
0883             if (flag1 == 3) {
0884                 mexPrintf("WARNING: The distance of the ray to the magnetic axis is less than the minimal distance. Exit enforced.\n",delta);
0885             }
0886             goto Endloop;
0887         }
0888         
0889     }
0890     
0891     /* if (t1 < rayparam.tfinal[0]) {
0892      mexPrintf("Singularity likely at t = %f or matrix full\n",t1);
0893      }*/
0894     
0895 Endloop:
0896     
0897     mexPrintf("%d \n",k);
0898     mexPrintf("%d \n",ii);
0899     
0900     /* Create final matrix for transferring data to MatLab */
0901     
0902     T_OUT = mxCreateDoubleMatrix(k,1,mxREAL);
0903     Y_OUT = mxCreateDoubleMatrix(k,MC,mxREAL);
0904     tout = mxGetPr(T_OUT);
0905     yout = mxGetPr(Y_OUT);
0906     
0907     for (kk = 0;kk < k; kk++) {
0908         tout[kk] = tempt[kk];
0909     }
0910     for (kk = 0;kk < k; kk++) {
0911         yout[kk] = temp0[kk];
0912     }
0913     for (kk = 0;kk < k; kk++) {
0914         yout[kk + k] = temp1[kk];
0915     }
0916     for (kk = 0;kk < k; kk++) {
0917         yout[kk + 2*k] = temp2[kk];
0918     }
0919     for (kk = 0;kk < k; kk++) {
0920         yout[kk + 3*k] = temp3[kk];
0921     }
0922     for (kk = 0;kk < k; kk++) {
0923         yout[kk + 4*k] = temp4[kk];
0924     }
0925     for (kk = 0;kk < k; kk++) {
0926         yout[kk + 5*k] = temp5[kk];
0927     }
0928     for (kk = 0;kk < k; kk++) {
0929         yout[kk + 6*k] = temp6[kk];
0930     }
0931     for (kk = 0;kk < k; kk++) {
0932         yout[kk + 7*k] = temp7[kk];
0933     }
0934     
0935     /* Memory is released  */
0936     
0937     if (flag != 0) {
0938         mxFree(equilparam.zZi);
0939         mxFree(equilparam.zmi);
0940         mxFree(equilparam.ns);
0941         mxFree(equilparam.Rp);
0942         mxFree(equilparam.ap);
0943         mxFree(equilparam.Zp);
0944         mxFree(equilparam.psia_apRp);
0945     }
0946     
0947     mxFree(raymagnetic.rn);
0948     mxFree(raymagnetic.xn);
0949     mxFree(raymagnetic.yn);
0950     mxFree(raymagnetic.Brhon);
0951     mxFree(raymagnetic.Bsn);
0952     mxFree(raymagnetic.Bzn);
0953     mxFree(raymagnetic.B);
0954     mxFree(raymagnetic.salpha);
0955     mxFree(raymagnetic.calpha);
0956     mxFree(raymagnetic.gradrhon);
0957     mxFree(raymagnetic.rhorip);
0958     mxFree(raymagnetic.Upsilonn);
0959     
0960     mxFree(raymagnetic.drndY);
0961     mxFree(raymagnetic.dxndY);
0962     mxFree(raymagnetic.dyndY);
0963     mxFree(raymagnetic.dBrhondY);
0964     mxFree(raymagnetic.dBsndY);
0965     mxFree(raymagnetic.dBzndY);
0966     mxFree(raymagnetic.dBdY);
0967     mxFree(raymagnetic.dsalphadY);
0968     mxFree(raymagnetic.dcalphadY);
0969     mxFree(raymagnetic.dgradrhondY);
0970     mxFree(raymagnetic.drhoripdY);
0971     mxFree(raymagnetic.dUpsilonndY);
0972     
0973     mxFree(raymagnetic.d2rndY2);
0974     mxFree(raymagnetic.d2xndY2);
0975     mxFree(raymagnetic.d2yndY2);
0976     mxFree(raymagnetic.d2BrhondY2);
0977     mxFree(raymagnetic.d2BsndY2);
0978     mxFree(raymagnetic.d2BzndY2);
0979     mxFree(raymagnetic.d2BdY2);
0980     mxFree(raymagnetic.d2salphadY2);
0981     mxFree(raymagnetic.d2calphadY2);
0982     mxFree(raymagnetic.d2gradrhondY2);
0983     mxFree(raymagnetic.d2rhoripdY2);
0984     mxFree(raymagnetic.d2UpsilonndY2);
0985 
0986     
0987     mxFree(rayprofiles.Te);
0988     mxFree(rayprofiles.ne);
0989     mxFree(rayprofiles.zTi);
0990     mxFree(rayprofiles.zni);
0991     
0992     mxFree(rayprofiles.dTedY);
0993     mxFree(rayprofiles.dnedY);
0994     
0995     mxFree(rayprofiles.d2TedY2);
0996     mxFree(rayprofiles.d2nedY2);
0997     
0998     for (i = 0;i < ns; i++) {
0999         mxFree(rayprofiles.dzTidY[i]);
1000         mxFree(rayprofiles.dznidY[i]);
1001         mxFree(rayprofiles.d2zTidY2[i]);
1002         mxFree(rayprofiles.d2znidY2[i]);
1003     }
1004     
1005     mxFree(rayprofiles.dzTidY);
1006     mxFree(rayprofiles.dznidY);
1007     mxFree(rayprofiles.d2zTidY2);
1008     mxFree(rayprofiles.d2znidY2);
1009     
1010     mxFree(X.Xxx);
1011     mxFree(X.Xxy);
1012     mxFree(X.Xxz);
1013     mxFree(X.Xyy);
1014     mxFree(X.Xyz);
1015     mxFree(X.Xzz);
1016     
1017     mxFree(X.dXxxdNperp);
1018     mxFree(X.dXxydNperp);
1019     mxFree(X.dXxzdNperp);
1020     mxFree(X.dXyydNperp);
1021     mxFree(X.dXyzdNperp);
1022     mxFree(X.dXzzdNperp);
1023     
1024     mxFree(X.dXxxdNpar);
1025     mxFree(X.dXxydNpar);
1026     mxFree(X.dXxzdNpar);
1027     mxFree(X.dXyydNpar);
1028     mxFree(X.dXyzdNpar);
1029     mxFree(X.dXzzdNpar);
1030     
1031     mxFree(X.dXxxdY);
1032     mxFree(X.dXxydY);
1033     mxFree(X.dXxzdY);
1034     mxFree(X.dXyydY);
1035     mxFree(X.dXyzdY);
1036     mxFree(X.dXzzdY);
1037     
1038     mxFree(tempt);
1039     mxFree(temp0);
1040     mxFree(temp1);
1041     mxFree(temp2);
1042     mxFree(temp3);
1043     mxFree(temp4);
1044     mxFree(temp5);
1045     mxFree(temp6);
1046     mxFree(temp7);
1047     
1048     mxFree(y0);
1049     mxFree(y0dot);
1050     mxFree(y1);
1051     mxFree(s0);
1052     mxFree(s1);
1053     mxFree(s2);
1054     mxFree(s3);
1055     mxFree(s4);
1056     mxFree(s5);
1057     mxFree(s6);
1058     
1059     if (flag_proc == 1) {
1060         
1061         if (equilparam.zZi[0]>0) {
1062             
1063             Y_PROC = mxCreateDoubleMatrix(k,MPROC+2*ns+1,mxREAL);
1064             yproc = mxGetPr(Y_PROC);
1065             
1066             for (kk = 0;kk < k; kk++) {
1067                 for (i=0;i/* Memory is released  */
1073             
1074             for (i=0;ielse {
1082             
1083             Y_PROC = mxCreateDoubleMatrix(1,1,mxREAL);
1084             yproc = mxGetPr(Y_PROC);
1085             yproc[1] = 0.0;
1086         }
1087         
1088     }
1089     
1090     if (flag_fluct == 1) {
1091         
1092         if (fluctparam.ne_nmodel[0]) {
1093             
1094         }
1095         
1096         if (fluctparam.B_nmodel[0]) {
1097             
1098             mxFree(rayfluctuations.B_sfx_fit);
1099             mxFree(rayfluctuations.B_sfy_fit);
1100             mxFree(rayfluctuations.B_sfz_fit);
1101             
1102         }
1103         
1104        } else {
1105         
1106         mxFree(fluctparam.ne_nmodel);
1107         mxFree(fluctparam.B_nmodel);
1108        }
1109     
1110     /* End of C3PO */
1111 }
1112 
1113 
1114 
1115 
1116 double inf_norm(y,N)
1117 double  y[];
1118 unsigned int N;
1119 {
1120     register unsigned int m;
1121     double  temp_max;
1122     
1123     temp_max = fabs(y[0]);
1124     
1125     for (m = 1; m < N; m++) {
1126         temp_max = fmax(temp_max,fabs(y[m]));
1127     }
1128     
1129     return(temp_max);
1130 }
1131 
1132 
1133 /* General coordinate time evolution dY/dt with Y=[rho,theta,phi,krho,m,n,omega/c] */
1134 
1135 
1136 void ray(ns,X,Ydot,Sdot,Y0,Y,raymagnetic,rayprofiles,rayparam,equilparam,fluctparam,rayequil,rayfluctuations,flag,flag_fluct,flag_metric)/*Doesn't have to be modified under a change of metric*/
1137 int ns;
1138 susceptibilitytensor_format X;
1139 double Y0[],Y[],Ydot[],*Sdot;
1140 raymagnetic_format raymagnetic;
1141 rayprofiles_format rayprofiles;
1142 rayparam_format rayparam;
1143 equilparam_format equilparam;
1144 fluctparam_format fluctparam;
1145 rayequil_format rayequil;
1146 rayfluctuations_format rayfluctuations;
1147 double flag;
1148 int flag_fluct;
1149 int flag_metric;
1150 {
1151     
1152     register int i,j;
1153     
1154     double Npar,dNpardY[MC];
1155     double complex Dtot,dDtotdY[MC];
1156     double complex Nperp,dNperpdY[MC],N2,dN2dY[MC],eikval;
1157     
1158     double Sdot2;
1159     double Gcov[3][3];
1160     double wcn[ns+1],wpn2[ns+1],betath[ns+1];
1161     
1162     
1163     /* Equilibrium interpolation at ray location */
1164     if (flag == 0) {
1165         interpequil(rayparam,raymagnetic,rayprofiles,equilparam,fluctparam,Y0,Y,rayequil,rayfluctuations,flag_fluct,flag_metric);
1166     } else {
1167         interpequil_test(raymagnetic,rayprofiles,equilparam,Y,flag);
1168     }
1169     
1170     /* Refractive index calculation */
1171     rayindex(&Nperp,dNperpdY,&N2,dN2dY,flag_metric,Y,raymagnetic,equilparam,&Npar,dNpardY,&eikval);
1172     
1173     /*
1174      mexPrintf("rn,xn,yn,Brhon,Bsn,krho,sina,cosa,B,Bzn:%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g\n",raymagnetic.rn[0],raymagnetic.xn[0],raymagnetic.yn[0],raymagnetic.Brhon[0],raymagnetic.Bsn[0],Y[3],raymagnetic.salpha[0],raymagnetic.calpha[0],raymagnetic.B[0],raymagnetic.Bzn[0]);
1175      mexPrintf("Npar,w*dNpardw,Nperpr,Nperpi,w*dNperpdwr,w*dNperpdwi:%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g\n",Npar,dNpardY[6],Nperp,dNperpdY[6]);
1176      */
1177     
1178     /*mexPrintf("Eikonal validity (<< 1):%g,%g\n",eikval);*/
1179     
1180     
1181     /* Susceptibility tensor  */
1182     
1183     susceptibility(X,Nperp,dNperpdY,wcn,wpn2,betath,rayparam.tensortype[0],(int)rayparam.ncyclharm[0],equilparam,raymagnetic,rayprofiles,Npar,dNpardY,Y[6]);
1184     
1185     /* mexPrintf("X.Xxx[0],X.Xxy[0],X.Xxz[0],X.Xyy[0],X.Xyz[0],X.Xzz[0],%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g\n",X.Xxx[0],X.Xxy[0],X.Xxz[0],X.Xyy[0],X.Xyz[0],X.Xzz[0]); */
1186     
1187     if (flag < 0) {/* dispersion relation */
1188         disprel(dDtotdY,&Dtot,X,dNperpdY,Nperp,dN2dY,N2,dNpardY,Npar,3);
1189     } else {
1190         disprel(dDtotdY,&Dtot,X,dNperpdY,Nperp,dN2dY,N2,dNpardY,Npar,1);
1191     }
1192     
1193     if (equilparam.zZi[0] > 0) {
1194         Ydot[0] = -creal(dDtotdY[3])/creal(dDtotdY[6]);
1195         Ydot[1] = -creal(dDtotdY[4])/creal(dDtotdY[6]);
1196         Ydot[2] = -creal(dDtotdY[5])/creal(dDtotdY[6]);
1197         Ydot[3] = creal(dDtotdY[0])/creal(dDtotdY[6]);
1198         Ydot[4] = creal(dDtotdY[1])/creal(dDtotdY[6]);
1199         Ydot[5] = creal(dDtotdY[2])/creal(dDtotdY[6]);
1200         Ydot[6] = 0.0;
1201     } else {/* vacuum case */
1202         Ydot[0] = -creal(dN2dY[3])/creal(dN2dY[6]);
1203         Ydot[1] = -creal(dN2dY[4])/creal(dN2dY[6]);
1204         Ydot[2] = -creal(dN2dY[5])/creal(dN2dY[6]);
1205         Ydot[3] = creal(dN2dY[0])/creal(dN2dY[6]);
1206         Ydot[4] = creal(dN2dY[1])/creal(dN2dY[6]);
1207         Ydot[5] = creal(dN2dY[2])/creal(dN2dY[6]);
1208         Ydot[6] = 0.0;
1209     }
1210     /* Calculation of the infinitesimal path length */
1211     
1212     metrictensor(Gcov,raymagnetic,flag_metric);
1213     
1214     Sdot2 = 0.0;
1215     
1216     for (i=0;i<3;i++) {
1217         for (j=0;j<3;j++) {
1218             Sdot2 = Sdot2 + Gcov[i][j]*Ydot[i]*Ydot[j];
1219         }
1220     }
1221     
1222     Sdot[0] = sqrt(Sdot2);
1223     
1224     /* test for the cold dispersion relation */
1225     /*
1226      double complex P0,P2,P4,dP0dY[MC],dP2dY[MC],dP4dY[MC];
1227      double complex Kpar,Kperp,Kxy,dKpardY[MC],dKperpdY[MC],dKxydY[MC];
1228      double complex Dot_cold,dDtot_colddY[MC];
1229      double Ydot_cold[MC];
1230      
1231      Kpar = (1 + Xzz)/N2;
1232      Kperp = (1 + Xxx)/N2;
1233      Kxy = I*Xxy/N2;
1234      
1235      P0 = Kpar*((Npar2/N2 - Kperp)*(Npar2/N2 - Kperp) - Kxy*Kxy);
1236      P2 = (Npar2/N2 - Kperp)*(Kpar + Kperp) + Kxy*Kxy;
1237      P4 = Kperp;
1238      
1239      Dot_cold = P4*Nperp4/N2/N2 + P2*Nperp2/N2 + P0;
1240      mexPrintf("Dtot_cold:%g,%g\n",Dot_cold);
1241      
1242      for (i=0;i<MC;i++) {
1243      dKpardY[i] = X.dXzzdY[i]/N2 - (1+Xzz)*dN2dY[i]/N2/N2;
1244      dKperpdY[i] = X.dXxxdY[i]/N2 - (1+Xxx)*dN2dY[i]/N2/N2;
1245      dKxydY[i] = I*X.dXxydY[i]/N2 - I*Xxy*dN2dY[i]/N2/N2;
1246      dP0dY[i] = dKpardY[i]*((Npar2/N2 - Kperp)*(Npar2/N2 - Kperp) - Kxy*Kxy) + Kpar*(2*(Npar2/N2 - Kperp)*(2*Npar1*dNpardY[i]/N2 - Npar2*dN2dY[i]/N2/N2 - dKperpdY[i]) - 2*Kxy*dKxydY[i]);
1247      dP2dY[i] = (2*Npar1*dNpardY[i]/N2 - Npar2*dN2dY[i]/N2/N2 - dKperpdY[i])*(Kpar + Kperp) + (Npar2/N2 - Kperp)*(dKpardY[i] + dKperpdY[i]) + 2*Kxy*dKxydY[i];
1248      dP4dY[i] = dKperpdY[i];
1249      dDtot_colddY[i] = dP4dY[i]*Nperp4/N2/N2 + dP2dY[i]*Nperp2/N2 + dP0dY[i] + P4*(4*Nperp3*dNperpdY[i]/N2/N2 - 2*Nperp4*dN2dY[i]/N2/N2/N2) + P2*(2*Nperp*dNperpdY[i]/N2 - Nperp2*dN2dY[i]/N2/N2);
1250      }
1251      
1252      Ydot[0] = -creal(dDtot_colddY[3])/creal(dDtot_colddY[6]);
1253      Ydot[1] = -creal(dDtot_colddY[4])/creal(dDtot_colddY[6]);
1254      Ydot[2] = -creal(dDtot_colddY[5])/creal(dDtot_colddY[6]);
1255      Ydot[3] = creal(dDtot_colddY[0])/creal(dDtot_colddY[6]);
1256      Ydot[4] = creal(dDtot_colddY[1])/creal(dDtot_colddY[6]);
1257      Ydot[5] = 0.0;
1258      Ydot[6] = 0.0;
1259      */
1260     
1261     /*
1262      
1263      mexPrintf("dN2dY[1]:%g\n",dN2dY[1]);
1264      mexPrintf("dDtotdY:%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g\n",dDtotdY[0],dDtotdY[1],dDtotdY[2],dDtotdY[3],dDtotdY[4],dDtotdY[5],dDtotdY[6],dDtotdY[7]);
1265      mexPrintf("dDtot_colddY:%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g\n",dDtot_colddY[0],dDtot_colddY[1],dDtot_colddY[2],dDtot_colddY[3],dDtot_colddY[4],dDtot_colddY[5],dDtot_colddY[6]);
1266      mexPrintf("Ydot:%g,%g,%g,%g,%g,%g,%g,%g\n",Ydot[0],Ydot[1],Ydot[2],Ydot[3],Ydot[4],Ydot[5],Ydot[6],Ydot[7]);
1267      mexPrintf("Ydot_cold:%g,%g,%g,%g,%g,%g,%g\n",Ydot_cold[0],Ydot_cold[1],Ydot_cold[2],Ydot_cold[3],Ydot_cold[4],Ydot_cold[5],Ydot_cold[6]);
1268      
1269      */
1270     
1271 }
1272 
1273 void metrictensor(Gcov,raymagnetic,flag_metric)/*Has to be modified under a change of metric*/
1274 double Gcov[3][3];
1275 raymagnetic_format raymagnetic;
1276 int flag_metric;
1277 {
1278     if (flag_metric == 1)/*Flux case*/
1279     {
1280         Gcov[0][0] = 1/raymagnetic.gradrhon[0]/raymagnetic.gradrhon[0]/raymagnetic.calpha[0]/raymagnetic.calpha[0];
1281         Gcov[0][1] = raymagnetic.rn[0]*raymagnetic.salpha[0]/raymagnetic.gradrhon[0]/raymagnetic.calpha[0]/raymagnetic.calpha[0];
1282         Gcov[0][2] = 0;
1283         Gcov[1][0] = Gcov[0][1];
1284         Gcov[1][1] = raymagnetic.rn[0]*raymagnetic.rn[0]/raymagnetic.calpha[0]/raymagnetic.calpha[0];
1285         Gcov[1][2] = 0;
1286         Gcov[2][0] = Gcov[0][2];
1287         Gcov[2][1] = Gcov[1][2];
1288         Gcov[2][2] = raymagnetic.Upsilonn[0]*raymagnetic.Upsilonn[0];
1289     }
1290     else/*Cartesian case*/
1291     {
1292         Gcov[0][0]=1;
1293         Gcov[0][1]=0;
1294         Gcov[0][2]=0;
1295         Gcov[1][0]=0;
1296         Gcov[1][1]=1;
1297         Gcov[1][2]=0;
1298         Gcov[2][0]=0;
1299         Gcov[2][1]=0;
1300         Gcov[2][2]=raymagnetic.Upsilonn[0]*raymagnetic.Upsilonn[0];
1301     }
1302 }
1303 
1304 
1305 void polarization(X,Npar,Nperp,epolx,epoly,epolz,epolp,epolm)/*Doesn't have to be modified under a change of metric*/
1306 susceptibilitytensor_format X;
1307 double Npar;
1308 double complex Nperp,*epolx,*epoly,*epolz,*epolp,*epolm;
1309 {
1310     double complex a,b,c;
1311     double epolnorm;
1312     
1313     a = X.Xxz[0] + Npar*Nperp;
1314     b = Npar*Npar - 1.0 - X.Xxx[0];
1315     c = Nperp*Nperp - 1.0 - X.Xzz[0];
1316     
1317     /*
1318      epolx[0] = -I*(X.Xxy[0] - X.Xyz[0]*a/c);
1319      epoly[0] = -I*(b - a*a/c);
1320      epolz[0] = (X.Xyz[0]*b - X.Xxy[0]*a)/c;
1321      */
1322     
1323     epolx[0] = I*(X.Xxy[0] - X.Xyz[0]*a/c);
1324     epoly[0] = -I*(b - a*a/c);
1325     epolz[0] = -I*(X.Xyz[0]*b - X.Xxy[0]*a)/c;
1326     
1327     epolnorm = sqrt(cabs(epolx[0])*cabs(epolx[0]) + cabs(epoly[0])*cabs(epoly[0]) + cabs(epolz[0])*cabs(epolz[0]));
1328     
1329     epolx[0] = epolx[0]/epolnorm;
1330     epoly[0] = epoly[0]/epolnorm;
1331     epolz[0] = epolz[0]/epolnorm;
1332     
1333     epolp[0] = (epolx[0] + I*epoly[0])/sqrt(2.0);
1334     epolm[0] = (epolx[0] - I*epoly[0])/sqrt(2.0);
1335 }
1336 
1337 
1338 void rayprocess(ns,rayproc,rayparam,raymagnetic,rayprofiles,X,equilparam,fluctparam,Y0,Y,rayequil,rayfluctuations,distriparam,raydistri,flag_f0,flag,flag_fluct,flag_metric)/* Has to be modified under a change of metric*/
1339 int ns;
1340 double rayproc[];
1341 rayparam_format rayparam;
1342 raymagnetic_format raymagnetic;
1343 rayprofiles_format rayprofiles;
1344 susceptibilitytensor_format X;
1345 equilparam_format equilparam;
1346 fluctparam_format fluctparam;
1347 double Y0[],Y[];
1348 rayequil_format rayequil;
1349 rayfluctuations_format rayfluctuations;
1350 distriparam_format distriparam;
1351 raydistri_format raydistri;
1352 int flag_f0;
1353 double flag;
1354 int flag_fluct;
1355 int flag_metric;
1356 {
1357     double Npar,Npar2,dNpardY[MC];
1358     double complex Nperp,dNperpdY[MC];
1359     double complex N2,dN2dY[MC];
1360     
1361     double complex Dtot,dDtotdY[MC];
1362     double complex epolx,epoly,epolz,epolp,epolm;
1363     double complex d,eikval;
1364     double alphaphi = 0.0,phix,phiy,phiz,pmin,pmax,yn,yn2;
1365     int n,nmin,nmax,flagn;
1366     register int i;
1367     
1368     double wcn[ns+1],wpn2[ns+1],betath[ns+1];
1369     
1370     double *Xf0,*dXf0drho,*d2Xf0drho2;
1371     double *PSI;
1372     double *pn,*mhu;
1373     int npn,nmhu;
1374     double dummy1;
1375     
1376     double qe = 1.602176462e-19;/*Absolute value of the electron charge (C) */
1377     double me = 9.10938188e-31;/*Electron rest mass (Kg) */
1378     double epsi0 = 8.854187818e-12;/*Free space permittivity (F/m) */
1379     
1380     
1381     /* Equilibrium interpolation at ray location */
1382     if (flag == 0) {
1383         interpequil(rayparam,raymagnetic,rayprofiles,equilparam,fluctparam,Y0,Y,rayequil,rayfluctuations,flag_fluct,flag_metric);
1384     } else {
1385         interpequil_test(raymagnetic,rayprofiles,equilparam,Y,flag);
1386     }
1387     
1388     /* Refractive index calculation */
1389     rayindex(&Nperp,dNperpdY,&N2,dN2dY,flag_metric,Y,raymagnetic,equilparam,&Npar,dNpardY,&eikval);
1390     
1391     /* Susceptibility tensor  */
1392     susceptibility(X,Nperp,dNperpdY,wcn,wpn2,betath,rayparam.tensortype[0],(int)rayparam.ncyclharm[0],equilparam,raymagnetic,rayprofiles,Npar,dNpardY,Y[6]);
1393     /* dispersion relation */
1394     disprel(dDtotdY,&Dtot,X,dNperpdY,Nperp,dN2dY,N2,dNpardY,Npar,2);
1395     
1396     /* test mode */
1397     
1398     /*
1399      epolp = 0.7;
1400      epolm = 0.7;
1401      epolz = 0.1;
1402      n = 0;
1403      phix = 0.1;
1404      phiy = 0.0;
1405      phiz = 0.5;
1406      */
1407     
1408     /* polarization vector */
1409     
1410     polarization(X,Npar,Nperp,&epolx,&epoly,&epolz,&epolp,&epolm);
1411     
1412     /* energy flow vector */
1413     
1414     /* poynting contribution */
1415     
1416     phix = creal(Nperp);
1417     phiy = 0;
1418     phiz = Npar;
1419     
1420     d = conj(epolx)*Nperp + conj(epolz)*Npar;
1421     
1422     phix = phix - creal(d*epolx);
1423     phiy = phiy - creal(d*epoly);
1424     phiz = phiz - creal(d*epolz);
1425     
1426     /* thermal contribution */
1427     
1428     /*mexPrintf("epolx,epoly,epolz,d:%g+i*%g,%g+i*%g,%g+i*%g,%g+i*%g\n",epolx,epoly,epolz,d);
1429      mexPrintf("creal(Nperp),Npar,-creal(d*epolx),-creal(d*epoly),-creal(d*epolz):%g,%g,%g,%g,%g\n",creal(Nperp),Npar,-creal(d*epolx),-creal(d*epoly),-creal(d*epolz));
1430      mexPrintf("phiPx,phiPy,phiPz:%g,%g,%g\n",phix,phiy,phiz);*/
1431     
1432     phix = phix - creal(conj(epolx)*X.dXxxdNperp[0]*epolx)/2
1433     - 2*creal(conj(epolx)*X.dXxydNperp[0]*epoly)/2
1434     - 2*creal(conj(epolx)*X.dXxzdNperp[0]*epolz)/2
1435     - creal(conj(epoly)*X.dXyydNperp[0]*epoly)/2
1436     - 2*creal(conj(epoly)*X.dXyzdNperp[0]*epolz)/2
1437     - creal(conj(epolz)*X.dXzzdNperp[0]*epolz)/2;
1438     
1439     phiz = phiz - creal(conj(epolx)*X.dXxxdNpar[0]*epolx)/2
1440     - 2*creal(conj(epolx)*X.dXxydNpar[0]*epoly)/2
1441     - 2*creal(conj(epolx)*X.dXxzdNpar[0]*epolz)/2
1442     - creal(conj(epoly)*X.dXyydNpar[0]*epoly)/2
1443     - 2*creal(conj(epoly)*X.dXyzdNpar[0]*epolz)/2
1444     - creal(conj(epolz)*X.dXzzdNpar[0]*epolz)/2;
1445     
1446     /*mexPrintf("phiP,phiP,phiP:%g,%g,%g\n",phix,phiy,phiz);*/
1447     
1448     /*mexPrintf("wpn2,wcn,betath,Npar,Nperp,epolp,epolm,epolz,n,rel_opt,nperp,pperpmax:%g,%g,%g,%g,%g,%g,%g,%g,%i,%i,%i,%g\n",wpn2[0],wcn[0],betath[0],Npar,creal(Nperp),epolp,epolm,epolz,n,(int)rayparam.rel_opt[0],(int)rayparam.nperp[0],rayparam.pperpmax[0]);*/
1449     
1450     /* harmonics to be considered */
1451     
1452     flagn = 0;
1453     Npar2 = Npar*Npar;
1454     pmax = rayparam.pperpmax[0];
1455     
1456     if (Npar2 > 1 && betath[0]*pmax*sqrt(Npar2 - 1) > 1) {
1457         nmin = 0; /* Landau damping is significant */
1458     } else {
1459         nmin = 1; /* Only cyclotron damping is significant */
1460     }
1461     
1462     nmax = 0;
1463     
1464     while (flagn == 0) {
1465         nmax = nmax + 1;
1466         
1467         yn = -wcn[0]*nmax;
1468         yn2 = yn*yn;
1469         
1470         /* Minimum of p on resonance curves */
1471         
1472         if (Npar2 > 1) {
1473             pmin = fabs(sqrt(yn2 + Npar2 - 1) - sqrt(Npar2)*yn)/(Npar2 - 1)/betath[0];
1474         } else {
1475             if (Npar2 == 1) {
1476                 pmin = fabs(yn2 - 1)/yn/betath[0]/2;
1477             } else {
1478                 if (Npar2 < 1) {
1479                     if (yn2 > 1 - Npar2) {
1480                         pmin = fabs(sqrt(yn2 + Npar2 - 1) - sqrt(Npar2)*yn)/(1 - Npar2)/betath[0];
1481                     } else {
1482                         pmin = pmax + 1;
1483                     }
1484                 }}}
1485         
1486         if (pmin > pmax) {
1487             if (yn <= 1) { /* LFS */
1488                 if (nmin > 0) {
1489                     nmin = nmin + 1;
1490                 }
1491             } else { /* HFS */
1492                 nmax = nmax - 1;
1493                 flagn = 1;
1494             }
1495         }
1496     }
1497     
1498     /*mexPrintf("nmin,nmax:%i,%i\n",nmin,nmax);*/
1499     
1500     /* wave absorption coefficient */
1501     
1502     if (flag_f0 == 1) {/* non-Maxwellian electron distribution */
1503         
1504         Xf0 = mxCalloc(distriparam.npn[0]*distriparam.nmhu[0],sizeof(double));
1505         dXf0drho = mxCalloc(distriparam.npn[0]*distriparam.nmhu[0],sizeof(double));
1506         d2Xf0drho2 = mxCalloc(distriparam.npn[0]*distriparam.nmhu[0],sizeof(double));
1507         PSI = mxCalloc(1,sizeof(double));
1508         
1509         if (flag_metric == 1)
1510         {
1511             ppvald_1D(raydistri.f0_fit,rayparam.dS[0],Y[0],Xf0,dXf0drho,d2Xf0drho2);
1512             ppvald_2D(raydistri.PSI_fit,rayparam.dS[0],Y[0],Y[1],PSI,&dummy1,&dummy1,&dummy1,&dummy1,&dummy1);
1513         }
1514         else
1515         {
1516             double rho,theta;
1517             substitution(rayequil,rayparam,equilparam,&rho,&theta,Y);
1518             ppvald_1D(raydistri.f0_fit,rayparam.dS[0],rho,Xf0,dXf0drho,d2Xf0drho2);
1519             ppvald_2D(raydistri.PSI_fit,rayparam.dS[0],rho,theta,PSI,&dummy1,&dummy1,&dummy1,&dummy1,&dummy1);
1520         }
1521         
1522         pn = distriparam.pn;
1523         npn = distriparam.npn[0];
1524         
1525         mhu = distriparam.mhu;
1526         nmhu = distriparam.nmhu[0];
1527         
1528         /********** WARNING: alphaphi_jd MUST be modified before using these quantities YP **************/
1529         
1530         /*wpn2[0] = qe*qe*distriparam.ne_ref[0]/epsi0/me/Y[6]/Y[6];*/ /*electrons */
1531         /*betath[0] = distriparam.betath_ref[0];*/
1532         
1533         /************************************************************************************************/
1534         
1535     } else {/* Maxwellian electron distribution */
1536         
1537         Xf0 = mxCalloc(1,sizeof(double));
1538         dXf0drho = mxCalloc(1,sizeof(double));
1539         d2Xf0drho2 = mxCalloc(1,sizeof(double));
1540         
1541         PSI = mxCalloc(1,sizeof(double));
1542         
1543         pn = mxCalloc(1,sizeof(double));
1544         npn = 1;
1545         
1546         mhu = mxCalloc(1,sizeof(double));
1547         nmhu = 1;
1548     }
1549     
1550     for (n=nmin;nint)rayparam.rel_opt[0],(int)rayparam.nperp[0],pmax,npn,pn,nmhu,mhu,Xf0,PSI);
1552     }
1553     
1554     if (flag_f0 == 1) {/* non-Maxwellian electron distribution */
1555         mxFree(Xf0);
1556         mxFree(dXf0drho);
1557         mxFree(d2Xf0drho2);
1558         mxFree(PSI);
1559     } else {/* Maxwellian electron distribution */
1560         mxFree(Xf0);
1561         mxFree(dXf0drho);
1562         mxFree(d2Xf0drho2);
1563         mxFree(PSI);
1564         mxFree(pn);
1565         mxFree(mhu);
1566     }
1567     
1568     rayproc[0] = cabs(Dtot);
1569     disprel(dDtotdY,&Dtot,X,dNperpdY,Nperp,dN2dY,N2,dNpardY,Npar,1);
1570     rayproc[1] = Npar;
1571     rayproc[2] = creal(Nperp);
1572     rayproc[3] = creal(epolp);
1573     rayproc[4] = cimag(epolp);
1574     rayproc[5] = creal(epolm);
1575     rayproc[6] = cimag(epolm);
1576     rayproc[7] = creal(epolz);
1577     rayproc[8] = cimag(epolz);
1578     rayproc[9] = phix;
1579     rayproc[10] = phiy;
1580     rayproc[11] = phiz;
1581     rayproc[12] = alphaphi;
1582     rayproc[13] = raymagnetic.xn[0];
1583     rayproc[14] = raymagnetic.yn[0];
1584     rayproc[15] = raymagnetic.B[0];
1585     rayproc[16] = raymagnetic.Brhon[0];
1586     rayproc[17] = raymagnetic.Bsn[0];
1587     rayproc[18] = raymagnetic.Bzn[0];
1588     rayproc[19] = raymagnetic.rn[0];
1589     rayproc[20] = raymagnetic.salpha[0];
1590     rayproc[21] = raymagnetic.gradrhon[0];
1591     rayproc[22] = eikval;
1592     rayproc[23] = raymagnetic.Upsilonn[0];
1593     
1594     rayproc[24] = rayprofiles.Te[0];
1595     rayproc[25] = rayprofiles.ne[0];
1596     
1597     for (i=0;iint reflection(flag,X,rayparam,equilparam,fluctparam,raymagnetic,rayprofiles,krho2,m2,kz2,Y0,Y,rayequil,rayfluctuations,flag_fluct)/*Doesn't have to be modified under a change of metric that only applies to the center of the grid*/
1607 double flag;
1608 susceptibilitytensor_format X;
1609 rayparam_format rayparam;
1610 equilparam_format equilparam;
1611 fluctparam_format fluctparam;
1612 raymagnetic_format raymagnetic;
1613 rayprofiles_format rayprofiles;
1614 double *krho2,*m2,*kz2;
1615 double Y0[],Y[];
1616 rayequil_format rayequil;
1617 rayfluctuations_format rayfluctuations;
1618 int flag_fluct;
1619 {
1620     double complex Dtot,dDtotdY[MC];
1621     
1622     double Npar,Npar2,dNpardY[MC];
1623     double complex Nperp,dNperpdY[MC];
1624     double complex N2,dN2dY[MC],eikval;
1625     
1626     double wcn[equilparam.ns[0]+1],wpn2[equilparam.ns[0]+1],betath[equilparam.ns[0]+1];
1627     
1628     double alpha_rho,alpha_theta,alpha_z;
1629     double beta_r,beta_theta,beta_z;
1630     double a11,a12,a13,a21,a22,a23,a31,a32,a33,b1,b2,b3,det;
1631     double acc,krho_dsolve;
1632     
1633     double Yguess[MC];
1634     
1635     
1636     /* Equilibrium interpolation at ray location */
1637     if (flag == 0) {
1638         interpequil(rayparam,raymagnetic,rayprofiles,equilparam,fluctparam,Y0,Y,rayequil,rayfluctuations,flag_fluct,1);
1639     } else {
1640         interpequil_test(raymagnetic,rayprofiles,equilparam,Y,flag);
1641     }
1642     
1643     /* Refractive index calculation */
1644     
1645     rayindex(&Nperp,dNperpdY,&N2,dN2dY,1,Y,raymagnetic,equilparam,&Npar,dNpardY,&eikval);
1646     
1647     /* Susceptibility tensor  */
1648     
1649     susceptibility(X,Nperp,dNperpdY,wcn,wpn2,betath,rayparam.tensortype[0],(int)rayparam.ncyclharm[0],equilparam,raymagnetic,rayprofiles,Npar,dNpardY,Y[6]);
1650     
1651     /* dispersion relation */
1652     
1653     disprel(dDtotdY,&Dtot,X,dNperpdY,Nperp,dN2dY,N2,dNpardY,Npar,3);
1654     /*mexPrintf("Disprel_in reflection:%g\n",creal(Dtot));*/
1655     
1656     /* calculation of the rotation angle beta around Bfield direction with the condition k2.grad(rho) = -k1.grad(rho) where rho is the perturbed magnetic flux surface */
1657     
1658     alpha_rho = raymagnetic.gradrhon[0]*raymagnetic.drhoripdY[0];
1659     alpha_theta = raymagnetic.drhoripdY[1]/raymagnetic.rn[0];
1660     alpha_z = raymagnetic.drhoripdY[2]/raymagnetic.Upsilonn[0];
1661     
1662     beta_r = -raymagnetic.salpha[0]*raymagnetic.Bzn[0]*alpha_rho + alpha_theta*raymagnetic.Bzn[0] + alpha_z*(raymagnetic.Brhon[0]*raymagnetic.salpha[0] - raymagnetic.Bsn[0]*raymagnetic.calpha[0]);
1663     beta_theta = -raymagnetic.calpha[0]*raymagnetic.Bzn[0]*alpha_rho + alpha_z*(raymagnetic.Brhon[0]*raymagnetic.calpha[0] + raymagnetic.Bsn[0]*raymagnetic.salpha[0]);
1664     beta_z = raymagnetic.Bsn[0]*alpha_rho - alpha_theta*(raymagnetic.Brhon[0]*raymagnetic.calpha[0] + raymagnetic.Bsn[0]*raymagnetic.salpha[0]);
1665     
1666     a11 = raymagnetic.gradrhon[0]*alpha_rho;
1667     a12 = (alpha_theta*raymagnetic.calpha[0] - alpha_rho*raymagnetic.salpha[0])/raymagnetic.rn[0];
1668     a13 = alpha_z/raymagnetic.Upsilonn[0];
1669     
1670     a21 = raymagnetic.gradrhon[0]*raymagnetic.Brhon[0];
1671     a22 = (raymagnetic.Bsn[0]*raymagnetic.calpha[0] - raymagnetic.Brhon[0]*raymagnetic.salpha[0])/raymagnetic.rn[0];
1672     a23 = raymagnetic.Bzn[0]/raymagnetic.Upsilonn[0];
1673     
1674     a31 = raymagnetic.gradrhon[0]*(beta_r*raymagnetic.calpha[0] - beta_theta*raymagnetic.salpha[0]);
1675     a32 = beta_theta/raymagnetic.rn[0];
1676     a33 = beta_z/raymagnetic.Upsilonn[0];
1677     
1678     b1 = -a11*Y[3] - a12*Y[4] - a13*Y[5];
1679     b2 = a21*Y[3] + a22*Y[4] + a23*Y[5];
1680     b3 = a31*Y[3] + a32*Y[4] + a33*Y[5];
1681     
1682     det = a11*(a22*a33 - a23*a32) - a21*(a12*a33 - a32*a13) + a31*(a12*a23 - a22*a13);
1683     
1684     krho2[0] = (b1*(a22*a33 - a23*a32) - b2*(a12*a33 - a32*a13) + b3*(a12*a23 - a22*a13))/det;
1685     m2[0] = (a11*(b2*a33 - a23*b3) - a21*(b1*a33 - b3*a13) + a31*(b1*a23 - b2*a13))/det;
1686     kz2[0] = (a11*(a22*b3 - b2*a32) - a21*(a12*b3 - a32*b1) + a31*(a12*b2 - a22*b1))/det;
1687     
1688     /* simple expressions for the axisymmetric case only for benchmarking */
1689     
1690     /* mexPrintf("General calculation -> krho2[0],m2[0],n2[0]:%g,%g,%g\n",krho2[0],m2[0],n2[0]);
1691      
1692      krho2[0] = 2.0*Y[4]*raymagnetic.salpha[0]/raymagnetic.rn[0]/raymagnetic.gradrhon[0] - Y[3];
1693      m2[0] = Y[4];
1694      n2[0] = Y[5];
1695      
1696      mexPrintf("Axisymmetric case -> krho2[0],m2[0],n2[0]:%g,%g,%g\n",krho2[0],m2[0],n2[0]);
1697      mexPrintf("Initial values -> krho1[0],m1[0],n1[0]:%g,%g,%g\n",Y[3],Y[4],Y[5]);
1698      
1699      mexPrintf("General calculation -> alpha_rho,alpha_theta,alpha_z:%g,%g,%g\n",alpha_rho,alpha_theta,alpha_z);
1700      mexPrintf("General calculation -> raymagnetic.Brhon[0],raymagnetic.Bsn[0],raymagnetic.Bzn[0]:%g,%g,%g\n",raymagnetic.Brhon[0],raymagnetic.Bsn[0],raymagnetic.Bzn[0]);
1701      mexPrintf("General calculation -> raymagnetic.calpha[0],raymagnetic.salpha[0],raymagnetic.gradrhon[0]:%g,%g,%g\n",raymagnetic.calpha[0],raymagnetic.salpha[0],raymagnetic.gradrhon[0]);
1702      */
1703     
1704     /*correct lack of accuracy of the magnetic topology in presence of fluctuation when Brho is not exatly zero */
1705     
1706     acc = raymagnetic.Brhon[0]*(alpha_rho - alpha_theta*raymagnetic.salpha[0]) + raymagnetic.Bsn[0]*alpha_theta*raymagnetic.calpha[0] + alpha_z*raymagnetic.Bzn[0];
1707     
1708     if (acc != 0) {
1709         
1710         Yguess[0] = Y[0];
1711         Yguess[1] = Y[1];
1712         Yguess[2] = Y[2];
1713         Yguess[3] = krho2[0];
1714         Yguess[4] = m2[0];
1715         Yguess[5] = kz2[0];
1716         Yguess[6] = Y[6];
1717         dsolve(1,equilparam.ns[0],&krho_dsolve,Y0,Yguess,raymagnetic,rayprofiles,X,rayparam,equilparam,fluctparam,rayequil,rayfluctuations,flag,flag_fluct);
1718         /* mexPrintf("General calculation -> krho_in,krho_reflection,krho_reflection_dsolve:%g,%g,%g\n",Y[3],krho2[0],krho_dsolve);*/
1719         krho2[0] = krho_dsolve;
1720         mexPrintf("The dispersion relation is solved at the reflection point to avoid cumulative propagation of numerical errors.\n");
1721         if (fabs((krho_dsolve - krho2[0])/krho2[0]) > 1e-3) mexPrintf("WARNING: The relative difference between krho after reflection and krho after dsolve exceeds 1e-3.\n");
1722         
1723     }
1724     
1725     return(0);
1726 }
1727 
1728 
1729 void dsolve(mode,ns,krho,Y0,Y,raymagnetic,rayprofiles,X,rayparam,equilparam,fluctparam,rayequil,rayfluctuations,flag,flag_fluct)/*Doesn't have to be modified under a change of metric that only applies to the grid's center*/
1730 int mode,ns;
1731 double *krho;
1732 double Y0[],Y[];
1733 raymagnetic_format raymagnetic;
1734 rayprofiles_format rayprofiles;
1735 susceptibilitytensor_format X;
1736 rayparam_format rayparam;
1737 equilparam_format equilparam;
1738 fluctparam_format fluctparam;
1739 rayequil_format rayequil;
1740 rayfluctuations_format rayfluctuations;
1741 double flag;
1742 int flag_fluct;
1743 {
1744     double Npar,dNpardY[MC];
1745     double complex Nperp,dNperpdY[MC];
1746     double complex N2,dN2dY[MC],eikval;
1747     
1748     double frac,fracmax,exp,tol;
1749     double krho0,krho1,krho2,dkrho;
1750     double complex cD0,cD1,dDtotdY[MC];
1751     double D0,D1,D2;
1752     int maxit;
1753     
1754     double wcn[ns+1],wpn2[ns+1],betath[ns+1];
1755     register int j;
1756     
1757     frac = 1 - 1e-4;
1758     fracmax = 2;
1759     exp = -1.5;
1760     tol = 1e-12;
1761     
1762     maxit = 50;
1763     
1764     if (equilparam.zZi[0] > 0) {
1765         
1766         /* Equilibrium interpolation at ray location */
1767         if (flag == 0) {
1768             interpequil(rayparam,raymagnetic,rayprofiles,equilparam,fluctparam,Y0,Y,rayequil,rayfluctuations,flag_fluct,1);
1769         } else {
1770             interpequil_test(raymagnetic,rayprofiles,equilparam,Y,flag);
1771         }
1772         
1773         krho0 = Y[3];
1774         krho1 = frac*krho0;
1775         
1776         rayindex(&Nperp,dNperpdY,&N2,dN2dY,1,Y,raymagnetic,equilparam,&Npar,dNpardY,&eikval);
1777         if (mode > 0) {/* plasma case */
1778             susceptibility(X,Nperp,dNperpdY,wcn,wpn2,betath,rayparam.tensortype[0],(int)rayparam.ncyclharm[0],equilparam,raymagnetic,rayprofiles,Npar,dNpardY,Y[6]);
1779         }
1780         disprel(dDtotdY,&cD0,X,dNperpdY,Nperp,dN2dY,N2,dNpardY,Npar,2);
1781         D0 = creal(cD0);/* to be changed if non-hermitian susceptibility tensors are used */
1782         /* mexPrintf("krho0,D0:%g,%g\n",krho0,D0); */
1783         
1784         Y[3] = krho1;
1785         rayindex(&Nperp,dNperpdY,&N2,dN2dY,1,Y,raymagnetic,equilparam,&Npar,dNpardY,&eikval);
1786         if (mode > 0) {/* plasma case */
1787             susceptibility(X,Nperp,dNperpdY,wcn,wpn2,betath,rayparam.tensortype[0],(int)rayparam.ncyclharm[0],equilparam,raymagnetic,rayprofiles,Npar,dNpardY,Y[6]);
1788         }
1789         disprel(dDtotdY,&cD1,X,dNperpdY,Nperp,dN2dY,N2,dN2dY,Npar,2);
1790         D1 = creal(cD1);/* to be changed if non-hermitian susceptibility tensors are used */
1791         /* mexPrintf("krho1,D1:%g,%g\n",krho1,D1); */
1792         
1793         /* Search for root bounding interval */
1794         
1795         while ((D1*D0 > 0) && (fracmax < 100)) {
1796             
1797             frac = pow(frac,exp);
1798             krho1 = frac*krho0;
1799             
1800             Y[3] = krho1;
1801             rayindex(&Nperp,dNperpdY,&N2,dN2dY,1,Y,raymagnetic,equilparam,&Npar,dNpardY,&eikval);
1802             if (mode > 0) {/* plasma case */
1803                 susceptibility(X,Nperp,dNperpdY,wcn,wpn2,betath,rayparam.tensortype[0],(int)rayparam.ncyclharm[0],equilparam,raymagnetic,rayprofiles,Npar,dNpardY,Y[6]);
1804             }
1805             disprel(dDtotdY,&cD1,X,dNperpdY,Nperp,dN2dY,N2,dNpardY,Npar,2);
1806             D1 = creal(cD1);/* to be changed if non-hermitian susceptibility tensors are used */
1807             /*mexPrintf("krho1,D1:%g,%g\n",krho1,D1);*/
1808         }
1809         
1810         if (D1*D0 > 0) {
1811             krho[0] = krho0;  /* put error message */
1812         }
1813         /*    else if (fabs(D0) < tol){
1814          krho[0] = krho0;
1815          }
1816          else if (fabs(D1) < tol){
1817          krho[0] = krho1;
1818          }
1819          */
1820         else {
1821             if (fabs(D0) < fabs(D1)) { /*Closest root is set to latest value. */
1822                 krho2 = krho0;
1823                 krho0 = krho1;
1824                 krho1 = krho2;
1825                 D2 = D0;
1826                 D0 = D1;
1827                 D1 = D2;
1828             }
1829             
1830             j = 0;
1831             
1832             /*        mexPrintf("fabs(D1),tol,j,maxit:%g,%g,%d,%d\n",fabs(D1),tol,j,maxit); */
1833             
1834             while ((fabs(D1) > tol) && (j < maxit)) { /*Secant loop. */
1835                 
1836                 /*          mexPrintf("krho0,D0,krho1,D1,frac,tol:%g,%g,%g,%g,%g,%g\n",krho0,D0,krho1,D1,frac,tol); */
1837                 
1838                 dkrho = (krho0 - krho1)*D1/(D1-D0); /*Increment with respect to latest value. */
1839                 krho0 = krho1;
1840                 D0 = D1;
1841                 krho1 += dkrho;
1842                 
1843                 Y[3] = krho1;
1844                 rayindex(&Nperp,dNperpdY,&N2,dN2dY,1,Y,raymagnetic,equilparam,&Npar,dNpardY,&eikval);
1845                 if (mode > 0) {/* plasma case */
1846                     susceptibility(X,Nperp,dNperpdY,wcn,wpn2,betath,rayparam.tensortype[0],(int)rayparam.ncyclharm[0],equilparam,raymagnetic,rayprofiles,Npar,dNpardY,Y[6]);
1847                 }
1848                 disprel(dDtotdY,&cD1,X,dNperpdY,Nperp,dN2dY,N2,dNpardY,Npar,2);
1849                 D1 = creal(cD1);/* to be changed if non-hermitian susceptibility tensor are used */
1850                 /*          mexPrintf("krho1,D1:%g,%g\n",krho1,D1); */
1851             }
1852             
1853             if (fabs(D1) <= tol) { /*Convergence. */
1854                 krho[0] = krho1;
1855             }
1856             else {
1857                 krho[0] = krho2; /* put error message */
1858             }
1859         }
1860         
1861         
1862         /* krho[0] = -Y[3];*/ /* old method not accurate */
1863     } else {
1864         krho[0] = Y[3];
1865     }
1866     
1867 }
1868 
1869 
1870 void disprel(dDtotdY,Dtot,X,dNperpdY,Nperp,dN2dY,N2,dNpardY,Npar,flag)/*Doesn't have to be modified under a change of metric*/
1871 double complex dDtotdY[],*Dtot;
1872 susceptibilitytensor_format X;
1873 double complex dNperpdY[],Nperp,dN2dY[],N2;
1874 double dNpardY[],Npar;
1875 int flag;
1876 {
1877     double complex D[43],dDdY[43][MC],N6,dN6m1;
1878     
1879     double complex Nperp4,Nperp3,Nperp2,Nperp1;
1880     double Npar4,Npar3,Npar2,Npar1;
1881     double complex Xxx,Xxy,Xxz,Xyy,Xyz,Xzz;
1882     double complex Xxx2,Xxy2,Xxz2,Xyy2,Xyz2,Xzz2;
1883     
1884     int i,j;
1885     
1886     Nperp1 = Nperp;
1887     Nperp2 = Nperp1*Nperp1;
1888     Nperp3 = Nperp1*Nperp1*Nperp1;
1889     Nperp4 = Nperp1*Nperp1*Nperp1*Nperp1;
1890     Npar1 = Npar;
1891     Npar2 = Npar1*Npar1;
1892     Npar3 = Npar1*Npar1*Npar1;
1893     Npar4 = Npar1*Npar1*Npar1*Npar1;
1894     
1895     N6 = N2*N2*N2;
1896     
1897     
1898     /* mexPrintf("N2,dN2dY[i],%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g,%5.100g\n",N2,dN2dY[0],dN2dY[1],dN2dY[2],dN2dY[3],dN2dY[4],dN2dY[5],dN2dY[6],dN2dY[7]); */
1899     
1900     
1901     Xxx = X.Xxx[0];
1902     Xxy = X.Xxy[0];
1903     Xxz = X.Xxz[0];
1904     Xyy = X.Xyy[0];
1905     Xyz = X.Xyz[0];
1906     Xzz = X.Xzz[0];
1907     Xxx2 = X.Xxx[0]*X.Xxx[0];
1908     Xxy2 = X.Xxy[0]*X.Xxy[0];
1909     Xxz2 = X.Xxz[0]*X.Xxz[0];
1910     Xyy2 = X.Xyy[0]*X.Xyy[0];
1911     Xyz2 = X.Xyz[0]*X.Xyz[0];
1912     Xzz2 = X.Xzz[0]*X.Xzz[0];
1913     
1914     /*
1915      mexPrintf("Nperp4r,Nperp4i:%g,%g\n",creal(Nperp4),cimag(Nperp4));
1916      mexPrintf("Npar:%g\n",Npar1);
1917      mexPrintf("Nperpr,Nperpi:%g,%g\n",creal(Nperp1),cimag(Nperp1));
1918      mexPrintf("Xxxr,XXxxi:%g,%g\n",creal(Xxx),cimag(Xxx));
1919      mexPrintf("Xxyr,XXxyi:%g,%g\n",creal(Xxy),cimag(Xxy));
1920      mexPrintf("Xxzr,XXxzi:%g,%g\n",creal(Xxz),cimag(Xxz));
1921      mexPrintf("Xyyr,XXyyi:%g,%g\n",creal(Xyy),cimag(Xyy));
1922      mexPrintf("Xyzr,XXyzi:%g,%g\n",creal(Xyz),cimag(Xyz));
1923      mexPrintf("Xzzr,XXzzi:%g,%g\n",creal(Xzz),cimag(Xzz));
1924      
1925      double complex Dtot1;
1926      Dtot1 = (Xxx+1)*Nperp4/N6+2*Npar1*Xxz*Nperp3/N6-(-2*Npar2+Xyy-Npar2*Xzz+Xxy2+Xzz-Xxz2+Xxx*Xzz+Xxx*Xyy+2+2*Xxx-Xxx*Npar2)*Nperp2/N6-(2*Npar1*Xxz+2*Npar1*Xyy*Xxz-2*Xxy*Xyz*Npar-2*Npar3*Xxz)*Nperp1/N6-(-1-Xxx*Xyz2-Xxy2*Xzz+Xyy*Xxz2-2*Xxy*Xyz*Xxz-Xxx*Xyy*Xzz-Xzz+2*Npar2-Xyy-Xyz2-Npar4-Xxx-Xxy2+Xxz2+2*Npar2*Xzz-Xyy*Xzz+Npar2*Xyy-Xxx*Xzz+Xxx*Npar2-Xxx*Xyy-Npar4*Xzz+Npar2*Xyz2-Npar2*Xxz2+Npar2*Xyy*Xzz+Xxx*Npar2*Xzz)/N6;
1927      mexPrintf("Dtot1:%g\n",Dtot1);
1928      */
1929     if ((flag == 1) || (flag == 3)) {
1930         
1931         for (i = 0;ifor (i = 0;ifor (i = 0;i<43;i++) {
1985             for (j=0;jif ((flag == 2) || (flag == 3)) {
1992         
1993         D[0] = Nperp4/N6;
1994         D[1] = Xxx*Nperp4/N6;
1995         D[2] = 2.0*Npar1*Xxz*Nperp3/N6;
1996         D[3] = Npar2*Xxx*Nperp2/N6;
1997         D[4] = Npar2*Xzz*Nperp2/N6;
1998         D[5] = 2.0*Npar2*Nperp2/N6;
1999         D[6] = -2.0*Xxx*Nperp2/N6;
2000         D[7] = -Xyy*Nperp2/N6;
2001         D[8] = -Xzz*Nperp2/N6;
2002         D[9] = -Xxx*Xzz*Nperp2/N6;
2003         D[10] = Xxz2*Nperp2/N6;
2004         D[11] = -Xxx*Xyy*Nperp2/N6;
2005         D[12] = -Xxy2*Nperp2/N6;
2006         D[13] = -2.0*Nperp2/N6;
2007         D[14] = -2.0*Npar1*Xyy*Xxz*Nperp1/N6;
2008         D[15] = 2.0*Npar1*Xxy*Xyz*Nperp1/N6;
2009         D[16] = -2.0*Npar1*Xxz*Nperp1/N6;
2010         D[17] = 2.0*Npar3*Xxz*Nperp1/N6;
2011         D[18] = 1/N6;
2012         D[19] = Npar4*Xzz/N6;
2013         D[20] = Npar4/N6;
2014         D[21] = Npar2*Xxz2/N6;
2015         D[22] = -Npar2*Xyy*Xzz/N6;
2016         D[23] = -Npar2*Xxx*Xzz/N6;
2017         D[24] = -2.0*Npar2*Xzz/N6;
2018         D[25] = -Npar2*Xyy/N6;
2019         D[26] = -Npar2*Xyz2/N6;
2020         D[27] = -Npar2*Xxx/N6;
2021         D[28] = -2.0*Npar2/N6;
2022         D[29] = Xyy*Xzz/N6;
2023         D[30] = Xxx*Xzz/N6;
2024         D[31] = Xxx*Xyy/N6;
2025         D[32] = Xxx*Xyz2/N6;
2026         D[33] = Xyz2/N6;
2027         D[34] = Xxx/N6;
2028         D[35] = Xxy2/N6;
2029         D[36] = Xxy2*Xzz/N6;
2030         D[37] = -Xxz2/N6;
2031         D[38] = -Xyy*Xxz2/N6;
2032         D[39] = Xyy/N6;
2033         D[40] = Xzz/N6;
2034         D[41] = Xxx*Xyy*Xzz/N6;
2035         D[42] = 2.0*Xxy*Xyz*Xxz/N6;
2036         
2037         /*     for (i = 0;i<43;i++) {
2038          mexPrintf("i,Dr,Di:%d,%g\n",i,creal(D[i]),cimag(D[i]));
2039          }*/
2040         
2041         Dtot[0] = 0.0;
2042         for (i = 0;i<43;i++) {
2043             Dtot[0] = Dtot[0] + D[i];
2044         }
2045         
2046         /* mexPrintf("Dtot:%g\n",Dtot[0]);*/
2047     }
2048     
2049 }
2050 
2051 void susceptibility(X,Nperp,dNperpdY,wcn,wpn2,betath,tensortype,ncyclharm,equilparam,raymagnetic,rayprofiles,Npar,dNpardY,omega)/*Doesn't have to be modified under a change of metric*/
2052 susceptibilitytensor_format X;
2053 double complex Nperp,dNperpdY[];
2054 double wcn[],wpn2[],betath[];
2055 double tensortype,omega;
2056 int ncyclharm;
2057 double Npar,dNpardY[];
2058 
2059 raymagnetic_format raymagnetic;
2060 rayprofiles_format rayprofiles;
2061 equilparam_format equilparam;
2062 {
2063     double qe = 1.602176462e-19;/*Absolute value of the electron charge (C) */
2064     double me = 9.10938188e-31;/*Electron rest mass (Kg) */
2065     double mp = 1.67262158e-27;/*Proton rest mass (Kg) */
2066     double epsi0 = 8.854187818e-12;/*Free space permittivity (F/m) */
2067     double mu0 = 12.566370614e-7;/*Free space permeability (F/m) */
2068     double mc2 = 510.998902;/*Electron energy rest mass (keV) */
2069     
2070     double dwcndY[equilparam.ns[0]+1][MC],dwpn2dY[equilparam.ns[0]+1][MC],dbetathdY[equilparam.ns[0]+1][MC];
2071     
2072     int i,j,is;
2073     
2074     
2075     if (equilparam.zZi[0] > 0) {
2076         
2077         for (i = 0;i < equilparam.ns[0] + 1; i++) {/*initialisation */
2078             wcn[i] = 0.0;
2079             wpn2[i] = 0.0;
2080             betath[i] = 0.0;
2081             for (j=0;j/* Normalized parameters */
2089         
2090         wcn[0] = -qe*raymagnetic.B[0]/me/omega;/*electrons */
2091         dwcndY[0][0] = -qe*raymagnetic.dBdY[0]/me/omega;
2092         dwcndY[0][1] = -qe*raymagnetic.dBdY[1]/me/omega;
2093         dwcndY[0][2] = -qe*raymagnetic.dBdY[2]/me/omega;
2094         dwcndY[0][6] = -wcn[0];
2095         
2096         wpn2[0] = qe*qe*rayprofiles.ne[0]/epsi0/me/omega/omega;/*electrons */
2097         dwpn2dY[0][0] = qe*qe*rayprofiles.dnedY[0]/epsi0/me/omega/omega;
2098         dwpn2dY[0][1] = qe*qe*rayprofiles.dnedY[1]/epsi0/me/omega/omega;
2099         dwpn2dY[0][2] = qe*qe*rayprofiles.dnedY[2]/epsi0/me/omega/omega;
2100         dwpn2dY[0][6] = -2.0*wpn2[0];
2101         
2102         betath[0] = sqrt(rayprofiles.Te[0]/mc2);
2103         dbetathdY[0][0] = rayprofiles.dTedY[0]/betath[0]/2.0;
2104         dbetathdY[0][1] = rayprofiles.dTedY[1]/betath[0]/2.0;
2105         dbetathdY[0][2] = rayprofiles.dTedY[2]/betath[0]/2.0;
2106         
2107         for (is = 1;is < equilparam.ns[0]+1; is++) {
2108             if (rayprofiles.zni[is-1] > 0.0) {/* only when ion density is positive */
2109                 wcn[is] = qe*equilparam.zZi[is-1]*raymagnetic.B[0]/equilparam.zmi[is-1]/mp/omega;/*ions */
2110                 dwcndY[is][0] = qe*equilparam.zZi[is-1]*raymagnetic.dBdY[0]/equilparam.zmi[is-1]/mp/omega;
2111                 dwcndY[is][1] = qe*equilparam.zZi[is-1]*raymagnetic.dBdY[1]/equilparam.zmi[is-1]/mp/omega;
2112                 dwcndY[is][2] = qe*equilparam.zZi[is-1]*raymagnetic.dBdY[2]/equilparam.zmi[is-1]/mp/omega;
2113                 dwcndY[is][6] = -wcn[is];
2114                 
2115                 wpn2[is] = qe*equilparam.zZi[is-1]*qe*equilparam.zZi[is-1]*rayprofiles.zni[is-1]/epsi0/equilparam.zmi[is-1]/mp/omega/omega;/*ions */
2116                 dwpn2dY[is][0] = qe*equilparam.zZi[is-1]*qe*equilparam.zZi[is-1]*rayprofiles.dznidY[is-1][0]/epsi0/equilparam.zmi[is-1]/mp/omega/omega;
2117                 dwpn2dY[is][1] = qe*equilparam.zZi[is-1]*qe*equilparam.zZi[is-1]*rayprofiles.dznidY[is-1][1]/epsi0/equilparam.zmi[is-1]/mp/omega/omega;
2118                 dwpn2dY[is][2] = qe*equilparam.zZi[is-1]*qe*equilparam.zZi[is-1]*rayprofiles.dznidY[is-1][2]/epsi0/equilparam.zmi[is-1]/mp/omega/omega;
2119                 dwpn2dY[is][6] = -2.0*wpn2[is];
2120                 
2121                 betath[is] = sqrt(rayprofiles.zTi[is-1]*me/equilparam.zmi[is-1]/mp/mc2);
2122                 dbetathdY[is][0] = rayprofiles.dzTidY[is-1][0]/betath[is]/2.0;
2123                 dbetathdY[is][1] = rayprofiles.dzTidY[is-1][1]/betath[is]/2.0;
2124                 dbetathdY[is][2] = rayprofiles.dzTidY[is-1][2]/betath[is]/2.0;
2125             }
2126         }
2127         
2128         if (tensortype == 0) {
2129             /*        mexPrintf("Cold dielectric tensor\n"); */
2130             coldtensor(X,Nperp,dNperpdY,equilparam.ns[0],ncyclharm,raymagnetic,Npar,dNpardY,wcn,dwcndY,wpn2,dwpn2dY,betath,dbetathdY);
2131         }
2132         if (tensortype == 1) {
2133             /*        mexPrintf("Warm dielectric tensor\n");
2134              warmtensor(X,Nperp,dNperpdY,equilparam.ns[0],ncyclharm,raymagnetic,Npar,dNpardY,wcn,dwcndY,wpn2,dwpn2dY,betath,dbetathdY); */
2135         }
2136         if (tensortype == 2) {
2137             /*        mexPrintf("Hot dielectric tensor\n");*/
2138             hottensor(X,Nperp,dNperpdY,equilparam.ns[0],ncyclharm,raymagnetic,Npar,dNpardY,wcn,dwcndY,wpn2,dwpn2dY,betath,dbetathdY);
2139         }
2140         if (tensortype == 3) {
2141             /*        mexPrintf("Weak relativistic dielectric tensor\n");*/
2142             weakrelativistictensor(X,Nperp,dNperpdY,equilparam.ns[0],ncyclharm,raymagnetic,Npar,dNpardY,wcn,dwcndY,wpn2,dwpn2dY,betath,dbetathdY);
2143         }
2144         if (tensortype == 4) {
2145             /*        mexPrintf("Full relativistic dielectric tensor\n");
2146              fullrelativistictensor(X,Nperp,dNperpdY,equilparam.ns[0],ncyclharm,raymagnetic,Npar,dNpardY,wcn,dwcndY,wpn2,dwpn2dY,betath,dbetathdY); */
2147         }
2148         
2149     } else {
2150         vacuumtensor(X);
2151     }
2152 }
2153 
2154 
2155 void rayindex(Nperp,dNperpdY,N2,dN2dY,flag_metric,Y,raymagnetic,equilparam,Npar,dNpardY,eikval)/*Has to be modified under a change of metric*/
2156 double complex *Nperp,*dNperpdY;
2157 double complex *N2,*dN2dY;
2158 int flag_metric;
2159 double Y[];
2160 double *Npar,*dNpardY;
2161 raymagnetic_format raymagnetic;
2162 equilparam_format equilparam;
2163 double complex *eikval;
2164 {
2165     double dYdY[MC][MC];
2166     
2167     double Npar0,dNpar0dY,dNpar0dY1,dNpar0dY2,dNpar0dY3,dNpar0dY4,dNpar0dY5,dNpar0dY6;
2168     double Npar1,dNpar1dY,dNpar1dY1,dNpar1dY2,dNpar1dY3,dNpar1dY4,dNpar1dY5,dNpar1dY6;
2169     double Npar2,dNpar2dY,dNpar2dY1,dNpar2dY2,dNpar2dY3,dNpar2dY4,dNpar2dY5;
2170     double calpha_theta,salpha_theta,dcalpha_thetadx,dcalpha_thetady,dsalpha_thetadx,dsalpha_thetady;
2171     
2172     double complex N21,dN21dY,dN21dY1,dN21dY2,dN21dY3;
2173     double complex N22,dN22dY,dN22dY1,dN22dY2,dN22dY3,dN22dY4,dN22dY5,dN22dY6;
2174     double complex N23,dN23dY,dN23dY1,dN23dY2,dN23dY3;
2175     double complex N24,dN24dY,dN24dY1,dN24dY2,dN24dY3;
2176     
2177     
2178     double complex divN11,divN12,divN13,divN14,divN15;
2179     double complex divN21,divN22,divN23,divN24,divN25;
2180     double complex divN31,divN32;
2181     double complex divN1,divN2,divN3;
2182     
2183     double ap,cnorm;
2184     double theta;
2185     
2186     register int i,j;
2187     
2188     /*Covariant matrix */
2189     
2190     for (i=0;ifor (j=0;jif ((i==j) && (i<7)) {
2193                 dYdY[i][j] = 1.0;
2194             } else {
2195                 dYdY[i][j] = 0.0;
2196             }
2197         }
2198     }
2199     
2200     
2201     for (i=0;i/*initialisation */
2202         dNpardY[i] = 0.0;
2203         dNperpdY[i] = 0.0;
2204         dN2dY[i] = 0.0;
2205     }
2206     
2207     ap = equilparam.ap[0];
2208     cnorm = CLUM/ap/Y[6];
2209     
2210     /*  mexPrintf("clum_norm,ap,CLUM,Y[6]:%g,%g,%g,%g\n",cnorm,ap,CLUM,Y[6]); */
2211     
2212     /* Definition of the rayindex and its derivatives in flux coordinates */
2213     
2214     if (flag_metric == 1)
2215     {
2216         
2217         Npar0 = Y[3]*raymagnetic.gradrhon[0]*raymagnetic.Brhon[0];
2218         Npar1 = Y[4]*(raymagnetic.calpha[0]*raymagnetic.Bsn[0] - raymagnetic.salpha[0]*raymagnetic.Brhon[0])/raymagnetic.rn[0];
2219         Npar2 = Y[5]*raymagnetic.Bzn[0]/raymagnetic.Upsilonn[0];
2220         Npar[0] = cnorm*(Npar0 + Npar1 + Npar2);
2221         /*  mexPrintf("Npar0,Npar1,Npar2:%g,%g,%g\n",Npar0,Npar1,Npar2); */
2222         /*  mexPrintf("Nparth:%g\n",Npar[0]); */
2223         /*  mexPrintf("Y[0],Y[1],Y[2],Y[3],Y[4],Y[5]:%g,%g,%g,%g,%g,%g\n",Y[0],Y[1],Y[2],Y[3],Y[4],Y[5]); */
2224         /*  mexPrintf("Y[4],raymagnetic.calpha[0],raymagnetic.Brhon[0],raymagnetic.Bsn[0],raymagnetic.rn[0],Y[5],raymagnetic.Bzn[0],raymagnetic.xn[0]:%g,%g,%g,%g,%g,%g,%g\n",Y[4],raymagnetic.calpha[0],raymagnetic.Brhon[0],raymagnetic.Bsn[0],raymagnetic.rn[0],Y[5],raymagnetic.Bzn[0],raymagnetic.xn[0]); */
2225         
2226         
2227         for (i=0;i/*mexPrintf("i,dNpardY[i]:%d,%g\n",i,dNpardY[i]);*/
2256             /*mexPrintf("i,dYdY[3][i],dYdY[4][i],dYdY[5][i]:%d,%g,%g,%g\n",i,dYdY[3][i],dYdY[4][i],dYdY[4][i]);*/
2257         }
2258         N21 = raymagnetic.gradrhon[0]*raymagnetic.gradrhon[0]*Y[3]*Y[3];
2259         N22 = -2.0*raymagnetic.gradrhon[0]*raymagnetic.salpha[0]*Y[4]*Y[3]/raymagnetic.rn[0];
2260         N23 = Y[4]*Y[4]/raymagnetic.rn[0]/raymagnetic.rn[0];
2261         N24 = Y[5]*Y[5]/raymagnetic.Upsilonn[0]/raymagnetic.Upsilonn[0];
2262         
2263         N2[0] = cnorm*cnorm*(N21 + N22 + N23 + N24);
2264         Nperp[0] = sqrt(N2[0] - Npar[0]*Npar[0]);
2265         
2266         /*mexPrintf("Npar,Nperp,N2:%g,%g,%g,%g,%g\n",Npar[0],Nperp[0],N2[0]);*/
2267         
2268         for (i=0;i/*      mexPrintf("Y[]:%g,%g,%g,%g,%g,%g,%g\n",Y[0],Y[1],Y[2],Y[3],Y[4],Y[5]);
2305          mexPrintf("r,2*r*drdY[]:%g,%g,%g,%g,%g,%g,%g,%g,%g\n",raymagnetic.rn[0],2.0*raymagnetic.rn[0]*raymagnetic.drndY[0],2.0*raymagnetic.rn[0]*raymagnetic.drndY[1],2.0*raymagnetic.rn[0]*raymagnetic.drndY[2],2.0*raymagnetic.rn[0]*raymagnetic.drndY[3],2.0*raymagnetic.rn[0]*raymagnetic.drndY[4],2.0*raymagnetic.rn[0]*raymagnetic.drndY[5],2.0*raymagnetic.rn[0]*raymagnetic.drndY[6],2.0*raymagnetic.rn[0]*raymagnetic.drndY[7],2.0*raymagnetic.rn[0]*raymagnetic.drndY[8]);
2306          mexPrintf("dN2dY[]:%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g\n",dN2dY[0],dN2dY[1],dN2dY[2],dN2dY[3],dN2dY[4],dN2dY[5],dN2dY[6],dN2dY[7]);
2307          */
2308         
2309         divN11 = raymagnetic.dUpsilonndY[0]*raymagnetic.rn[0]*raymagnetic.gradrhon[0]*Y[3]/raymagnetic.calpha[0];
2310         divN12 = raymagnetic.Upsilonn[0]*raymagnetic.drndY[0]*raymagnetic.gradrhon[0]*Y[3]/raymagnetic.calpha[0];
2311         divN13 = raymagnetic.Upsilonn[0]*raymagnetic.rn[0]*raymagnetic.dgradrhondY[0]*Y[3]/raymagnetic.calpha[0];
2312         divN14 = raymagnetic.Upsilonn[0]*raymagnetic.rn[0]*raymagnetic.gradrhon[0]*dYdY[3][0]/raymagnetic.calpha[0];
2313         divN15 = -raymagnetic.Upsilonn[0]*raymagnetic.rn[0]*raymagnetic.gradrhon[0]*Y[3]*raymagnetic.dcalphadY[0]/raymagnetic.calpha[0]/raymagnetic.calpha[0];
2314         
2315         divN21 = dYdY[4][1]/raymagnetic.rn[0]/raymagnetic.calpha[0]/raymagnetic.Bsn[0]/raymagnetic.B[0];
2316         divN22 = -Y[4]*raymagnetic.drndY[1]/raymagnetic.rn[0]/raymagnetic.rn[0]/raymagnetic.calpha[0]/raymagnetic.Bsn[0]/raymagnetic.B[0];
2317         divN23 = -Y[4]*raymagnetic.dcalphadY[1]/raymagnetic.rn[0]/raymagnetic.calpha[0]/raymagnetic.calpha[0]/raymagnetic.Bsn[0]/raymagnetic.B[0];
2318         divN24 = -Y[4]*raymagnetic.dBsndY[1]/raymagnetic.rn[0]/raymagnetic.calpha[0]/raymagnetic.Bsn[0]/raymagnetic.Bsn[0]/raymagnetic.B[0];
2319         divN25 = -Y[4]*raymagnetic.dBdY[1]/raymagnetic.rn[0]/raymagnetic.calpha[0]/raymagnetic.Bsn[0]/raymagnetic.B[0]/raymagnetic.B[0];
2320         
2321         divN31 = dYdY[5][2]/raymagnetic.Upsilonn[0];
2322         divN32 = -Y[5]*raymagnetic.dUpsilonndY[2]/raymagnetic.Upsilonn[0]/raymagnetic.Upsilonn[0];
2323         
2324         divN1 = (divN11 + divN12 + divN13 + divN14 + divN15)*raymagnetic.gradrhon[0]*raymagnetic.calpha[0]/raymagnetic.Upsilonn[0]/raymagnetic.rn[0];
2325         divN2 = (divN21 + divN22 + divN23 + divN24 + divN25)*raymagnetic.Bsn[0]*raymagnetic.B[0]*raymagnetic.calpha[0]/raymagnetic.rn[0];
2326         divN3 = (divN31 + divN32)/raymagnetic.Upsilonn[0];
2327         
2328         eikval[0] = cnorm*cabs(divN1 + divN2 + divN3)/N2[0];
2329         
2330     }
2331     else/*Cartesian ray index declaration, 06/06/16 update*/
2332     /* In this section the array Y stands for Y=[x,y,phi,kx,kz,n,omega/c]*/
2333     {
2334         
2335         /* Declaration of cos(alpha-theta), sin(alpha-theta) */
2336         
2337         theta = atan2(Y[1],Y[0]);
2338         
2339         calpha_theta = raymagnetic.calpha[0]*cos(theta) + raymagnetic.salpha[0]*sin(theta);
2340         
2341         salpha_theta = raymagnetic.salpha[0]*cos(theta) - raymagnetic.calpha[0]*sin(theta);
2342         
2343         
2344         /* Declaration of the cartesian derivatives of cos(alpha-theta), sin(alpha-theta) */
2345         
2346         
2347         dcalpha_thetadx = cos(theta)*(raymagnetic.dcalphadY[0] - raymagnetic.salpha[0]*sin(theta)/raymagnetic.rn[0]) + sin(theta)*(raymagnetic.dsalphadY[0] + raymagnetic.calpha[0]*sin(theta)/raymagnetic.rn[0]);
2348         
2349         dcalpha_thetady = cos(theta)*(raymagnetic.dcalphadY[1] + raymagnetic.salpha[0]*cos(theta)/raymagnetic.rn[0]) + sin(theta)*(raymagnetic.dsalphadY[1] - raymagnetic.calpha[0]*cos(theta)/raymagnetic.rn[0]);
2350         
2351         dsalpha_thetadx = cos(theta)*(raymagnetic.dsalphadY[0] + raymagnetic.calpha[0]*sin(theta)/raymagnetic.rn[0]) - sin(theta)*(raymagnetic.dcalphadY[0] - raymagnetic.salpha[0]*sin(theta)/raymagnetic.rn[0]);
2352         
2353         dsalpha_thetady = cos(theta)*(raymagnetic.dsalphadY[1] - raymagnetic.calpha[0]*cos(theta)/raymagnetic.rn[0]) - sin(theta)*(raymagnetic.dcalphadY[1] + raymagnetic.salpha[0]*cos(theta)/raymagnetic.rn[0]);
2354         
2355         double dsalpha_thetadY[MC];
2356         double dcalpha_thetadY[MC];
2357         
2358         for(i=0;iif(i==0)
2361             {
2362                 dsalpha_thetadY[i] = dsalpha_thetadx;
2363                 dcalpha_thetadY[i] = dcalpha_thetadx;
2364             }
2365             else
2366             {
2367                 if(i==1)
2368                 {
2369                     dsalpha_thetadY[i] = dsalpha_thetady;
2370                     dcalpha_thetadY[i] = dcalpha_thetady;
2371                 }
2372                 else
2373                 {
2374                     dsalpha_thetadY[i] = 0;
2375                     dcalpha_thetadY[i] = 0;
2376                 }
2377             }
2378         }
2379         
2380         /* Declaration of the parallel ray index */
2381         
2382         
2383         Npar0 = Y[3]*(raymagnetic.Bsn[0]*salpha_theta + calpha_theta*raymagnetic.Brhon[0]);
2384         Npar1 = Y[4]*(raymagnetic.Bsn[0]*calpha_theta - salpha_theta*raymagnetic.Brhon[0]);
2385         Npar2 = Y[5]*raymagnetic.Bzn[0]/raymagnetic.Upsilonn[0];
2386         
2387         Npar[0] = cnorm*(Npar0 + Npar1 + Npar2);
2388         
2389         /*Declaration of the parallel ray index first order derivatives*/
2390         
2391         for(i=0;i/* Declaration of the square rayindex and its derivatives */
2422         
2423         N2[0] = cnorm*cnorm*(pow(Y[3],2) + pow(Y[4],2) + pow(Y[5]/raymagnetic.Upsilonn[0],2));
2424         
2425         for(i=0;i/* Declaration of the perpendicular ray index and its first order derivatives */
2447         
2448         Nperp[0] = sqrt(N2[0]-pow(Npar[0],2));/*Perpendicular ray index*/
2449         
2450         for(i=0;i/* WKB approximation */
2456         
2457         eikval[0]=0.0;/*We will turn on this paramater later*/
2458     }
2459 }
2460 
2461 
2462 void buildXstruc(X,dNperpdY,Xxx,Xxy,Xxz,Xyy,Xyz,Xzz,dXxxdNperp,dXxydNperp,dXxzdNperp,dXyydNperp,dXyzdNperp,dXzzdNperp,dXxxdNpar,dXxydNpar,dXxzdNpar,dXyydNpar,dXyzdNpar,dXzzdNpar,dXxxdbetath,dXxydbetath,dXxzdbetath,dXyydbetath,dXyzdbetath,dXzzdbetath,dXxxdwcn,dXxydwcn,dXxzdwcn,dXyydwcn,dXyzdwcn,dXzzdwcn,dXxxdwpn2,dXxydwpn2,dXxzdwpn2,dXyydwpn2,dXyzdwpn2,dXzzdwpn2,ns,dNpardY,dwcndY,dwpn2dY,dbetathdY)/*Doesn't have to be modified under a change of metric*/
2463 susceptibilitytensor_format X;
2464 double complex dNperpdY[];
2465 double complex Xxx[],Xxy[],Xxz[],Xyy[],Xyz[],Xzz[];
2466 double complex dXxxdNperp[],dXxydNperp[],dXxzdNperp[],dXyydNperp[],dXyzdNperp[],dXzzdNperp[];
2467 double complex dXxxdNpar[],dXxydNpar[],dXxzdNpar[],dXyydNpar[],dXyzdNpar[],dXzzdNpar[];
2468 double complex dXxxdbetath[],dXxydbetath[],dXxzdbetath[],dXyydbetath[],dXyzdbetath[],dXzzdbetath[];
2469 double complex dXxxdwcn[],dXxydwcn[],dXxzdwcn[],dXyydwcn[],dXyzdwcn[],dXzzdwcn[];
2470 double complex dXxxdwpn2[],dXxydwpn2[],dXxzdwpn2[],dXyydwpn2[],dXyzdwpn2[],dXzzdwpn2[];
2471 int ns;
2472 double dwcndY[][MC],dwpn2dY[][MC],dbetathdY[][MC],dNpardY[];
2473 {
2474     
2475     int i,is;
2476     
2477     X.Xxx[0] = Xxx[0];
2478     X.Xxy[0] = Xxy[0];
2479     X.Xxz[0] = Xxz[0];
2480     X.Xyy[0] = Xyy[0];
2481     X.Xyz[0] = Xyz[0];
2482     X.Xzz[0] = Xzz[0];
2483     
2484     for (is = 1;is < ns + 1;is++) {
2485         X.Xxx[0] = X.Xxx[0] + Xxx[is];
2486         X.Xxy[0] = X.Xxy[0] + Xxy[is];
2487         X.Xxz[0] = X.Xxz[0] + Xxz[is];
2488         X.Xyy[0] = X.Xyy[0] + Xyy[is];
2489         X.Xyz[0] = X.Xyz[0] + Xyz[is];
2490         X.Xzz[0] = X.Xzz[0] + Xzz[is];
2491     }
2492     
2493     X.dXxxdNperp[0] = dXxxdNperp[0];
2494     X.dXxydNperp[0] = dXxydNperp[0];
2495     X.dXxzdNperp[0] = dXxzdNperp[0];
2496     X.dXyydNperp[0] = dXyydNperp[0];
2497     X.dXyzdNperp[0] = dXyzdNperp[0];
2498     X.dXzzdNperp[0] = dXzzdNperp[0];
2499     
2500     for (is = 1;is < ns + 1;is++) {
2501         X.dXxxdNperp[0] = X.dXxxdNperp[0] + dXxxdNperp[is];
2502         X.dXxydNperp[0] = X.dXxydNperp[0] + dXxydNperp[is];
2503         X.dXxzdNperp[0] = X.dXxzdNperp[0] + dXxzdNperp[is];
2504         X.dXyydNperp[0] = X.dXyydNperp[0] + dXyydNperp[is];
2505         X.dXyzdNperp[0] = X.dXyzdNperp[0] + dXyzdNperp[is];
2506         X.dXzzdNperp[0] = X.dXzzdNperp[0] + dXzzdNperp[is];
2507     }
2508     
2509     X.dXxxdNpar[0] = dXxxdNpar[0];
2510     X.dXxydNpar[0] = dXxydNpar[0];
2511     X.dXxzdNpar[0] = dXxzdNpar[0];
2512     X.dXyydNpar[0] = dXyydNpar[0];
2513     X.dXyzdNpar[0] = dXyzdNpar[0];
2514     X.dXzzdNpar[0] = dXzzdNpar[0];
2515     
2516     for (is = 1;is < ns + 1;is++) {
2517         X.dXxxdNpar[0] = X.dXxxdNpar[0] + dXxxdNpar[is];
2518         X.dXxydNpar[0] = X.dXxydNpar[0] + dXxydNpar[is];
2519         X.dXxzdNpar[0] = X.dXxzdNpar[0] + dXxzdNpar[is];
2520         X.dXyydNpar[0] = X.dXyydNpar[0] + dXyydNpar[is];
2521         X.dXyzdNpar[0] = X.dXyzdNpar[0] + dXyzdNpar[is];
2522         X.dXzzdNpar[0] = X.dXzzdNpar[0] + dXzzdNpar[is];
2523     }
2524     
2525     for (i = 0;i < MC;i++) {/* Initialisation */
2526         X.dXxxdY[i] = 0.0;
2527         X.dXxydY[i] = 0.0;
2528         X.dXxzdY[i] = 0.0;
2529         X.dXyydY[i] = 0.0;
2530         X.dXyzdY[i] = 0.0;
2531         X.dXzzdY[i] = 0.0;
2532     }
2533     
2534     
2535     for (i = 0;i < MC;i++) {
2536         for (is = 0;is < ns + 1;is++) {
2537             X.dXxxdY[i] = X.dXxxdY[i] + dXxxdNperp[is]*dNperpdY[i] + dXxxdNpar[is]*dNpardY[i] + dXxxdbetath[is]*dbetathdY[is][i] + dXxxdwcn[is]*dwcndY[is][i] + dXxxdwpn2[is]*dwpn2dY[is][i];
2538             X.dXxydY[i] = X.dXxydY[i] + dXxydNperp[is]*dNperpdY[i] + dXxydNpar[is]*dNpardY[i] + dXxydbetath[is]*dbetathdY[is][i] + dXxydwcn[is]*dwcndY[is][i] + dXxydwpn2[is]*dwpn2dY[is][i];
2539             X.dXxzdY[i] = X.dXxzdY[i] + dXxzdNperp[is]*dNperpdY[i] + dXxzdNpar[is]*dNpardY[i] + dXxzdbetath[is]*dbetathdY[is][i] + dXxzdwcn[is]*dwcndY[is][i] + dXxzdwpn2[is]*dwpn2dY[is][i];
2540             X.dXyydY[i] = X.dXyydY[i] + dXyydNperp[is]*dNperpdY[i] + dXyydNpar[is]*dNpardY[i] + dXyydbetath[is]*dbetathdY[is][i] + dXyydwcn[is]*dwcndY[is][i] + dXyydwpn2[is]*dwpn2dY[is][i];
2541             X.dXyzdY[i] = X.dXyzdY[i] + dXyzdNperp[is]*dNperpdY[i] + dXyzdNpar[is]*dNpardY[i] + dXyzdbetath[is]*dbetathdY[is][i] + dXyzdwcn[is]*dwcndY[is][i] + dXyzdwpn2[is]*dwpn2dY[is][i];
2542             X.dXzzdY[i] = X.dXzzdY[i] + dXzzdNperp[is]*dNperpdY[i] + dXzzdNpar[is]*dNpardY[i] + dXzzdbetath[is]*dbetathdY[is][i] + dXzzdwcn[is]*dwcndY[is][i] + dXzzdwpn2[is]*dwpn2dY[is][i];
2543         }
2544     }
2545     
2546     /*    for (i = 0;i < MC;i++) {
2547      mexPrintf("i,dbetathdY[1][i]:%d,%g\n",i,dbetathdY[1][i]);
2548      mexPrintf("i,dwcndY[1][i]:%d,%g\n",i,dwcndY[1][i]);
2549      mexPrintf("i,dwpn2dY[1][i]:%d,%g\n",i,dwpn2dY[1][i]);
2550      mexPrintf("i,dXxxdY,dXxydY,dXxzdY,dXyydY,dXyzdY,dXzzdY:%d,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g\n",i,X.dXxxdY[i],X.dXxydY[i],X.dXxzdY[i],X.dXyydY[i],X.dXyzdY[i],X.dXzzdY[i]);
2551      mexPrintf("i,dNpardY[i],dNperpdY[i]:%d,%g,%g\n",i,dNpardY[i],dNperpdY[i]);
2552      }
2553      */
2554     
2555 }
2556 
2557 
2558 
2559 
2560 
2561 void interpequil(rayparam,raymagnetic,rayprofiles,equilparam,fluctparam,Y0,Y,rayequil,rayfluctuations,flag_fluct,flag_metric)/*Has to be modified under a change of metric*/
2562 rayparam_format rayparam;
2563 raymagnetic_format raymagnetic;
2564 rayprofiles_format rayprofiles;
2565 equilparam_format equilparam;
2566 fluctparam_format fluctparam;
2567 double Y0[],Y[];
2568 rayequil_format rayequil;
2569 rayfluctuations_format rayfluctuations;
2570 int flag_fluct;
2571 int flag_metric;
2572 {
2573     /* interpolation from numerical equilibrium data*/
2574     
2575     double dTidY[equilparam.ns[0]],dnidY[equilparam.ns[0]];
2576     double d2TidY2[equilparam.ns[0]],d2nidY2[equilparam.ns[0]];
2577     double x,dxdrho,dxdtheta,d2xdtheta2,d2xdthetadrho,d2xdrho2;
2578     double y,dydrho,dydtheta,d2ydtheta2,d2ydthetadrho,d2ydrho2;
2579     double r=0,drdrho=0,drdtheta=0,d2rdtheta2=0,d2rdthetadrho=0,d2rdrho2=0;
2580     double calpha=0,dcalphadrho=0,dcalphadtheta=0,d2calphadtheta2=0,d2calphadthetadrho=0,d2calphadrho2=0;
2581     double salpha=0,dsalphadrho=0,dsalphadtheta=0,d2salphadtheta2=0,d2salphadthetadrho=0,d2salphadrho2=0;
2582     double gradrho=0,dgradrhodrho=0,dgradrhodtheta=0,d2gradrhodtheta2=0,d2gradrhodthetadrho=0,d2gradrhodrho2=0;
2583     double Bx=0,dBxdrho=0,dBxdtheta=0,d2Bxdtheta2=0,d2Bxdthetadrho=0,d2Bxdrho2=0,dBxdz=0;
2584     double By=0,dBydrho=0,dBydtheta=0,d2Bydtheta2=0,d2Bydthetadrho=0,d2Bydrho2=0,dBydz=0;
2585     double Bz=0,dBzdrho=0,dBzdtheta=0,d2Bzdtheta2=0,d2Bzdthetadrho=0,d2Bzdrho2=0,dBzdz=0;
2586     double BP=0,dBPdrho=0,dBPdtheta=0,d2BPdtheta2=0,d2BPdthetadrho=0,d2BPdrho2=0,dBPdz=0;
2587     double BB=0,dBBdrho=0,dBBdtheta=0,d2BBdtheta2=0,d2BBdthetadrho=0,d2BBdrho2=0,dBBdz=0;
2588     
2589     double icm,idcmdrho,cm,cn0,dcn0drho;
2590     
2591     double phaseB,dphaseBdrho,dphaseBdtheta,dphaseBdphi;
2592     double phasene,dphasenedrho,dphasenedtheta,dphasenedphi;
2593     
2594     double nefsne,dnefsnedrho,dnefsnedtheta,dnefsnedphi;
2595     double TefsTe,dTefsTedrho,dTefsTedtheta,dTefsTedphi;
2596     double znifszni[equilparam.ns[0]],dznifsznidrho[equilparam.ns[0]],dznifsznidtheta[equilparam.ns[0]],dznifsznidphi[equilparam.ns[0]];
2597     double zTifszTi[equilparam.ns[0]],dzTifszTidrho[equilparam.ns[0]],dzTifszTidtheta[equilparam.ns[0]],dzTifszTidphi[equilparam.ns[0]];
2598     
2599     double sfBx[fluctparam.B_nmodel[0]],dsfBxdrho[fluctparam.B_nmodel[0]],dsfBxdtheta[fluctparam.B_nmodel[0]],d2sfBxdtheta2[fluctparam.B_nmodel[0]],d2sfBxdthetadrho[fluctparam.B_nmodel[0]];
2600     double sfBy[fluctparam.B_nmodel[0]],dsfBydrho[fluctparam.B_nmodel[0]],dsfBydtheta[fluctparam.B_nmodel[0]],d2sfBydtheta2[fluctparam.B_nmodel[0]],d2sfBydthetadrho[fluctparam.B_nmodel[0]];
2601     double sfBz[fluctparam.B_nmodel[0]],dsfBzdrho[fluctparam.B_nmodel[0]],dsfBzdtheta[fluctparam.B_nmodel[0]],d2sfBzdtheta2[fluctparam.B_nmodel[0]],d2sfBzdthetadrho[fluctparam.B_nmodel[0]];
2602     double BxfsB,dBxfsBdrho,dBxfsBdtheta,dBxfsBdphi;
2603     double ByfsB,dByfsBdrho,dByfsBdtheta,dByfsBdphi;
2604     double BzfsB,dBzfsBdrho,dBzfsBdtheta,dBzfsBdphi;
2605     double BrhofsB,dBrhofsBdrho,dBrhofsBdtheta,dBrhofsBdphi;
2606     double BsfsB,dBsfsBdrho,dBsfsBdtheta,dBsfsBdphi;
2607     double BphifsB,dBphifsBdrho,dBphifsBdtheta,dBphifsBdphi;
2608     
2609     double cta,dctadrho,dctadtheta,dctadphi;
2610     double sta,dstadrho,dstadtheta,dstadphi;
2611     
2612     double Brho,Bs,Bphi,B;
2613     double Brhon,Bsn,Bphin;
2614     double dBrhodrho,dBrhodtheta,dBrhodphi;
2615     double dBsdrho,dBsdtheta,dBsdphi;
2616     double dBphidrho,dBphidtheta,dBphidphi;
2617     double dBdrho,dBdtheta,dBdphi;
2618     
2619     double Brho0,dBrho0drho,dBrho0dtheta;
2620     double lambda,dlambdadrho,dlambdadtheta;
2621     double rhorip,drhodrhorip,drhodthetarip,drhodphirip;
2622     
2623     double val,dvaldrho,d2valdrho2;
2624     double zval[equilparam.ns[0]],dzvaldrho[equilparam.ns[0]],d2zvaldrho2[equilparam.ns[0]];
2625     
2626     double ne_sep,dnedrho_sep;
2627     double rho_neeq0;
2628     double nerip,dnedrhorip,dnedthetarip,dnedphirip;
2629     double ne_tilde,dnedrho_tilde,dnedtheta_tilde,dnedphi_tilde;
2630     double ner_tilde,dnerdrho_tilde,dnerdtheta_tilde,dnerdphi_tilde;
2631     
2632     double Te_sep,dTedrho_sep;
2633     double rho_Teeq0;
2634     double Terip,dTedrhorip,dTedthetarip,dTedphirip;
2635     double Te_tilde,dTedrho_tilde,dTedtheta_tilde,dTedphi_tilde;
2636     double Ter_tilde,dTerdrho_tilde,dTerdtheta_tilde,dTerdphi_tilde;
2637     
2638     double zni_sep[equilparam.ns[0]],dznidrho_sep[equilparam.ns[0]];
2639     double rho_znieq0[equilparam.ns[0]];
2640     double znirip[equilparam.ns[0]],dznidrhorip[equilparam.ns[0]],dznidthetarip[equilparam.ns[0]],dznidphirip[equilparam.ns[0]];
2641     double zni_tilde[equilparam.ns[0]],dznidrho_tilde[equilparam.ns[0]],dznidtheta_tilde[equilparam.ns[0]],dznidphi_tilde[equilparam.ns[0]];
2642     double znir_tilde[equilparam.ns[0]],dznirdrho_tilde[equilparam.ns[0]],dznirdtheta_tilde[equilparam.ns[0]],dznirdphi_tilde[equilparam.ns[0]];
2643     
2644     double zTi_sep[equilparam.ns[0]],dzTidrho_sep[equilparam.ns[0]];
2645     double rho_zTieq0[equilparam.ns[0]];
2646     double zTirip[equilparam.ns[0]],dzTidrhorip[equilparam.ns[0]],dzTidthetarip[equilparam.ns[0]],dzTidphirip[equilparam.ns[0]];
2647     double zTi_tilde[equilparam.ns[0]],dzTidrho_tilde[equilparam.ns[0]],dzTidtheta_tilde[equilparam.ns[0]],dzTidphi_tilde[equilparam.ns[0]];
2648     double zTir_tilde[equilparam.ns[0]],dzTirdrho_tilde[equilparam.ns[0]],dzTirdtheta_tilde[equilparam.ns[0]],dzTirdphi_tilde[equilparam.ns[0]];
2649     
2650     int il,im,in,iphase;
2651     
2652     double dl,dm;
2653     double phase,dphasedrho,dphasedtheta,dphasedphi;
2654     double Flambda,dFlambdadrho,dFlambdadtheta,dFlambdadphi;
2655     double Fdelta,dFdeltadrho,dFdeltadtheta,dFdeltadphi;
2656     
2657     double L_rho,dL_rhodrho,dL_rhodtheta,dL_rhodphi;
2658     double xq,dxqdrho,dxqdtheta,dxqdphi;
2659     double xL_theta,dxL_thetadrho,dxL_thetadtheta,dxL_thetadphi;
2660     double xL_perp,dxL_perpdrho,dxL_perpdtheta,dxL_perpdphi;
2661     double XL_phi,dXL_phidrho,dXL_phidtheta,dXL_phidphi;
2662     
2663     double ac,dacdrho,dacdtheta,dacdphi;
2664     double u_l,du_ldrho,du_ldtheta,du_ldphi,expu_l,dexpu_ldrho,dexpu_ldtheta,dexpu_ldphi;
2665     double u_m,du_mdrho,du_mdtheta,du_mdphi,expu_m,dexpu_mdrho,dexpu_mdtheta,dexpu_mdphi;
2666     double u_n,du_ndrho,du_ndtheta,du_ndphi,expu_n,dexpu_ndrho,dexpu_ndtheta,dexpu_ndphi;
2667     double almn,dalmndrho,dalmndtheta,dalmndphi;
2668     double alm,dalmdrho,dalmdtheta,dalmdphi;
2669     double am,damdrho,damdtheta,damdphi;
2670     double curtheta,dcurthetadrho,dcurthetadtheta,dcurthetadphi;
2671     
2672     double kperp,dkperpdrho,dkperpdtheta,dkperpdphi;
2673     
2674     double ht=0,dht=0,d2ht=0;
2675     double xx=0,dxxdrho=0,dxxdtheta=0,dxxdphi=0;
2676     
2677     double dummy,dummy1,dummy2,dummy3;
2678     
2679     int i,j,is,imodel;
2680     
2681     double save;
2682     double rho,theta,xbis,ybis;
2683     
2684     /*Axisymmetric magnetic field equilibrium interpolation*/
2685     
2686     if (flag_metric == 1)/*Curvilinear case*/
2687     {
2688         ppvald_2D(rayequil.x_fit,rayparam.dS[0],Y[0],Y[1],&x,&dxdrho,&dxdtheta,&d2xdtheta2,&d2xdthetadrho,&dummy1);
2689         
2690         ppvald_2D(rayequil.y_fit,rayparam.dS[0],Y[0],Y[1],&y,&dydrho,&dydtheta,&d2ydtheta2,&d2ydthetadrho,&dummy1);
2691         ppvald_2D(rayequil.r_fit,rayparam.dS[0],Y[0],Y[1],&r,&drdrho,&drdtheta,&d2rdtheta2,&d2rdthetadrho,&dummy1);
2692         ppvald_2D(rayequil.calpha_fit,rayparam.dS[0],Y[0],Y[1],&calpha,&dcalphadrho,&dcalphadtheta,&d2calphadtheta2,&d2calphadthetadrho,&dummy1);
2693         ppvald_2D(rayequil.salpha_fit,rayparam.dS[0],Y[0],Y[1],&salpha,&dsalphadrho,&dsalphadtheta,&d2salphadtheta2,&d2salphadthetadrho,&dummy1);
2694         ppvald_2D(rayequil.gradrho_fit,rayparam.dS[0],Y[0],Y[1],&gradrho,&dgradrhodrho,&dgradrhodtheta,&d2gradrhodtheta2,&d2gradrhodthetadrho,&dummy1);
2695         
2696         ppvald_2D(rayequil.Bx_fit,rayparam.dS[0],Y[0],Y[1],&Bx,&dBxdrho,&dBxdtheta,&dummy1,&dummy2,&dummy3);
2697         ppvald_2D(rayequil.By_fit,rayparam.dS[0],Y[0],Y[1],&By,&dBydrho,&dBydtheta,&dummy1,&dummy2,&dummy3);
2698         ppvald_2D(rayequil.Bz_fit,rayparam.dS[0],Y[0],Y[1],&Bz,&dBzdrho,&dBzdtheta,&dummy1,&dummy2,&dummy3);
2699         ppvald_2D(rayequil.BP_fit,rayparam.dS[0],Y[0],Y[1],&BP,&dBPdrho,&dBPdtheta,&dummy1,&dummy2,&dummy3);
2700         ppvald_2D(rayequil.B_fit,rayparam.dS[0],Y[0],Y[1],&BB,&dBBdrho,&dBBdtheta,&dummy1,&dummy2,&dummy3);
2701         
2702         build_raymagnetic(Y[1],raymagnetic,equilparam,x,dxdrho,dxdtheta,d2xdtheta2,d2xdthetadrho,d2xdrho2,
2703                 y,dydrho,dydtheta,d2ydtheta2,d2ydthetadrho,d2ydrho2,
2704                 r,drdrho,drdtheta,d2rdtheta2,d2rdthetadrho,d2rdrho2,
2705                 calpha,dcalphadrho,dcalphadtheta,d2calphadtheta2,d2calphadthetadrho,d2calphadrho2,
2706                 salpha,dsalphadrho,dsalphadtheta,d2salphadtheta2,d2salphadthetadrho,d2salphadrho2,
2707                 gradrho,dgradrhodrho,dgradrhodtheta,d2gradrhodtheta2,d2gradrhodthetadrho,d2gradrhodrho2,
2708                 Bx,dBxdrho,dBxdtheta,d2Bxdtheta2,d2Bxdthetadrho,d2Bxdrho2,dBxdz,
2709                 By,dBydrho,dBydtheta,d2Bydtheta2,d2Bydthetadrho,d2Bydrho2,dBydz,
2710                 Bz,dBzdrho,dBzdtheta,d2Bzdtheta2,d2Bzdthetadrho,d2Bzdrho2,dBzdz,
2711                 BP,dBPdrho,dBPdtheta,d2BPdtheta2,d2BPdthetadrho,d2BPdrho2,dBPdz,
2712                 BB,dBBdrho,dBBdtheta,dBBdz,d2BBdtheta2,d2BBdthetadrho,d2BBdrho2,flag_metric);
2713     }
2714     else/*Cartesian case*/
2715     {
2716         substitution(rayequil,rayparam,equilparam,&rho,&theta,Y);/*Retrieve (rho,theta) from (x,y) or (Y[0],Y[1]) here*/
2717         
2718         ppvald_2D(rayequil.x_fit,rayparam.dS[0],rho,theta,&x,&dxdrho,&dxdtheta,&d2xdtheta2,&d2xdthetadrho,&d2xdrho2);
2719         ppvald_2D(rayequil.y_fit,rayparam.dS[0],rho,theta,&y,&dydrho,&dydtheta,&d2ydtheta2,&d2ydthetadrho,&d2ydrho2);
2720         ppvald_2D(rayequil.r_fit,rayparam.dS[0],rho,theta,&r,&drdrho,&drdtheta,&d2rdtheta2,&d2rdthetadrho,&d2rdrho2);
2721         ppvald_2D(rayequil.calpha_fit,rayparam.dS[0],rho,theta,&calpha,&dcalphadrho,&dcalphadtheta,&d2calphadtheta2,&d2calphadthetadrho,&d2calphadrho2);
2722         ppvald_2D(rayequil.salpha_fit,rayparam.dS[0],rho,theta,&salpha,&dsalphadrho,&dsalphadtheta,&d2salphadtheta2,&d2salphadthetadrho,&d2salphadrho2);
2723         ppvald_2D(rayequil.gradrho_fit,rayparam.dS[0],rho,theta,&gradrho,&dgradrhodrho,&dgradrhodtheta,&d2gradrhodtheta2,&d2gradrhodthetadrho,&d2gradrhodrho2);
2724         
2725         ppvald_2D(rayequil.Bx_fit,rayparam.dS[0],rho,theta,&Bx,&dBxdrho,&dBxdtheta,&d2Bxdtheta2,&d2Bxdthetadrho,&d2Bxdrho2);
2726         ppvald_2D(rayequil.By_fit,rayparam.dS[0],rho,theta,&By,&dBydrho,&dBydtheta,&d2Bydtheta2,&d2Bydthetadrho,&d2Bydrho2);
2727         ppvald_2D(rayequil.Bz_fit,rayparam.dS[0],rho,theta,&Bz,&dBzdrho,&dBzdtheta,&d2Bzdtheta2,&d2Bzdthetadrho,&d2Bzdrho2);
2728         ppvald_2D(rayequil.BP_fit,rayparam.dS[0],rho,theta,&BP,&dBPdrho,&dBPdtheta,&d2BPdtheta2,&d2BPdthetadrho,&d2BPdrho2);
2729         ppvald_2D(rayequil.B_fit,rayparam.dS[0],rho,theta,&BB,&dBBdrho,&dBBdtheta,&d2BBdtheta2,&d2BBdthetadrho,&d2BBdrho2);
2730         
2731         build_raymagnetic(theta,raymagnetic,equilparam,x,dxdrho,dxdtheta,d2xdtheta2,d2xdthetadrho,d2xdrho2,
2732                 y,dydrho,dydtheta,d2ydtheta2,d2ydthetadrho,d2ydrho2,
2733                 r,drdrho,drdtheta,d2rdtheta2,d2rdthetadrho,d2rdrho2,
2734                 calpha,dcalphadrho,dcalphadtheta,d2calphadtheta2,d2calphadthetadrho,d2calphadrho2,
2735                 salpha,dsalphadrho,dsalphadtheta,d2salphadtheta2,d2salphadthetadrho,d2salphadrho2,
2736                 gradrho,dgradrhodrho,dgradrhodtheta,d2gradrhodtheta2,d2gradrhodthetadrho,d2gradrhodrho2,
2737                 Bx,dBxdrho,dBxdtheta,d2Bxdtheta2,d2Bxdthetadrho,d2Bxdrho2,dBxdz,
2738                 By,dBydrho,dBydtheta,d2Bydtheta2,d2Bydthetadrho,d2Bydrho2,dBydz,
2739                 Bz,dBzdrho,dBzdtheta,d2Bzdtheta2,d2Bzdthetadrho,d2Bzdrho2,dBzdz,
2740                 BP,dBPdrho,dBPdtheta,d2BPdtheta2,d2BPdthetadrho,d2BPdrho2,dBPdz,
2741                 BB,dBBdrho,dBBdtheta,d2BBdtheta2,d2BBdthetadrho,d2BBdrho2,dBBdz,flag_metric);
2742     }
2743     
2744     /*Definition of the derivatives used to defined the cartesian derivatives*/
2745     
2746     double calpha_theta = calpha*cos(theta) + salpha*sin(theta);/*cos(alpha-theta)*/
2747     double salpha_theta = salpha*cos(theta) - calpha*sin(theta);/*sin(alpha-theta)*/
2748     
2749     double drhodx = gradrho*equilparam.ap[0]*calpha_theta;/*drhodx for the change of variable (rho,theta)->(x,y)*/
2750     double drhody = -gradrho*equilparam.ap[0]*salpha_theta;/*drhody for the change of variable (rho,theta)->(x,y)*/
2751     double dthetadx = -sin(theta)*equilparam.ap[0]/r;/*dthetadx for the change of variable (rho,theta)->(x,y)*/
2752     double dthetady = cos(theta)*equilparam.ap[0]/r;/*dthetady for the change of variable (rho,theta)->(x,y)*/
2753     
2754     double dxdrhobis = cos(theta)/(calpha*raymagnetic.gradrhon[0]);/*dxdrho for the change of variable (x,y)->(rho,theta)*/
2755     double dydrhobis = sin(theta)/(calpha*raymagnetic.gradrhon[0]);/*dydrho for the change of variable (x,y)->(rho,theta)*/
2756     double dxdthetabis = raymagnetic.rn[0]*salpha_theta/calpha;/*dxdtheta for the change of variable (x,y)->(rho,theta)*/
2757     double dydthetabis = raymagnetic.rn[0]*calpha_theta/calpha;/*dydtheta for the change of variable (x,y)->(rho,theta)*/
2758     
2759     if (equilparam.zZi[0] > 0) { /*Plasma case, otherwise vacuum*/
2760         
2761         if (flag_metric == 1)
2762         {
2763             
2764             ppvald_1D(rayequil.Te_fit,rayparam.dS[0],Y[0],&rayprofiles.Te[0],&rayprofiles.dTedY[0],&rayprofiles.d2TedY2[0]);
2765             
2766             rayprofiles.dTedY[1] = 0;/*Te is taken constant on a magnetic flux surface*/
2767             rayprofiles.dTedY[2] = 0;/*Te is taken constant on a magnetic flux surface*/
2768             
2769             ppvald_1D(rayequil.ne_fit,rayparam.dS[0],Y[0],&rayprofiles.ne[0],&rayprofiles.dnedY[0],&rayprofiles.d2nedY2[0]);
2770             rayprofiles.dnedY[1] = 0;/*ne is taken constant on a magnetic flux surface*/
2771             rayprofiles.dnedY[2] = 0;/*ne is taken constant on a magnetic flux surface*/
2772             
2773             /*mexPrintf("Y[0],Y[1],Y[2],ne[0]:%g,%g,%g,%g\n",Y[0],Y[1],Y[2],rayprofiles.ne[0]);*/
2774             
2775             ppvald_1D(rayequil.zTi_fit,rayparam.dS[0],Y[0],rayprofiles.zTi,dTidY,d2TidY2);
2776             ppvald_1D(rayequil.zni_fit,rayparam.dS[0],Y[0],rayprofiles.zni,dnidY,d2nidY2);
2777             
2778             for (is=0;is/*ni is taken constant on a magnetic flux surface*/
2782                 rayprofiles.dzTidY[is][2] = 0.0;/*ni is taken constant on a magnetic flux surface*/
2783                 rayprofiles.d2zTidY2[is][0] = d2TidY2[is];
2784                 rayprofiles.d2zTidY2[is][1] = 0.0;/*ni is taken constant on a magnetic flux surface*/
2785                 rayprofiles.d2zTidY2[is][2] = 0.0;/*ni is taken constant on a magnetic flux surface*/
2786                 
2787                 rayprofiles.dznidY[is][0] = dnidY[is];
2788                 rayprofiles.dznidY[is][1] = 0.0;/*ni is taken constant on a magnetic flux surface*/
2789                 rayprofiles.dznidY[is][2] = 0.0;/*ni is taken constant on a magnetic flux surface*/
2790                 rayprofiles.d2znidY2[is][0] = d2nidY2[is];
2791                 rayprofiles.d2znidY2[is][1] = 0.0;/*ni is taken constant on a magnetic flux surface*/
2792                 rayprofiles.d2znidY2[is][2] = 0.0;/*ni is taken constant on a magnetic flux surface*/
2793             }
2794         }
2795         else
2796         {
2797             ppvald_1D(rayequil.Te_fit,rayparam.dS[0],rho,&rayprofiles.Te[0],&rayprofiles.dTedY[0],&rayprofiles.d2TedY2[0]);
2798             save = rayprofiles.dTedY[0];
2799             rayprofiles.dTedY[0] = save*drhodx;
2800             rayprofiles.dTedY[1] = save*drhody;
2801             rayprofiles.dTedY[2] = 0;/*Te is taken constant on a magnetic flux surface*/
2802             
2803             ppvald_1D(rayequil.ne_fit,rayparam.dS[0],rho,&rayprofiles.ne[0],&rayprofiles.dnedY[0],&rayprofiles.d2nedY2[0]);
2804             save = rayprofiles.dnedY[0];
2805             rayprofiles.dnedY[0] = save*drhodx;
2806             rayprofiles.dnedY[1] = save*drhody;
2807             rayprofiles.dnedY[2] = 0;/*Te is taken constant on a magnetic flux surface*/
2808             
2809             /*mexPrintf("Y[0],Y[1],Y[2],ne[0]:%g,%g,%g,%g\n",Y[0],Y[1],Y[2],rayprofiles.ne[0]);*/
2810             
2811             ppvald_1D(rayequil.zTi_fit,rayparam.dS[0],rho,rayprofiles.zTi,dTidY,d2TidY2);
2812             ppvald_1D(rayequil.zni_fit,rayparam.dS[0],rho,rayprofiles.zni,dnidY,d2nidY2);
2813             
2814             for (is=0;is/*ni is taken constant on a magnetic flux surface*/
2820                 rayprofiles.d2zTidY2[is][0] = d2TidY2[is];
2821                 rayprofiles.d2zTidY2[is][1] = 0.0;/*ni is taken constant on a magnetic flux surface*/
2822                 rayprofiles.d2zTidY2[is][2] = 0.0;/*ni is taken constant on a magnetic flux surface*/
2823                 
2824                 save = dnidY[is];
2825                 rayprofiles.dznidY[is][0] = save*drhodx;
2826                 rayprofiles.dznidY[is][1] = save*drhody;
2827                 rayprofiles.dznidY[is][2] = 0.0;/*ni is taken constant on a magnetic flux surface*/
2828                 rayprofiles.d2znidY2[is][0] = d2nidY2[is];
2829                 rayprofiles.d2znidY2[is][1] = 0.0;/*ni is taken constant on a magnetic flux surface*/
2830                 rayprofiles.d2znidY2[is][2] = 0.0;/*ni is taken constant on a magnetic flux surface*/
2831             }
2832         }
2833         
2834         /*--------------------------------------------------------------------------*/
2835         /*---------------------Contribution of the fluctuations --------------------*/
2836         /*--------------------------------------------------------------------------*/
2837         
2838         if (flag_fluct == 1) { /* no fluctuation in vacuum */
2839             
2840             /*Initialisation of the perturbations */
2841             
2842             if(flag_metric == 2)/*All fluctuations calculations will be done in flux coordinates to avoid having to drastically modify this part of the code, the final values will be translated in cartesian coordinates at the end*/
2843             {
2844                 xbis = Y[0];
2845                 ybis = Y[1];
2846                 Y[0] = rho;
2847                 Y[1] = theta;
2848                 
2849                 save = raymagnetic.drndY[0];
2850                 raymagnetic.drndY[0] = dxdrhobis*raymagnetic.drndY[0] + dydrhobis*raymagnetic.drndY[1];
2851                 raymagnetic.drndY[1] = dxdthetabis*save + dydthetabis*raymagnetic.drndY[1];
2852                 
2853                 save = raymagnetic.dxndY[0];
2854                 raymagnetic.dxndY[0] = dxdrhobis*raymagnetic.dxndY[0] + dydrhobis*raymagnetic.dxndY[1];
2855                 raymagnetic.dxndY[1] = dxdthetabis*save + dydthetabis*raymagnetic.dxndY[1];
2856                 
2857                 save = raymagnetic.dyndY[0];
2858                 raymagnetic.dyndY[0] = dxdrhobis*raymagnetic.dyndY[0] + dydrhobis*raymagnetic.dyndY[1];
2859                 raymagnetic.dyndY[1] = dxdthetabis*save + dydthetabis*raymagnetic.dyndY[1];
2860                 
2861                 save = raymagnetic.dBrhondY[0];
2862                 raymagnetic.dBrhondY[0] = dxdrhobis*raymagnetic.dBrhondY[0] + dydrhobis*raymagnetic.dBrhondY[1];
2863                 raymagnetic.dBrhondY[1] = dxdthetabis*save + dydthetabis*raymagnetic.dBrhondY[1];
2864                 
2865                 save = raymagnetic.dBsndY[0];
2866                 raymagnetic.dBsndY[0] = dxdrhobis*raymagnetic.dBsndY[0] + dydrhobis*raymagnetic.dBsndY[1];
2867                 raymagnetic.dBsndY[1] = dxdthetabis*save + dydthetabis*raymagnetic.dBsndY[1];
2868                 
2869                 save = raymagnetic.dBzndY[0];
2870                 raymagnetic.dBzndY[0] = dxdrhobis*raymagnetic.dBzndY[0] + dydrhobis*raymagnetic.dBzndY[1];
2871                 raymagnetic.dBzndY[1] = dxdthetabis*save + dydthetabis*raymagnetic.dBzndY[1];
2872                 
2873                 save = raymagnetic.dBdY[0];
2874                 raymagnetic.dBdY[0] = dxdrhobis*raymagnetic.dBdY[0] + dydrhobis*raymagnetic.dBdY[1];
2875                 raymagnetic.dBdY[1] = dxdthetabis*save + dydthetabis*raymagnetic.dBdY[1];
2876                 
2877                 save = raymagnetic.dsalphadY[0];
2878                 raymagnetic.dsalphadY[0] = dxdrhobis*raymagnetic.dsalphadY[0] + dydrhobis*raymagnetic.dsalphadY[1];
2879                 raymagnetic.dsalphadY[1] = dxdthetabis*save + dydthetabis*raymagnetic.dsalphadY[1];
2880                 
2881                 save = raymagnetic.dcalphadY[0];
2882                 raymagnetic.dcalphadY[0] = dxdrhobis*raymagnetic.dcalphadY[0] + dydrhobis*raymagnetic.dcalphadY[1];
2883                 raymagnetic.dcalphadY[1] = dxdthetabis*save + dydthetabis*raymagnetic.dcalphadY[1];
2884                 
2885                 save = raymagnetic.dgradrhondY[0];
2886                 raymagnetic.dgradrhondY[0] = dxdrhobis*raymagnetic.dgradrhondY[0] + dydrhobis*raymagnetic.dgradrhondY[1];
2887                 raymagnetic.dgradrhondY[1] = dxdthetabis*save + dydthetabis*raymagnetic.dgradrhondY[1];
2888                 
2889                 save = raymagnetic.drhoripdY[0];
2890                 raymagnetic.drhoripdY[0] = dxdrhobis*raymagnetic.drhoripdY[0] + dydrhobis*raymagnetic.drhoripdY[1];
2891                 raymagnetic.drhoripdY[1] = dxdthetabis*save + dydthetabis*raymagnetic.drhoripdY[1];
2892                 
2893                 save = raymagnetic.dUpsilonndY[0];
2894                 raymagnetic.dUpsilonndY[0] = dxdrhobis*raymagnetic.dUpsilonndY[0] + dydrhobis*raymagnetic.dUpsilonndY[1];
2895                 raymagnetic.dUpsilonndY[1] = dxdthetabis*save + dydthetabis*raymagnetic.dUpsilonndY[1];
2896                 
2897                 save = rayprofiles.dTedY[0];
2898                 rayprofiles.dTedY[0] = dxdrhobis*rayprofiles.dTedY[0] + dydrhobis*rayprofiles.dTedY[1];
2899                 rayprofiles.dTedY[1] = dxdthetabis*save + dydthetabis*rayprofiles.dTedY[1];
2900                 
2901                 save = rayprofiles.dnedY[0];
2902                 rayprofiles.dnedY[0] = dxdrhobis*rayprofiles.dnedY[0] + dydrhobis*rayprofiles.dnedY[1];
2903                 rayprofiles.dnedY[1] = dxdthetabis*save + dydthetabis*rayprofiles.dnedY[1];
2904                 
2905                 for(is=0;isfor (is=0;is/*geometrical factor for fluctuations phase, kpar = 0 drift wave model */
2981             ppvald_2D(rayfluctuations.Xcm_fit,rayparam.dS[0],Y[0],Y[1],&cm,&dummy,&dummy,&dummy,&dummy);/*geometrical factor for fluctuations phase, kpar = 0 drift wave model */
2982             ppvali_2D(rayfluctuations.Xcm_fit,rayparam.dS[0],Y[0],Y0[1],Y[1],&icm,&idcmdrho);/*geometrical factor for fluctuations phase, kpar = 0 drift wave model */
2983             
2984             /*
2985              mexPrintf("rho,theta,phi,gphase,dgphasedrho,dgphasedtheta,dgphasedphi:%g,%g,%g,%g,%g,%g,%g\n",Y[0],Y[1],Y[2],gphase,dgphasedrho,dgphasedtheta,dgphasedphi);
2986              mexPrintf("cn0,dcn0drho,icm,idcmdrho,cm:%g,%g,%g,%g,%g\n",cn0,dcn0drho,icm,idcmdrho,cm);
2987              */
2988             
2989             if (fluctparam.ne_nmodel[0] > 0) {/* Electron density statistical fluctuations */
2990                 
2991                 for (imodel=0; imodel < fluctparam.ne_nmodel[0]; imodel++) {
2992                     
2993                     dl = fluctparam.ne_lmax[imodel][0] - fluctparam.ne_lmin[imodel][0] + 1.0;
2994                     dm = fluctparam.ne_mmax[imodel][0] - fluctparam.ne_mmin[imodel][0] + 1.0;
2995                     
2996                     Flambda = (1.0 + fluctparam.ne_polmode[imodel][0] + (1.0 - fluctparam.ne_polmode[imodel][0])*cos(Y[1]))/2.0;
2997                     dFlambdadrho = 0.0;
2998                     dFlambdadtheta = -(1.0 - fluctparam.ne_polmode[imodel][0])*sin(Y[1])/2.0;
2999                     dFlambdadphi = 0.0;
3000                     
3001                     Fdelta = exp(-log(2.0)*pow(Y[0] - fluctparam.ne_sigmar_rho[imodel][0],2.0)/pow(fluctparam.ne_sigmar_hwhm[imodel][0],2));
3002                     dFdeltadrho = -Fdelta*2.0*log(2.0)*(Y[0] - fluctparam.ne_sigmar_rho[imodel][0])/pow(fluctparam.ne_sigmar_hwhm[imodel][0],2);
3003                     dFdeltadtheta = 0.0;
3004                     dFdeltadphi = 0.0;
3005                     
3006                     xx = 0;
3007                     dxxdrho = 0;
3008                     dxxdtheta = 0;
3009                     dxxdphi = 0;
3010                     
3011                     if (fluctparam.ne_model[imodel][0] == 1) {/* 3-D Gaussian model (rho,theta,phi), relative epsi values (benchmark of C3PO) */
3012                         
3013                         ac = 4.0*pow(PI,0.75)*fluctparam.ne_sigmar_max[imodel][0]*sqrt(fluctparam.ne_epsi_rho[imodel][0]*fluctparam.ne_epsi_theta[imodel][0]*fluctparam.ne_epsi_phi[imodel][0]);
3014                         
3015                         for (il = fluctparam.ne_lmin[imodel][0];il <= fluctparam.ne_lmax[imodel][0];il++) {
3016                             for (im = fluctparam.ne_mmin[imodel][0];im <= fluctparam.ne_mmax[imodel][0];im++) {
3017                                 for (in = fluctparam.ne_nmin[imodel][0];in <= fluctparam.ne_nmax[imodel][0];in++) {
3018                                     
3019                                     iphase = (int)dl*(int)dm*(in-(int)fluctparam.ne_nmin[imodel][0]) + (int)dl*(im-(int)fluctparam.ne_mmin[imodel][0]) + (il-(int)fluctparam.ne_lmin[imodel][0]) + 1;
3020                                     
3021                                     phase = 2*PI*il*Y[0] + im*Y[1] + in*Y[2]/equilparam.Rp[0] + fluctparam.ne_phase[imodel][iphase-1];
3022                                     dphasedrho = 2*PI*il;
3023                                     dphasedtheta = im;
3024                                     dphasedphi = in;
3025                                     
3026                                     u_l = PI*fluctparam.ne_epsi_rho[imodel][0]*il;
3027                                     u_m = PI*fluctparam.ne_epsi_theta[imodel][0]*im;
3028                                     u_n = PI*fluctparam.ne_epsi_phi[imodel][0]*in;
3029                                     
3030                                     expu_l = exp(-u_l*u_l/2);
3031                                     expu_m = exp(-u_m*u_m/2);
3032                                     expu_n = exp(-u_n*u_n/2);
3033                                     
3034                                     almn = expu_l*expu_m*expu_n;
3035                                     
3036                                     xx += ac*almn*Flambda*Fdelta*sin(phase);
3037                                     dxxdrho += ac*almn*Flambda*(Fdelta*cos(phase)*dphasedrho + dFdeltadrho*sin(phase));
3038                                     dxxdtheta += ac*almn*Fdelta*(Flambda*cos(phase)*dphasedtheta + dFlambdadtheta*sin(phase));
3039                                     dxxdphi += ac*almn*Flambda*Fdelta*cos(phase)*dphasedphi;
3040                                 }
3041                             }
3042                         }
3043                         
3044                         /* convolution to avoid negative density values. No restriction on positive values, ht(x) = x */
3045                         
3046                         halftanh(xx,&ht,&dht,&d2ht);
3047                         
3048                         nefsne += ht;
3049                         dnefsnedrho += dht*dxxdrho;
3050                         dnefsnedtheta += dht*dxxdtheta;
3051                         dnefsnedphi += dht*dxxdphi;
3052                         
3053                     }
3054                     
3055                     if (fluctparam.ne_model[imodel][0] == 2) {/* 3-D Gaussian model (rho,theta,phi), absolute epsi values (benchmark of C3PO) */
3056                         
3057                         ac = 4.0*pow(PI,0.75)*fluctparam.ne_sigmar_max[imodel][0]*sqrt(fluctparam.ne_epsi_rho[imodel][0]*fluctparam.ne_epsi_theta[imodel][0]*fluctparam.ne_epsi_phi[imodel][0]/L_rho/xL_theta/XL_phi);
3058                         dacdrho = -0.5*ac*(dL_rhodrho/L_rho + dxL_thetadrho/xL_theta +  dXL_phidrho/XL_phi);
3059                         dacdtheta = -0.5*ac*(dL_rhodtheta/L_rho + dxL_thetadtheta/xL_theta + dXL_phidtheta/XL_phi);
3060                         dacdphi = -0.5*ac*(dL_rhodphi/L_rho + dxL_thetadphi/xL_theta + dXL_phidphi/XL_phi);
3061                         
3062                         for (il = fluctparam.ne_lmin[imodel][0];il <= fluctparam.ne_lmax[imodel][0];il++) {
3063                             for (im = fluctparam.ne_mmin[imodel][0];im <= fluctparam.ne_mmax[imodel][0];im++) {
3064                                 for (in = fluctparam.ne_nmin[imodel][0];in <= fluctparam.ne_nmax[imodel][0];in++) {
3065                                     
3066                                     iphase = (int)dl*(int)dm*(in-(int)fluctparam.ne_nmin[imodel][0]) + (int)dl*(im-(int)fluctparam.ne_mmin[imodel][0]) + (il-(int)fluctparam.ne_lmin[imodel][0]) + 1;
3067                                     
3068                                     phase = 2*PI*il*Y[0] + im*Y[1] + in*Y[2]/equilparam.Rp[0] + fluctparam.ne_phase[imodel][iphase-1];
3069                                     dphasedrho = 2*PI*il;
3070                                     dphasedtheta = im;
3071                                     dphasedphi = in;
3072                                     
3073                                     u_l = PI*fluctparam.ne_epsi_rho[imodel][0]*il/L_rho;
3074                                     u_m = PI*fluctparam.ne_epsi_theta[imodel][0]*im/xL_theta;
3075                                     u_n = PI*fluctparam.ne_epsi_phi[imodel][0]*in/XL_phi;
3076                                     
3077                                     du_ldrho = -u_l/L_rho*dL_rhodrho;
3078                                     du_mdrho = -u_m/xL_theta*dxL_thetadrho;
3079                                     du_ndrho = -u_n/XL_phi*dXL_phidrho;
3080                                     
3081                                     du_ldtheta = -u_l/L_rho*dL_rhodtheta;
3082                                     du_mdtheta = -u_m/xL_theta*dxL_thetadtheta;
3083                                     du_ndtheta = -u_n/XL_phi*dXL_phidtheta;
3084                                     
3085                                     du_ldphi = -u_l/L_rho*dL_rhodphi;
3086                                     du_mdphi = -u_m/xL_theta*dxL_thetadphi;
3087                                     du_ndphi = -u_n/XL_phi*dXL_phidphi;
3088                                     
3089                                     expu_l = exp(-u_l*u_l/2);
3090                                     expu_m = exp(-u_m*u_m/2);
3091                                     expu_n = exp(-u_n*u_n/2);
3092                                     almn = expu_l*expu_m*expu_n;
3093                                     
3094                                     dexpu_ldrho = -expu_l*u_l*du_ldrho;
3095                                     dexpu_mdrho = -expu_m*u_m*du_mdrho;
3096                                     dexpu_ndrho = -expu_n*u_n*du_ndrho;
3097                                     dalmndrho = dexpu_ldrho*expu_m*expu_n + expu_l*dexpu_mdrho*expu_n + expu_l*expu_m*dexpu_ndrho;
3098                                     
3099                                     dexpu_ldtheta = -expu_l*u_l*du_ldtheta;
3100                                     dexpu_mdtheta = -expu_m*u_m*du_mdtheta;
3101                                     dexpu_ndtheta = -expu_n*u_n*du_ndtheta;
3102                                     dalmndtheta = dexpu_ldtheta*expu_m*expu_n + expu_l*dexpu_mdtheta*expu_n + expu_l*expu_m*dexpu_ndtheta;
3103                                     
3104                                     dexpu_ldphi = -expu_l*u_l*du_ldphi;
3105                                     dexpu_mdphi = -expu_m*u_m*du_mdphi;
3106                                     dexpu_ndphi = -expu_n*u_n*du_ndphi;
3107                                     dalmndphi = dexpu_ldphi*expu_m*expu_n + expu_l*dexpu_mdphi*expu_n + expu_l*expu_m*dexpu_ndphi;
3108                                     
3109                                     xx += ac*Flambda*Fdelta*almn*sin(phase);
3110                                     dxxdrho += dacdrho*Flambda*Fdelta*almn*sin(phase) + ac*dFlambdadrho*Fdelta*almn*sin(phase) + ac*Flambda*dFdeltadrho*almn*sin(phase) + ac*Flambda*Fdelta*dalmndrho*sin(phase) + ac*Flambda*Fdelta*almn*cos(phase)*dphasedrho;
3111                                     dxxdtheta += dacdtheta*Flambda*Fdelta*almn*sin(phase) + ac*dFlambdadtheta*Fdelta*almn*sin(phase) + ac*Flambda*dFdeltadtheta*almn*sin(phase) + ac*Flambda*Fdelta*dalmndtheta*sin(phase) + ac*Flambda*Fdelta*almn*cos(phase)*dphasedtheta;
3112                                     dxxdphi += dacdphi*Flambda*Fdelta*almn*sin(phase) + ac*dFlambdadphi*Fdelta*almn*sin(phase) + ac*Flambda*dFdeltadphi*almn*sin(phase) + ac*Flambda*Fdelta*dalmndphi*sin(phase) + ac*Flambda*Fdelta*almn*cos(phase)*dphasedphi;
3113                                 }
3114                             }
3115                         }
3116                         
3117                         /* convolution to avoid negative density values. No restriction on positive values, ht(x) = x */
3118                         
3119                         halftanh(xx,&ht,&dht,&d2ht);
3120                         
3121                         nefsne += ht;
3122                         dnefsnedrho += dht*dxxdrho;
3123                         dnefsnedtheta += dht*dxxdtheta;
3124                         dnefsnedphi += dht*dxxdphi;
3125                     }
3126                     
3127                     if (fluctparam.ne_model[imodel][0] == 3) {/* 2-D Gaussian model (rho,curtheta), absolute epsi values (drift wave model, global cylindrical phase approx.) */
3128                         
3129                         /* Note that epsi_perp = fluctparam.ne_epsi_theta */
3130                         
3131                         ac = 2.0*sqrt(2.0*PI)*fluctparam.ne_sigmar_max[imodel][0]*sqrt(fluctparam.ne_epsi_rho[imodel][0]*fluctparam.ne_epsi_theta[imodel][0]/L_rho/xL_perp);
3132                         dacdrho = -0.5*ac*(dL_rhodrho/L_rho + dxL_perpdrho/xL_perp);
3133                         dacdtheta = -0.5*ac*(dL_rhodtheta/L_rho + dxL_perpdtheta/xL_perp);
3134                         dacdphi = -0.5*ac*(dL_rhodphi/L_rho + dxL_perpdphi/xL_perp);
3135                         
3136                         for (il = fluctparam.ne_lmin[imodel][0];il <= fluctparam.ne_lmax[imodel][0];il++) {
3137                             for (im = fluctparam.ne_mmin[imodel][0];im <= fluctparam.ne_mmax[imodel][0];im++) {
3138                                 
3139                                 iphase = (int)dl*(im-(int)fluctparam.ne_mmin[imodel][0]) + (il-(int)fluctparam.ne_lmin[imodel][0]) + 1;
3140                                 
3141                                 curtheta = xq*Y[1] - Y[2]/equilparam.Rp[0];
3142                                 dcurthetadrho = dxqdrho*Y[1];
3143                                 dcurthetadtheta = dxqdtheta*Y[1] + xq;
3144                                 dcurthetadphi = dxqdphi*Y[1]-1.0;
3145                                 
3146                                 phase = 2*PI*il*Y[0] + im*curtheta + fluctparam.ne_phase[imodel][iphase-1];
3147                                 dphasedrho = 2*PI*il + im*dcurthetadrho;
3148                                 dphasedtheta = im*dcurthetadtheta;
3149                                 dphasedphi = im*dcurthetadphi;
3150                                 
3151                                 u_l = PI*fluctparam.ne_epsi_rho[imodel][0]*il/L_rho;
3152                                 u_m = PI*fluctparam.ne_epsi_theta[imodel][0]*im/xL_perp;
3153                                 
3154                                 du_ldrho = -u_l/L_rho*dL_rhodrho;
3155                                 du_mdrho = -u_m/xL_perp*dxL_perpdrho;
3156                                 
3157                                 du_ldtheta = -u_l/L_rho*dL_rhodtheta;
3158                                 du_mdtheta = -u_m/xL_perp*dxL_perpdtheta;
3159                                 
3160                                 du_ldphi = -u_l/L_rho*dL_rhodphi;
3161                                 du_mdphi = -u_m/xL_perp*dxL_perpdphi;
3162                                 
3163                                 expu_l = exp(-u_l*u_l/2);
3164                                 expu_m = exp(-u_m*u_m/2);
3165                                 alm = expu_l*expu_m;
3166                                 
3167                                 dexpu_ldrho = -expu_l*u_l*du_ldrho;
3168                                 dexpu_mdrho = -expu_m*u_m*du_mdrho;
3169                                 dalmdrho = dexpu_ldrho*expu_m + expu_l*dexpu_mdrho;
3170                                 
3171                                 dexpu_ldtheta = -expu_l*u_l*du_ldtheta;
3172                                 dexpu_mdtheta = -expu_m*u_m*du_mdtheta;
3173                                 dalmdtheta = dexpu_ldtheta*expu_m + expu_l*dexpu_mdtheta;
3174                                 
3175                                 dexpu_ldphi = -expu_l*u_l*du_ldphi;
3176                                 dexpu_mdphi = -expu_m*u_m*du_mdphi;
3177                                 dalmdphi = dexpu_ldphi*expu_m + expu_l*dexpu_mdphi;
3178                                 
3179                                 xx += ac*Flambda*Fdelta*alm*sin(phase);
3180                                 dxxdrho += dacdrho*Flambda*Fdelta*alm*sin(phase) + ac*dFlambdadrho*Fdelta*alm*sin(phase) + ac*Flambda*dFdeltadrho*alm*sin(phase) + ac*Flambda*Fdelta*dalmdrho*sin(phase) + ac*Flambda*Fdelta*alm*cos(phase)*dphasedrho;
3181                                 dxxdtheta += dacdtheta*Flambda*Fdelta*alm*sin(phase) + ac*dFlambdadtheta*Fdelta*alm*sin(phase) + ac*Flambda*dFdeltadtheta*alm*sin(phase) + ac*Flambda*Fdelta*dalmdtheta*sin(phase) + ac*Flambda*Fdelta*alm*cos(phase)*dphasedtheta;
3182                                 dxxdphi += dacdphi*Flambda*Fdelta*alm*sin(phase) + ac*dFlambdadphi*Fdelta*alm*sin(phase) + ac*Flambda*dFdeltadphi*alm*sin(phase) + ac*Flambda*Fdelta*dalmdphi*sin(phase) + ac*Flambda*Fdelta*alm*cos(phase)*dphasedphi;
3183                                 
3184                             }
3185                         }
3186                         
3187                         /* convolution to avoid negative density values. No restriction on positive values, ht(x) = x */
3188                         
3189                         halftanh(xx,&ht,&dht,&d2ht);
3190                         
3191                         nefsne += ht;
3192                         dnefsnedrho += dht*dxxdrho;
3193                         dnefsnedtheta += dht*dxxdtheta;
3194                         dnefsnedphi += dht*dxxdphi;
3195                     }
3196                     
3197                     if (fluctparam.ne_model[imodel][0] == 4) {/* 1-D Gaussian model (rho,curtheta), absolute epsi values (drift wave model, global cylindrical phase approx.) */
3198                         
3199                         /* Note that epsi_perp = fluctparam.ne_epsi_theta */
3200                         
3201                         ac = 2.0*sqrt(sqrt(PI))*fluctparam.ne_sigmar_max[imodel][0]*sqrt(fluctparam.ne_epsi_theta[imodel][0]/xL_perp);
3202                         dacdrho = -0.5*ac*dxL_perpdrho/xL_perp;
3203                         dacdtheta = -0.5*ac*dxL_perpdtheta/xL_perp;
3204                         dacdphi = -0.5*ac*dxL_perpdphi/xL_perp;
3205                         
3206                         for (im = fluctparam.ne_mmin[imodel][0];im <= fluctparam.ne_mmax[imodel][0];im++) {
3207                             
3208                             iphase = (im-(int)fluctparam.ne_mmin[imodel][0]) + 1;
3209                             
3210                             curtheta = xq*(Y[1] - Y0[1]) - (Y[2] - Y0[2])/equilparam.Rp[0];
3211                             dcurthetadrho = dxqdrho*(Y[1] - Y0[1]);
3212                             dcurthetadtheta = dxqdtheta*Y[1] + xq;
3213                             dcurthetadphi = dxqdphi*Y[1] - 1.0;
3214                             
3215                             phase = im*curtheta + fluctparam.ne_phase[imodel][iphase-1];
3216                             dphasedrho = im*dcurthetadrho;
3217                             dphasedtheta = im*dcurthetadtheta;
3218                             dphasedphi = im*dcurthetadphi;
3219                             
3220                             u_m = PI*fluctparam.ne_epsi_theta[imodel][0]*im/xL_perp;
3221                             
3222                             du_mdrho = -u_m/xL_perp*dxL_perpdrho;
3223                             
3224                             du_mdtheta = -u_m/xL_perp*dxL_perpdtheta;
3225                             
3226                             du_mdphi = -u_m/xL_perp*dxL_perpdphi;
3227                             
3228                             expu_m = exp(-u_m*u_m/2);
3229                             am = expu_m;
3230                             
3231                             damdrho = -expu_m*u_m*du_mdrho;
3232                             
3233                             damdtheta = -expu_m*u_m*du_mdtheta;
3234                             
3235                             damdphi = -expu_m*u_m*du_mdphi;
3236                             
3237                             xx += ac*Flambda*Fdelta*am*sin(phase);
3238                             dxxdrho += dacdrho*Flambda*Fdelta*am*sin(phase) + ac*dFlambdadrho*Fdelta*am*sin(phase) + ac*Flambda*dFdeltadrho*am*sin(phase) + ac*Flambda*Fdelta*damdrho*sin(phase) + ac*Flambda*Fdelta*am*cos(phase)*dphasedrho;
3239                             dxxdtheta += dacdtheta*Flambda*Fdelta*am*sin(phase) + ac*dFlambdadtheta*Fdelta*am*sin(phase) + ac*Flambda*dFdeltadtheta*am*sin(phase) + ac*Flambda*Fdelta*damdtheta*sin(phase) + ac*Flambda*Fdelta*am*cos(phase)*dphasedtheta;
3240                             dxxdphi += dacdphi*Flambda*Fdelta*am*sin(phase) + ac*dFlambdadphi*Fdelta*am*sin(phase) + ac*Flambda*dFdeltadphi*am*sin(phase) + ac*Flambda*Fdelta*damdphi*sin(phase) + ac*Flambda*Fdelta*am*cos(phase)*dphasedphi;
3241                             
3242                         }
3243                         
3244                         /* convolution to avoid negative density values. No restriction on positive values, ht(x) = x */
3245                         
3246                         
3247                         halftanh(xx,&ht,&dht,&d2ht);
3248                         
3249                         nefsne += ht;
3250                         dnefsnedrho += dht*dxxdrho;
3251                         dnefsnedtheta += dht*dxxdtheta;
3252                         dnefsnedphi += dht*dxxdphi;
3253                     }
3254                     
3255                     
3256                     if (fluctparam.ne_model[imodel][0] == 5) {/* 1-D Gaussian model (rho,cm,cn), absolute epsi values (drift wave model, local phase approx. ) */
3257                         
3258                         /* Note that epsi_perp = fluctparam.ne_epsi_theta */
3259                         
3260                         ac = 2.0*sqrt(sqrt(PI))*fluctparam.ne_sigmar_max[imodel][0]*sqrt(fluctparam.ne_epsi_theta[imodel][0]/xL_perp);
3261                         dacdrho = -0.5*ac*dxL_perpdrho/xL_perp;
3262                         dacdtheta = -0.5*ac*dxL_perpdtheta/xL_perp;
3263                         dacdphi = -0.5*ac*dxL_perpdphi/xL_perp;
3264                         
3265                         for (im = fluctparam.ne_mmin[imodel][0];im <= fluctparam.ne_mmax[imodel][0];im++) {
3266                             
3267                             iphase = (im-(int)fluctparam.ne_mmin[imodel][0]) + 1;
3268                             
3269                             kperp = 2*PI*im/xL_perp;
3270                             dkperpdrho = -kperp/xL_perp*dxL_perpdrho;;
3271                             dkperpdtheta = 0.0;
3272                             dkperpdphi = 0.0;
3273                             
3274                             phase = (icm + cn0*(Y[2] - Y0[2])/equilparam.Rp[0])*kperp + fluctparam.ne_phase[imodel][iphase-1];
3275                             dphasedrho = (idcmdrho + dcn0drho*(Y[2] - Y0[2])/equilparam.Rp[0])*kperp + (icm + cn0*(Y[2] - Y0[2])/equilparam.Rp[0])*dkperpdrho;
3276                             dphasedtheta = cm*kperp + (icm + cn0*(Y[2] - Y0[2])/equilparam.Rp[0])*dkperpdtheta;
3277                             dphasedphi = cn0*kperp + (icm + cn0*(Y[2] - Y0[2])/equilparam.Rp[0])*dkperpdphi;
3278                             
3279                             u_m = PI*fluctparam.ne_epsi_theta[imodel][0]*im/xL_perp;
3280                             
3281                             du_mdrho = -u_m/xL_perp*dxL_perpdrho;
3282                             
3283                             du_mdtheta = -u_m/xL_perp*dxL_perpdtheta;
3284                             
3285                             du_mdphi = -u_m/xL_perp*dxL_perpdphi;
3286                             
3287                             expu_m = exp(-u_m*u_m/2);
3288                             am = expu_m;
3289                             
3290                             damdrho = -expu_m*u_m*du_mdrho;
3291                             
3292                             damdtheta = -expu_m*u_m*du_mdtheta;
3293                             
3294                             damdphi = -expu_m*u_m*du_mdphi;
3295                             
3296                             xx += ac*Flambda*Fdelta*am*sin(phase);
3297                             dxxdrho += dacdrho*Flambda*Fdelta*am*sin(phase) + ac*dFlambdadrho*Fdelta*am*sin(phase) + ac*Flambda*dFdeltadrho*am*sin(phase) + ac*Flambda*Fdelta*damdrho*sin(phase) + ac*Flambda*Fdelta*am*cos(phase)*dphasedrho;
3298                             dxxdtheta += dacdtheta*Flambda*Fdelta*am*sin(phase) + ac*dFlambdadtheta*Fdelta*am*sin(phase) + ac*Flambda*dFdeltadtheta*am*sin(phase) + ac*Flambda*Fdelta*damdtheta*sin(phase) + ac*Flambda*Fdelta*am*cos(phase)*dphasedtheta;
3299                             dxxdphi += dacdphi*Flambda*Fdelta*am*sin(phase) + ac*dFlambdadphi*Fdelta*am*sin(phase) + ac*Flambda*dFdeltadphi*am*sin(phase) + ac*Flambda*Fdelta*damdphi*sin(phase) + ac*Flambda*Fdelta*am*cos(phase)*dphasedphi;
3300                             
3301                         }
3302                         
3303                         /* convolution to avoid negative density values. No restriction on positive values, ht(x) = x */
3304                         
3305                         halftanh(xx,&ht,&dht,&d2ht);
3306                         
3307                         nefsne += ht;
3308                         dnefsnedrho += dht*dxxdrho;
3309                         dnefsnedtheta += dht*dxxdtheta;
3310                         dnefsnedphi += dht*dxxdphi;
3311                     }
3312                     
3313                     if (fluctparam.ne_model[imodel][0] == 6) {/* 2-D Gaussian model (rho,cm,cn), absolute epsi values (drift wave model, local phase approx. ) */
3314                         
3315                         /* Note that epsi_perp = fluctparam.ne_epsi_theta */
3316                         
3317                         ac = 2.0*sqrt(2.0*PI)*fluctparam.ne_sigmar_max[imodel][0]*sqrt(fluctparam.ne_epsi_rho[imodel][0]*fluctparam.ne_epsi_theta[imodel][0]/L_rho/xL_perp);
3318                         dacdrho = -0.5*ac*(dL_rhodrho/L_rho + dxL_perpdrho/xL_perp);
3319                         dacdtheta = -0.5*ac*(dL_rhodtheta/L_rho + dxL_perpdtheta/xL_perp);
3320                         dacdphi = -0.5*ac*(dL_rhodphi/L_rho + dxL_perpdphi/xL_perp);
3321                         
3322                         for (il = fluctparam.ne_lmin[imodel][0];il <= fluctparam.ne_lmax[imodel][0];il++) {
3323                             for (im = fluctparam.ne_mmin[imodel][0];im <= fluctparam.ne_mmax[imodel][0];im++) {
3324                                 
3325                                 iphase = (int)dl*(im-(int)fluctparam.ne_mmin[imodel][0]) + (il-(int)fluctparam.ne_lmin[imodel][0]) + 1;
3326                                 
3327                                 kperp = 2*PI*im/xL_perp;
3328                                 dkperpdrho = -kperp/xL_perp*dxL_perpdrho;;
3329                                 dkperpdtheta = 0.0;
3330                                 dkperpdphi = 0.0;
3331                                 
3332                                 phase = 2*PI*il*Y[0] + (icm + cn0*(Y[2] - Y0[2])/equilparam.Rp[0])*kperp + fluctparam.ne_phase[imodel][iphase-1];
3333                                 dphasedrho = 2*PI*il + (idcmdrho + dcn0drho*(Y[2] - Y0[2])/equilparam.Rp[0])*kperp + (icm + cn0*(Y[2] - Y0[2])/equilparam.Rp[0])*dkperpdrho;
3334                                 dphasedtheta = cm*kperp + (icm + cn0*(Y[2] - Y0[2])/equilparam.Rp[0])*dkperpdtheta;
3335                                 dphasedphi = cn0*kperp + (icm + cn0*(Y[2] - Y0[2])/equilparam.Rp[0])*dkperpdphi;
3336                                 
3337                                 u_l = PI*fluctparam.ne_epsi_rho[imodel][0]*il/L_rho;
3338                                 u_m = PI*fluctparam.ne_epsi_theta[imodel][0]*im/xL_perp;
3339                                 
3340                                 du_ldrho = -u_l/L_rho*dL_rhodrho;
3341                                 du_mdrho = -u_m/xL_perp*dxL_perpdrho;
3342                                 
3343                                 du_ldtheta = -u_l/L_rho*dL_rhodtheta;
3344                                 du_mdtheta = -u_m/xL_perp*dxL_perpdtheta;
3345                                 
3346                                 du_ldphi = -u_l/L_rho*dL_rhodphi;
3347                                 du_mdphi = -u_m/xL_perp*dxL_perpdphi;
3348                                 
3349                                 expu_l = exp(-u_l*u_l/2);
3350                                 expu_m = exp(-u_m*u_m/2);
3351                                 alm = expu_l*expu_m;
3352                                 
3353                                 dexpu_ldrho = -expu_l*u_l*du_ldrho;
3354                                 dexpu_mdrho = -expu_m*u_m*du_mdrho;
3355                                 dalmdrho = dexpu_ldrho*expu_m + expu_l*dexpu_mdrho;
3356                                 
3357                                 dexpu_ldtheta = -expu_l*u_l*du_ldtheta;
3358                                 dexpu_mdtheta = -expu_m*u_m*du_mdtheta;
3359                                 dalmdtheta = dexpu_ldtheta*expu_m + expu_l*dexpu_mdtheta;
3360                                 
3361                                 dexpu_ldphi = -expu_l*u_l*du_ldphi;
3362                                 dexpu_mdphi = -expu_m*u_m*du_mdphi;
3363                                 dalmdphi = dexpu_ldphi*expu_m + expu_l*dexpu_mdphi;
3364                                 
3365                                 xx += ac*Flambda*Fdelta*alm*sin(phase);
3366                                 dxxdrho += dacdrho*Flambda*Fdelta*alm*sin(phase) + ac*dFlambdadrho*Fdelta*alm*sin(phase) + ac*Flambda*dFdeltadrho*alm*sin(phase) + ac*Flambda*Fdelta*dalmdrho*sin(phase) + ac*Flambda*Fdelta*alm*cos(phase)*dphasedrho;
3367                                 dxxdtheta += dacdtheta*Flambda*Fdelta*alm*sin(phase) + ac*dFlambdadtheta*Fdelta*alm*sin(phase) + ac*Flambda*dFdeltadtheta*alm*sin(phase) + ac*Flambda*Fdelta*dalmdtheta*sin(phase) + ac*Flambda*Fdelta*alm*cos(phase)*dphasedtheta;
3368                                 dxxdphi += dacdphi*Flambda*Fdelta*alm*sin(phase) + ac*dFlambdadphi*Fdelta*alm*sin(phase) + ac*Flambda*dFdeltadphi*alm*sin(phase) + ac*Flambda*Fdelta*dalmdphi*sin(phase) + ac*Flambda*Fdelta*alm*cos(phase)*dphasedphi;
3369                                 
3370                             }
3371                         }
3372                         
3373                         /* convolution to avoid negative density values. No restriction on positive values, ht(x) = x */
3374                         
3375                         halftanh(xx,&ht,&dht,&d2ht);
3376                         
3377                         nefsne += ht;
3378                         dnefsnedrho += dht*dxxdrho;
3379                         dnefsnedtheta += dht*dxxdtheta;
3380                         dnefsnedphi += dht*dxxdphi;
3381                     }
3382                 }
3383             }
3384             
3385             if (fluctparam.B_nmodel[0] > 0) {/* Magnetic field fluctuations or ripple */
3386                 
3387                 cta = cos(Y[1])*raymagnetic.calpha[0] + sin(Y[1])*raymagnetic.salpha[0];
3388                 sta = -cos(Y[1])*raymagnetic.salpha[0] + sin(Y[1])*raymagnetic.calpha[0];
3389                 
3390                 dctadrho = cos(Y[1])*raymagnetic.dcalphadY[0] + sin(Y[1])*raymagnetic.dsalphadY[0];
3391                 dctadtheta = cos(Y[1])*raymagnetic.dcalphadY[1] + sin(Y[1])*raymagnetic.dsalphadY[1] - sta;
3392                 dctadphi = cos(Y[1])*raymagnetic.dcalphadY[2]*equilparam.Rp[0] + sin(Y[1])*raymagnetic.dsalphadY[2]*equilparam.Rp[0];
3393                 
3394                 dstadrho = - cos(Y[1])*raymagnetic.dsalphadY[0] + sin(Y[1])*raymagnetic.dcalphadY[0];
3395                 dstadtheta = - cos(Y[1])*raymagnetic.dsalphadY[1] + sin(Y[1])*raymagnetic.dcalphadY[1] + cta;
3396                 dstadphi = - cos(Y[1])*raymagnetic.dsalphadY[2]*equilparam.Rp[0] + sin(Y[1])*raymagnetic.dcalphadY[2]*equilparam.Rp[0];
3397                 
3398                 for (imodel=0; imodel < fluctparam.B_nmodel[0]; imodel++) {
3399                     
3400                     if (fluctparam.B_model[imodel][0] == 1) {/* Gaussian fluctuation spectrum */
3401                         
3402                         /*
3403                          for (ikperp=0; ikperp < fluctparam.B_nkperp[imodel][0]; ikperp++) {
3404                          
3405                          phaseB = gphase*fluctparam.B_kperp[imodel][ikperp] + fluctparam.B_phase[imodel][ikperp];
3406                          dphaseBdrho = dgphasedrho*fluctparam.B_kperp[imodel][ikperp];
3407                          dphaseBdtheta = dgphasedtheta*fluctparam.B_kperp[imodel][ikperp];
3408                          dphaseBdphi = dgphasedphi*fluctparam.B_kperp[imodel][ikperp];
3409                          
3410                          ff0 = sqrt(2*(fluctparam.B_kperp[imodel][1]-fluctparam.B_kperp[imodel][0])/sqrt(2*PI));
3411                          
3412                          ff1 = exp(-pow(fluctparam.B_kperp[imodel][ikperp]-krB[imodel],2)/pow(kcB[imodel],2)/4);
3413                          dff1drho = ff1*(fluctparam.B_kperp[imodel][ikperp]-krB[imodel])*((fluctparam.B_kperp[imodel][ikperp]-krB[imodel])*dkcBdrho[imodel] + kcB[imodel]*dkrBdrho[imodel])/2/pow(kcB[imodel],3);
3414                          dff1dtheta = ff1*(fluctparam.B_kperp[imodel][ikperp]-krB[imodel])*((fluctparam.B_kperp[imodel][ikperp]-krB[imodel])*dkcBdtheta[imodel] + kcB[imodel]*dkrBdtheta[imodel])/2/pow(kcB[imodel],3);
3415                          
3416                          ff2 = 1./sqrt(kcB[imodel]);
3417                          dff2drho = -dkcBdrho[imodel]/sqrt(kcB[imodel])/kcB[imodel]/2.0;
3418                          dff2dtheta = -dkcBdtheta[imodel]/sqrt(kcB[imodel])/kcB[imodel]/2.0;
3419                          
3420                          BxfsB = ff0*sfBx[imodel]*ff1*ff2*cos(phaseB);
3421                          dBxfsBdrho = ff0*(dsfBxdrho[imodel]*cos(phaseB)*ff1*ff2 - sfBx[imodel]*sin(phaseB)*dphaseBdrho*ff1*ff2 + sfBx[imodel]*cos(phaseB)*dff1drho*ff2 + sfBx[imodel]*cos(phaseB)*ff1*dff2drho);
3422                          dBxfsBdtheta = ff0*(dsfBxdtheta[imodel]*cos(phaseB)*ff1*ff2 - sfBx[imodel]*sin(phaseB)*dphaseBdtheta*ff1*ff2 + sfBx[imodel]*cos(phaseB)*dff1dtheta*ff2 + sfBx[imodel]*cos(phaseB)*ff1*dff2dtheta);
3423                          dBxfsBdphi = - ff0*sfBx[imodel]*sin(phaseB)*dphaseBdphi*ff1*ff2;
3424                          
3425                          ByfsB = ff0*sfBy[imodel]*ff1*ff2*cos(phaseB);
3426                          dByfsBdrho = ff0*(dsfBydrho[imodel]*cos(phaseB)*ff1*ff2 - sfBy[imodel]*sin(phaseB)*dphaseBdrho*ff1*ff2 + sfBy[imodel]*cos(phaseB)*dff1drho*ff2 + sfBy[imodel]*cos(phaseB)*ff1*dff2drho);
3427                          dByfsBdtheta = ff0*(dsfBydtheta[imodel]*cos(phaseB)*ff1*ff2 - sfBy[imodel]*sin(phaseB)*dphaseBdtheta*ff1*ff2 + sfBy[imodel]*cos(phaseB)*dff1dtheta*ff2 + sfBy[imodel]*cos(phaseB)*ff1*dff2dtheta);
3428                          dByfsBdphi = - ff0*sfBy[imodel]*sin(phaseB)*dphaseBdphi*ff1*ff2;
3429                          
3430                          BzfsB = ff0*sfBz[imodel]*ff1*ff2*cos(phaseB);
3431                          dBzfsBdrho = ff0*(dsfBzdrho[imodel]*cos(phaseB)*ff1*ff2 - sfBz[imodel]*sin(phaseB)*dphaseBdrho*ff1*ff2 + sfBz[imodel]*cos(phaseB)*dff1drho*ff2 + sfBz[imodel]*cos(phaseB)*ff1*dff2drho);
3432                          dBzfsBdtheta = ff0*(dsfBzdtheta[imodel]*cos(phaseB)*ff1*ff2 - sfBz[imodel]*sin(phaseB)*dphaseBdtheta*ff1*ff2 + sfBz[imodel]*cos(phaseB)*dff1dtheta*ff2 + sfBz[imodel]*cos(phaseB)*ff1*dff2dtheta);
3433                          dBzfsBdphi = - ff0*sfBz[imodel]*sin(phaseB)*dphaseBdphi*ff1*ff2;
3434                          */
3435                         
3436                         /* mexPrintf("Y[0],Y[1],Y[2],Bfx[0],dBxfdY[0],dBxfdY[1],dBxfdY[2]:%25.15g,%25.15g,%25.15g,%25.15g,%25.15g,%25.15g,%25.15g\n",Y[0],Y[1],Y[2],Bxf,dBxfdrho,dBxfdtheta,dBxfdphi);*/
3437                         /* mexPrintf("Y[0],Y[1],Y[2],Bfy[0],dByfdY[0],dByfdY[1],dByfdY[2]:%25.15g,%25.15g,%25.15g,%25.15g,%25.15g,%25.15g,%25.15g\n",Y[0],Y[1],Y[2],Byf,dByfdrho,dByfdtheta,dByfdphi);*/
3438                         /* mexPrintf("Y[0],Y[1],Y[2],Bfz[0],dBzfdY[0],dBzfdY[1],dBzfdY[2]:%25.15g,%25.15g,%25.15g,%25.15g,%25.15g,%25.15g,%25.15g\n",Y[0],Y[1],Y[2],Bzf,dBzfdrho,dBzfdtheta,dBzfdphi);
3439                          
3440                          }
3441                          */
3442                     }
3443                     
3444                     if (fluctparam.B_model[imodel][0] == 0) {/* Magnetic ripple modulation */
3445                         
3446                         ppvald_2D(rayfluctuations.B_sfx_fit[imodel],rayparam.dS[0],Y[0],Y[1],&sfBx[imodel],&dsfBxdrho[imodel],&dsfBxdtheta[imodel],&d2sfBxdtheta2[imodel],&d2sfBxdthetadrho[imodel]);
3447                         ppvald_2D(rayfluctuations.B_sfy_fit[imodel],rayparam.dS[0],Y[0],Y[1],&sfBy[imodel],&dsfBydrho[imodel],&dsfBydtheta[imodel],&d2sfBydtheta2[imodel],&d2sfBydthetadrho[imodel]);
3448                         ppvald_2D(rayfluctuations.B_sfz_fit[imodel],rayparam.dS[0],Y[0],Y[1],&sfBz[imodel],&dsfBzdrho[imodel],&dsfBzdtheta[imodel],&d2sfBzdtheta2[imodel],&d2sfBzdthetadrho[imodel]);
3449                         
3450                         phaseB = fluctparam.B_nmax[imodel][0]*Y[2]/equilparam.Rp[0];
3451                         dphaseBdrho = 0.0;
3452                         dphaseBdtheta = 0.0;
3453                         dphaseBdphi = fluctparam.B_nmax[imodel][0];
3454                         
3455                         BxfsB = sfBx[imodel]*sin(phaseB);
3456                         dBxfsBdrho = dsfBxdrho[imodel]*sin(phaseB);
3457                         dBxfsBdtheta = dsfBxdtheta[imodel]*sin(phaseB);
3458                         dBxfsBdphi = sfBx[imodel]*cos(phaseB)*dphaseBdphi;
3459                         
3460                         ByfsB = sfBy[imodel]*sin(phaseB);
3461                         dByfsBdrho = dsfBydrho[imodel]*sin(phaseB);
3462                         dByfsBdtheta = dsfBydtheta[imodel]*sin(phaseB);
3463                         dByfsBdphi = sfBy[imodel]*cos(phaseB)*dphaseBdphi;
3464                         
3465                         BzfsB = sfBz[imodel]*cos(phaseB);
3466                         dBzfsBdrho = dsfBzdrho[imodel]*cos(phaseB);
3467                         dBzfsBdtheta = dsfBzdtheta[imodel]*cos(phaseB);
3468                         dBzfsBdphi = -sfBz[imodel]*sin(phaseB)*dphaseBdphi;
3469                         
3470                         /* add ripple effect on densities and temperatures (electron and ion) */
3471                         
3472                         Brho0 = raymagnetic.B[0]*(cta*sfBx[imodel] + sta*sfBy[imodel]);
3473                         dBrho0drho = raymagnetic.dBdY[0]*(cta*sfBx[imodel] + sta*sfBy[imodel]) + raymagnetic.B[0]*(dctadrho*sfBx[imodel] + cta*dsfBxdrho[imodel] + dstadrho*sfBy[imodel] + sta*dsfBydrho[imodel]);
3474                         dBrho0dtheta = raymagnetic.dBdY[1]*(cta*sfBx[imodel] + sta*sfBy[imodel]) + raymagnetic.B[0]*(dctadtheta*sfBx[imodel] + cta*dsfBxdtheta[imodel] + dstadtheta*sfBy[imodel] + sta*dsfBydtheta[imodel]);
3475                         
3476                         lambda = Brho0*raymagnetic.gradrhon[0]*equilparam.Rp[0]/Bz/fluctparam.B_nmax[imodel][0]/equilparam.ap[0];
3477                         dlambdadrho = (dBrho0drho*raymagnetic.gradrhon[0] + Brho0*raymagnetic.dgradrhondY[0] - Brho0*raymagnetic.gradrhon[0]*dBzdrho/Bz)*equilparam.Rp[0]/Bz/fluctparam.B_nmax[imodel][0]/equilparam.ap[0];
3478                         dlambdadtheta = (dBrho0dtheta*raymagnetic.gradrhon[0] + Brho0*raymagnetic.dgradrhondY[1] - Brho0*raymagnetic.gradrhon[0]*dBzdtheta/Bz)*equilparam.Rp[0]/Bz/fluctparam.B_nmax[imodel][0]/equilparam.ap[0];
3479                         
3480                         rhorip = Y[0] + lambda*cos(phaseB);
3481                         drhodrhorip = 1.0 + dlambdadrho*cos(phaseB);
3482                         drhodthetarip = dlambdadtheta*cos(phaseB);
3483                         drhodphirip = - dphaseBdphi*lambda*sin(phaseB);
3484                         
3485                         /* Electron density */
3486                         
3487                         ppvald_1D(rayequil.ne_fit,rayparam.dS[0],1.0,&val,&dvaldrho,&d2valdrho2); /*value at the separatrix */
3488                         ne_sep = val;
3489                         dnedrho_sep = dvaldrho;
3490                         
3491                         if (dnedrho_sep == 0) {
3492                             rho_neeq0 = 1.0e20;
3493                         } else {
3494                             rho_neeq0 = - ne_sep/dnedrho_sep + 1.0;
3495                         }
3496                         
3497                         if (rhorip <= 1.0) {
3498                             ppvald_1D(rayequil.ne_fit,rayparam.dS[0],rhorip,&val,&dvaldrho,&d2valdrho2);
3499                             nerip = val;
3500                             dnedrhorip = dvaldrho*drhodrhorip;
3501                             dnedthetarip = dvaldrho*drhodthetarip;
3502                             dnedphirip = dvaldrho*drhodphirip;
3503                         }
3504                         
3505                         if ((rhorip > 1.0) & (rhorip <= rho_neeq0)) {
3506                             nerip = ne_sep + dnedrho_sep*(rhorip - 1.0); /* SOL */
3507                             dnedrhorip = dnedrho_sep*drhodrhorip;
3508                             dnedthetarip = dnedrho_sep*drhodthetarip;
3509                             dnedphirip = dnedrho_sep*drhodphirip;
3510                         }
3511                         
3512                         if (rhorip > rho_neeq0) {
3513                             nerip = 0.0; /*vacuum */
3514                             dnedrhorip = 0.0;
3515                             dnedthetarip = 0.0;
3516                             dnedphirip = 0.0;
3517                         }
3518                         
3519                         ne_tilde = nerip - rayprofiles.ne[0];
3520                         dnedrho_tilde = dnedrhorip - rayprofiles.dnedY[0];
3521                         dnedtheta_tilde = dnedthetarip;
3522                         dnedphi_tilde = dnedphirip;
3523                         
3524                         ner_tilde = ne_tilde/rayprofiles.ne[0];
3525                         dnerdrho_tilde = dnedrho_tilde/rayprofiles.ne[0] - ne_tilde*rayprofiles.dnedY[0]/rayprofiles.ne[0]/rayprofiles.ne[0];
3526                         dnerdtheta_tilde = dnedtheta_tilde/rayprofiles.ne[0];
3527                         dnerdphi_tilde = dnedphi_tilde/rayprofiles.ne[0];
3528                         
3529                         /*     mexPrintf("rho,theta,phi,rhorip,rho_neeq0,ne,dnedrho,nerip,dnedrhorip,dnedthetarip,dnedphirip,ner_tilde,dnerdrho_tilde,dnerdtheta_tilde,dnerdphi_tilde:%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g\n",Y[0],Y[1],Y[2],rhorip,rho_neeq0,rayprofiles.ne[0],rayprofiles.dnedY[0],nerip,dnedrhorip,dnedthetarip,dnedphirip,ner_tilde,dnerdrho_tilde,dnerdtheta_tilde,dnerdphi_tilde);
3530                          mexPrintf("Brho0,raymagnetic.gradrhon[0],equilparam.Rp[0],BPHI,fluctparam.B_kperp[imodel][ikperp],lambda:%g,%g,%g,%g,%g,%g\n",Brho0,raymagnetic.gradrhon[0],equilparam.Rp[0],BPHI,fluctparam.B_kperp[imodel][ikperp],lambda);
3531                          */
3532                         nefsne += ner_tilde;/* add the relative contribution of magnetic ripple to the density perturbation */
3533                         dnefsnedrho += dnerdrho_tilde;
3534                         dnefsnedtheta += dnerdtheta_tilde;
3535                         dnefsnedphi += dnerdphi_tilde;
3536                         
3537                         /* Electron temperature */
3538                         
3539                         ppvald_1D(rayequil.Te_fit,rayparam.dS[0],1.0,&val,&dvaldrho,&d2valdrho2); /*value at the separatrix */
3540                         Te_sep = val;
3541                         dTedrho_sep = dvaldrho;
3542                         
3543                         if (dTedrho_sep == 0) {
3544                             rho_Teeq0 = 1.0e20;
3545                         } else {
3546                             rho_Teeq0 = - Te_sep/dTedrho_sep + 1.0;
3547                         }
3548                         
3549                         if (rhorip <= 1.0) {
3550                             ppvald_1D(rayequil.Te_fit,rayparam.dS[0],rhorip,&val,&dvaldrho,&d2valdrho2);
3551                             Terip = val;
3552                             dTedrhorip = dvaldrho*drhodrhorip;
3553                             dTedthetarip = dvaldrho*drhodthetarip;
3554                             dTedphirip = dvaldrho*drhodphirip;
3555                         }
3556                         
3557                         if ((rhorip > 1.0) & (rhorip <= rho_Teeq0)) {
3558                             Terip = Te_sep + dTedrho_sep*(rhorip - 1.0); /* SOL */
3559                             dTedrhorip = dTedrho_sep*drhodrhorip;
3560                             dTedthetarip = dTedrho_sep*drhodthetarip;
3561                             dTedphirip = dTedrho_sep*drhodphirip;
3562                         }
3563                         
3564                         if (rhorip > rho_Teeq0) {
3565                             Terip = 0.0; /*vacuum */
3566                             dTedrhorip = 0.0;
3567                             dTedthetarip = 0.0;
3568                             dTedphirip = 0.0;
3569                         }
3570                         
3571                         Te_tilde = Terip - rayprofiles.Te[0];
3572                         dTedrho_tilde = dTedrhorip - rayprofiles.dTedY[0];
3573                         dTedtheta_tilde = dTedthetarip;
3574                         dTedphi_tilde = dTedphirip;
3575                         
3576                         Ter_tilde = Te_tilde/rayprofiles.Te[0];
3577                         dTerdrho_tilde = dTedrho_tilde/rayprofiles.Te[0] - Te_tilde*rayprofiles.dTedY[0]/rayprofiles.Te[0]/rayprofiles.Te[0];
3578                         dTerdtheta_tilde = dTedtheta_tilde/rayprofiles.Te[0];
3579                         dTerdphi_tilde = dTedphi_tilde/rayprofiles.Te[0];
3580                         
3581                         TefsTe += Ter_tilde;/* add the relative contribution of magnetic ripple to the electron temperature perturbation */
3582                         dTefsTedrho += dTerdrho_tilde;
3583                         dTefsTedtheta += dTerdtheta_tilde;
3584                         dTefsTedphi += dTerdphi_tilde;
3585                         
3586                         /* ion densities */
3587                         
3588                         for (is=0;is/*value at the separatrix */
3591                             zni_sep[is] = zval[is];
3592                             dznidrho_sep[is] = dzvaldrho[is];
3593                             
3594                             if (dznidrho_sep[is] == 0) {
3595                                 rho_znieq0[is] = 1.0e20;
3596                             } else {
3597                                 rho_znieq0[is] = - zni_sep[is]/dznidrho_sep[is] + 1.0;
3598                             }
3599                             
3600                             if (rhorip <= 1.0) {
3601                                 ppvald_1D(rayequil.zni_fit,rayparam.dS[0],rhorip,zval,dzvaldrho,d2zvaldrho2);
3602                                 znirip[is] = zval[is];
3603                                 dznidrhorip[is] = dzvaldrho[is]*drhodrhorip;
3604                                 dznidthetarip[is] = dzvaldrho[is]*drhodthetarip;
3605                                 dznidphirip[is] = dzvaldrho[is]*drhodphirip;
3606                             }
3607                             
3608                             if ((rhorip > 1.0) & (rhorip <= rho_znieq0[is])) {
3609                                 znirip[is] = zni_sep[is] + dznidrho_sep[is]*(rhorip - 1.0); /* SOL */
3610                                 dznidrhorip[is] = dznidrho_sep[is]*drhodrhorip;
3611                                 dznidthetarip[is] = dznidrho_sep[is]*drhodthetarip;
3612                                 dznidphirip[is] = dznidrho_sep[is]*drhodphirip;
3613                             }
3614                             
3615                             if (rhorip > rho_znieq0[is]) {
3616                                 znirip[is] = 0.0; /*vacuum */
3617                                 dznidrhorip[is] = 0.0;
3618                                 dznidthetarip[is] = 0.0;
3619                                 dznidphirip[is] = 0.0;
3620                             }
3621                             
3622                             zni_tilde[is] = znirip[is] - rayprofiles.zni[is];
3623                             dznidrho_tilde[is] = dznidrhorip[is] - rayprofiles.dznidY[is][0];
3624                             dznidtheta_tilde[is] = dznidthetarip[is];
3625                             dznidphi_tilde[is] = dznidphirip[is];
3626                             
3627                             /*mexPrintf("is,ns,rayprofiles.zni[is],%d,%d,%g\n",is,equilparam.ns[0],rayprofiles.zni[is]);*/
3628                             
3629                             if (rayprofiles.zni[is] > 0.0) {
3630                                 
3631                                 /* mexPrintf("is valide,%d\n",is);*/
3632                                 
3633                                 znir_tilde[is] = zni_tilde[is]/rayprofiles.zni[is];
3634                                 dznirdrho_tilde[is] = dznidrho_tilde[is]/rayprofiles.zni[is] - zni_tilde[is]*rayprofiles.dznidY[is][0]/rayprofiles.zni[is]/rayprofiles.zni[is];
3635                                 dznirdtheta_tilde[is] = dznidtheta_tilde[is]/rayprofiles.zni[is];
3636                                 dznirdphi_tilde[is] = dznidphi_tilde[is]/rayprofiles.zni[is];
3637                                 
3638                                 znifszni[is] += znir_tilde[is];/* add the relative contribution of magnetic ripple to the ion densities perturbations */
3639                                 dznifsznidrho[is] += dznirdrho_tilde[is];
3640                                 dznifsznidtheta[is] += dznirdtheta_tilde[is];
3641                                 dznifsznidphi[is] += dznirdphi_tilde[is];
3642                             }
3643                             
3644                             /* ion temperatures */
3645                             
3646                             ppvald_1D(rayequil.zTi_fit,rayparam.dS[0],1.0,zval,dzvaldrho,d2zvaldrho2); /*value at the separatrix */
3647                             zTi_sep[is] = zval[is];
3648                             dzTidrho_sep[is] = dzvaldrho[is];
3649                             
3650                             if (dzTidrho_sep[is] == 0) {
3651                                 rho_zTieq0[is] = 1.0e20;
3652                             } else {
3653                                 rho_zTieq0[is] = - zTi_sep[is]/dzTidrho_sep[is] + 1.0;
3654                             }
3655                             
3656                             if (rhorip <= 1.0) {
3657                                 ppvald_1D(rayequil.zTi_fit,rayparam.dS[0],rhorip,zval,dzvaldrho,d2zvaldrho2);
3658                                 zTirip[is] = zval[is];
3659                                 dzTidrhorip[is] = dzvaldrho[is]*drhodrhorip;
3660                                 dzTidthetarip[is] = dzvaldrho[is]*drhodthetarip;
3661                                 dzTidphirip[is] = dzvaldrho[is]*drhodphirip;
3662                             }
3663                             
3664                             if ((rhorip > 1.0) & (rhorip <= rho_zTieq0[is])) {
3665                                 zTirip[is] = zTi_sep[is] + dzTidrho_sep[is]*(rhorip - 1.0); /* SOL */
3666                                 dzTidrhorip[is] = dzTidrho_sep[is]*drhodrhorip;
3667                                 dzTidthetarip[is] = dzTidrho_sep[is]*drhodthetarip;
3668                                 dzTidphirip[is] = dzTidrho_sep[is]*drhodphirip;
3669                             }
3670                             
3671                             if (rhorip > rho_zTieq0[is]) {
3672                                 zTirip[is] = 0.0; /*vacuum */
3673                                 dzTidrhorip[is] = 0.0;
3674                                 dzTidthetarip[is] = 0.0;
3675                                 dzTidphirip[is] = 0.0;
3676                             }
3677                             
3678                             zTi_tilde[is] = zTirip[is] - rayprofiles.zTi[is];
3679                             dzTidrho_tilde[is] = dzTidrhorip[is] - rayprofiles.dzTidY[is][0];
3680                             dzTidtheta_tilde[is] = dzTidthetarip[is];
3681                             dzTidphi_tilde[is] = dzTidphirip[is];
3682                             
3683                             zTir_tilde[is] = zTi_tilde[is]/rayprofiles.zTi[is];
3684                             dzTirdrho_tilde[is] = dzTidrho_tilde[is]/rayprofiles.zTi[is] - zTi_tilde[is]*rayprofiles.dzTidY[is][0]/rayprofiles.zTi[is]/rayprofiles.zTi[is];
3685                             dzTirdtheta_tilde[is] = dzTidtheta_tilde[is]/rayprofiles.zTi[is];
3686                             dzTirdphi_tilde[is] = dzTidphi_tilde[is]/rayprofiles.zTi[is];
3687                             
3688                             zTifszTi[is] += zTir_tilde[is];/* add the relative contribution of magnetic ripple to the ion temperatures perturbations */
3689                             dzTifszTidrho[is] += dzTirdrho_tilde[is];
3690                             dzTifszTidtheta[is] += dzTirdtheta_tilde[is];
3691                             dzTifszTidphi[is] += dzTirdphi_tilde[is];
3692                         }
3693                         
3694                     }
3695                     
3696                     BrhofsB += cta*BxfsB + sta*ByfsB;
3697                     dBrhofsBdrho += dctadrho*BxfsB + cta*dBxfsBdrho + dstadrho*ByfsB + sta*dByfsBdrho;
3698                     dBrhofsBdtheta += dctadtheta*BxfsB + cta*dBxfsBdtheta + dstadtheta*ByfsB + sta*dByfsBdtheta;
3699                     dBrhofsBdphi += dctadphi*BxfsB + cta*dBxfsBdphi + dstadphi*ByfsB + sta*dByfsBdphi;
3700                     
3701                     BsfsB += cta*ByfsB - sta*BxfsB;
3702                     dBsfsBdrho += dctadrho*ByfsB + cta*dByfsBdrho - dstadrho*BxfsB - sta*dBxfsBdrho;
3703                     dBsfsBdtheta += dctadtheta*ByfsB + cta*dByfsBdtheta - dstadtheta*BxfsB - sta*dBxfsBdtheta;
3704                     dBsfsBdphi += dctadphi*ByfsB + cta*dByfsBdphi - dstadphi*BxfsB - sta*dBxfsBdphi;
3705                     
3706                     BphifsB += BzfsB;
3707                     dBphifsBdrho += dBzfsBdrho;
3708                     dBphifsBdtheta += dBzfsBdtheta;
3709                     dBphifsBdphi += dBzfsBdphi;
3710                     
3711                 }
3712             }
3713             
3714             /* Calculation of the perturbed magnetic field and its derivatives */
3715             
3716             Brho = (raymagnetic.Brhon[0] + BrhofsB)*raymagnetic.B[0];
3717             Bs = (raymagnetic.Bsn[0] + BsfsB)*raymagnetic.B[0];
3718             Bphi = (raymagnetic.Bzn[0] + BphifsB)*raymagnetic.B[0];
3719             B = sqrt(Brho*Brho + Bs*Bs + Bphi*Bphi);
3720             
3721             Brhon = Brho/B;/* Normalization to the new local value of B */
3722             Bsn = Bs/B;
3723             Bphin = Bphi/B;
3724             
3725             dBrhodrho = (raymagnetic.dBrhondY[0] + dBrhofsBdrho)*raymagnetic.B[0] + (raymagnetic.Brhon[0] + BrhofsB)*raymagnetic.dBdY[0];
3726             dBrhodtheta = (raymagnetic.dBrhondY[1] + dBrhofsBdtheta)*raymagnetic.B[0] + (raymagnetic.Brhon[0] + BrhofsB)*raymagnetic.dBdY[1];
3727             dBrhodphi = (raymagnetic.dBrhondY[2]*equilparam.Rp[0] + dBrhofsBdphi)*raymagnetic.B[0] + (raymagnetic.Brhon[0] + BrhofsB)*raymagnetic.dBdY[2]*equilparam.Rp[0];
3728             
3729             dBsdrho = (raymagnetic.dBsndY[0] + dBsfsBdrho)*raymagnetic.B[0] + (raymagnetic.Bsn[0] + BsfsB)*raymagnetic.dBdY[0];
3730             dBsdtheta = (raymagnetic.dBsndY[1] + dBsfsBdtheta)*raymagnetic.B[0] + (raymagnetic.Bsn[0] + BsfsB)*raymagnetic.dBdY[1];
3731             dBsdphi = (raymagnetic.dBsndY[2]*equilparam.Rp[0] + dBsfsBdphi)*raymagnetic.B[0] + (raymagnetic.Bsn[0] + BsfsB)*raymagnetic.dBdY[2]*equilparam.Rp[0];
3732             
3733             dBphidrho = (raymagnetic.dBzndY[0] + dBphifsBdrho)*raymagnetic.B[0] + (raymagnetic.Bzn[0] + BphifsB)*raymagnetic.dBdY[0];
3734             dBphidtheta = (raymagnetic.dBzndY[1] + dBphifsBdtheta)*raymagnetic.B[0] + (raymagnetic.Bzn[0] + BphifsB)*raymagnetic.dBdY[1];
3735             dBphidphi = (raymagnetic.dBzndY[2]*equilparam.Rp[0] + dBphifsBdphi)*raymagnetic.B[0] + (raymagnetic.Bzn[0] + BphifsB)*raymagnetic.dBdY[2]*equilparam.Rp[0];
3736             
3737             dBdrho = Brhon*dBrhodrho + Bsn*dBsdrho + Bphin*dBphidrho;
3738             dBdtheta = Brhon*dBrhodtheta + Bsn*dBsdtheta + Bphin*dBphidtheta;
3739             dBdphi = Brhon*dBrhodphi + Bsn*dBsdphi + Bphin*dBphidphi;
3740             
3741             raymagnetic.Brhon[0] = Brhon;
3742             raymagnetic.dBrhondY[0] = (dBrhodrho - Brhon*dBdrho)/B;
3743             raymagnetic.dBrhondY[1] = (dBrhodtheta - Brhon*dBdtheta)/B;
3744             raymagnetic.dBrhondY[2] = (dBrhodphi - Brhon*dBdphi)/B/equilparam.Rp[0];
3745             
3746             raymagnetic.Bsn[0] = Bsn;
3747             raymagnetic.dBsndY[0] = (dBsdrho - Bsn*dBdrho)/B;
3748             raymagnetic.dBsndY[1] = (dBsdtheta - Bsn*dBdtheta)/B;
3749             raymagnetic.dBsndY[2] = (dBsdphi - Bsn*dBdphi)/B/equilparam.Rp[0];
3750             
3751             raymagnetic.Bzn[0] = Bphin;
3752             raymagnetic.dBzndY[0] = (dBphidrho - Bphin*dBdrho)/B;
3753             raymagnetic.dBzndY[1] = (dBphidtheta - Bphin*dBdtheta)/B;
3754             raymagnetic.dBzndY[2] = (dBphidphi - Bphin*dBdphi)/B/equilparam.Rp[0];
3755             
3756             raymagnetic.B[0] = B;
3757             raymagnetic.dBdY[0] = dBdrho;
3758             raymagnetic.dBdY[1] = dBdtheta;
3759             raymagnetic.dBdY[2] = dBdphi/equilparam.Rp[0];
3760             
3761             raymagnetic.rhorip[0] = rhorip;
3762             raymagnetic.drhoripdY[0] = drhodrhorip;
3763             raymagnetic.drhoripdY[1] = drhodthetarip;
3764             raymagnetic.drhoripdY[2] = drhodphirip/equilparam.Rp[0];
3765             
3766             /* Calculation of the perturbed electron density and its derivatives */
3767             
3768             /* mexPrintf("rho,theta,phi,ner[0],dnerdY[0],dnerdY[1],dnerdY[2]:%25.15g,%25.15g,%25.15g,%25.15g,%25.15g,%25.15g,%25.15g\n",Y[0],Y[1],Y[2],nefsne,dnefsnedrho,dnefsnedtheta,dnefsnedphi);*/
3769             
3770             rayprofiles.dnedY[0] = rayprofiles.dnedY[0]*(1.0 + nefsne) + rayprofiles.ne[0]*dnefsnedrho;
3771             rayprofiles.dnedY[1] = rayprofiles.dnedY[1]*(1.0 + nefsne) + rayprofiles.ne[0]*dnefsnedtheta;
3772             rayprofiles.dnedY[2] = rayprofiles.dnedY[2]*(1.0 + nefsne) + rayprofiles.ne[0]*dnefsnedphi/equilparam.Rp[0];
3773             rayprofiles.ne[0] = rayprofiles.ne[0]*(1.0 + nefsne);
3774             
3775             /* Calculation of the perturbed electron temperature and it's derivatives */
3776             
3777             rayprofiles.dTedY[0] = rayprofiles.dTedY[0]*(1.0 + TefsTe) + rayprofiles.Te[0]*dTefsTedrho;
3778             rayprofiles.dTedY[1] = rayprofiles.dTedY[1]*(1.0 + TefsTe) + rayprofiles.Te[0]*dTefsTedtheta;
3779             rayprofiles.dTedY[2] = rayprofiles.dTedY[2]*(1.0 + TefsTe) + rayprofiles.Te[0]*dTefsTedphi/equilparam.Rp[0];
3780             rayprofiles.Te[0] = rayprofiles.Te[0]*(1.0 + TefsTe);
3781             
3782             for (is=0;is/* Calculation of the perturbed ion densities and their derivatives */
3785                 
3786                 rayprofiles.dznidY[is][0] = rayprofiles.dznidY[is][0]*(1.0 + znifszni[is]) + rayprofiles.zni[is]*dznifsznidrho[is];
3787                 rayprofiles.dznidY[is][1] = rayprofiles.dznidY[is][1]*(1.0 + znifszni[is]) + rayprofiles.zni[is]*dznifsznidtheta[is];
3788                 rayprofiles.dznidY[is][2] = rayprofiles.dznidY[is][2]*(1.0 + znifszni[is]) + rayprofiles.zni[is]*dznifsznidphi[is]/equilparam.Rp[0];
3789                 rayprofiles.zni[is] = rayprofiles.zni[is]*(1.0 + znifszni[is]);
3790                 
3791                 /* Calculation of the perturbed ion temperatures and their derivatives */
3792                 
3793                 rayprofiles.dzTidY[is][0] = rayprofiles.dzTidY[is][0]*(1.0 + zTifszTi[is]) + rayprofiles.zTi[is]*dzTifszTidrho[is];
3794                 rayprofiles.dzTidY[is][1] = rayprofiles.dzTidY[is][1]*(1.0 + zTifszTi[is]) + rayprofiles.zTi[is]*dzTifszTidtheta[is];
3795                 rayprofiles.dzTidY[is][2] = rayprofiles.dzTidY[is][2]*(1.0 + zTifszTi[is]) + rayprofiles.zTi[is]*dzTifszTidphi[is]/equilparam.Rp[0];
3796                 rayprofiles.zTi[is] = rayprofiles.zTi[is]*(1.0 + zTifszTi[is]);
3797                 
3798             }
3799             
3800             if(flag_metric == 2)/*Reset the equilibrium to the cartesian metric*/
3801             {
3802                 Y[0] = xbis;
3803                 Y[1] = ybis;
3804                 
3805                 save = raymagnetic.drndY[0];
3806                 raymagnetic.drndY[0] = drhodx*raymagnetic.drndY[0] + dthetadx*raymagnetic.drndY[1];
3807                 raymagnetic.drndY[1] = drhody*save + dthetady*raymagnetic.drndY[1];
3808                 
3809                 save = raymagnetic.dxndY[0];
3810                 raymagnetic.dxndY[0] = drhodx*raymagnetic.dxndY[0] + dthetadx*raymagnetic.dxndY[1];
3811                 raymagnetic.dxndY[1] = drhody*save + dthetady*raymagnetic.dxndY[1];
3812                 
3813                 save = raymagnetic.dyndY[0];
3814                 raymagnetic.dyndY[0] = drhodx*raymagnetic.dyndY[0] + dthetadx*raymagnetic.dyndY[1];
3815                 raymagnetic.dyndY[1] = drhody*save + dthetady*raymagnetic.dyndY[1];
3816                 
3817                 save = raymagnetic.dBrhondY[0];
3818                 raymagnetic.dBrhondY[0] = drhodx*raymagnetic.dBrhondY[0] + dthetadx*raymagnetic.dBrhondY[1];
3819                 raymagnetic.dBrhondY[1] = drhody*save + dthetady*raymagnetic.dBrhondY[1];
3820                 
3821                 save = raymagnetic.dBsndY[0];
3822                 raymagnetic.dBsndY[0] = drhodx*raymagnetic.dBsndY[0] + dthetadx*raymagnetic.dBsndY[1];
3823                 raymagnetic.dBsndY[1] = drhody*save + dthetady*raymagnetic.dBsndY[1];
3824                 
3825                 save = raymagnetic.dBzndY[0];
3826                 raymagnetic.dBzndY[0] = drhodx*raymagnetic.dBzndY[0] + dthetadx*raymagnetic.dBzndY[1];
3827                 raymagnetic.dBzndY[1] = drhody*save + dthetady*raymagnetic.dBzndY[1];
3828                 
3829                 save = raymagnetic.dBdY[0];
3830                 raymagnetic.dBdY[0] = drhodx*raymagnetic.dBdY[0] + dthetadx*raymagnetic.dBdY[1];
3831                 raymagnetic.dBdY[1] = drhody*save + dthetady*raymagnetic.dBdY[1];
3832                 
3833                 save = raymagnetic.dsalphadY[0];
3834                 raymagnetic.dsalphadY[0] = drhodx*raymagnetic.dsalphadY[0] + dthetadx*raymagnetic.dsalphadY[1];
3835                 raymagnetic.dsalphadY[1] = drhody*save + dthetady*raymagnetic.dsalphadY[1];
3836                 
3837                 save = raymagnetic.dcalphadY[0];
3838                 raymagnetic.dcalphadY[0] = drhodx*raymagnetic.dcalphadY[0] + dthetadx*raymagnetic.dcalphadY[1];
3839                 raymagnetic.dcalphadY[1] = drhody*save + dthetady*raymagnetic.dcalphadY[1];
3840                 
3841                 save = raymagnetic.dgradrhondY[0];
3842                 raymagnetic.dgradrhondY[0] = drhodx*raymagnetic.dgradrhondY[0] + dthetadx*raymagnetic.dgradrhondY[1];
3843                 raymagnetic.dgradrhondY[1] = drhody*save + dthetady*raymagnetic.dgradrhondY[1];
3844                 
3845                 save = raymagnetic.drhoripdY[0];
3846                 raymagnetic.drhoripdY[0] = drhodx*raymagnetic.drhoripdY[0] + dthetadx*raymagnetic.drhoripdY[1];
3847                 raymagnetic.drhoripdY[1] = drhody*save + dthetady*raymagnetic.drhoripdY[1];
3848                 
3849                 save = raymagnetic.dUpsilonndY[0];
3850                 raymagnetic.dUpsilonndY[0] = drhodx*raymagnetic.dUpsilonndY[0] + dthetadx*raymagnetic.dUpsilonndY[1];
3851                 raymagnetic.dUpsilonndY[1] = drhody*save + dthetady*raymagnetic.dUpsilonndY[1];
3852                 
3853                 save = rayprofiles.dTedY[0];
3854                 rayprofiles.dTedY[0] = drhodx*rayprofiles.dTedY[0] + dthetadx*rayprofiles.dTedY[1];
3855                 rayprofiles.dTedY[1] = drhody*save + dthetady*rayprofiles.dTedY[1];
3856                 
3857                 save = rayprofiles.dnedY[0];
3858                 rayprofiles.dnedY[0] = drhodx*rayprofiles.dnedY[0] + dthetadx*rayprofiles.dnedY[1];
3859                 rayprofiles.dnedY[1] = drhody*save + dthetady*rayprofiles.dnedY[1];
3860                 
3861                 for(is=0;isvoid build_raymagnetic(theta,raymagnetic,equilparam,x,dxdrho,dxdtheta,d2xdtheta2,d2xdthetadrho,d2xdrho2,
3877         y,dydrho,dydtheta,d2ydtheta2,d2ydthetadrho,d2ydrho2,
3878         r,drdrho,drdtheta,d2rdtheta2,d2rdthetadrho,d2rdrho2,
3879         calpha,dcalphadrho,dcalphadtheta,d2calphadtheta2,d2calphadthetadrho,d2calphadrho2,
3880         salpha,dsalphadrho,dsalphadtheta,d2salphadtheta2,d2salphadthetadrho,d2salphadrho2,
3881         gradrho,dgradrhodrho,dgradrhodtheta,d2gradrhodtheta2,d2gradrhodthetadrho,d2gradrhodrho2,
3882         Bx,dBxdrho,dBxdtheta,d2Bxdtheta2,d2Bxdthetadrho,d2Bxdrho2,dBxdz,
3883         By,dBydrho,dBydtheta,d2Bydtheta2,d2Bydthetadrho,d2Bydrho2,dBydz,
3884         Bz,dBzdrho,dBzdtheta,d2Bzdtheta2,d2Bzdthetadrho,d2Bzdrho2,dBzdz,
3885         BP,dBPdrho,dBPdtheta,d2BPdtheta2,d2BPdthetadrho,d2BPdrho2,dBPdz,
3886         B,dBdrho,dBdtheta,d2Bdtheta2,d2Bdthetadrho,d2Bdrho2,dBdz,flag_metric)/*Has to be modified under a change of metric*/
3887 raymagnetic_format raymagnetic;
3888 equilparam_format equilparam;
3889 double theta;
3890 double x,dxdrho,dxdtheta,d2xdtheta2,d2xdthetadrho,d2xdrho2;
3891 double y,dydrho,dydtheta,d2ydtheta2,d2ydthetadrho,d2ydrho2;
3892 double r,drdrho,drdtheta,d2rdtheta2,d2rdthetadrho,d2rdrho2;
3893 double calpha,dcalphadrho,dcalphadtheta,d2calphadtheta2,d2calphadthetadrho,d2calphadrho2;
3894 double salpha,dsalphadrho,dsalphadtheta,d2salphadtheta2,d2salphadthetadrho,d2salphadrho2;
3895 double gradrho,dgradrhodrho,dgradrhodtheta,d2gradrhodtheta2,d2gradrhodthetadrho,d2gradrhodrho2;
3896 double Bx,dBxdrho,dBxdtheta,d2Bxdtheta2,d2Bxdthetadrho,d2Bxdrho2,dBxdz;
3897 double By,dBydrho,dBydtheta,d2Bydtheta2,d2Bydthetadrho,d2Bydrho2,dBydz;
3898 double Bz,dBzdrho,dBzdtheta,d2Bzdtheta2,d2Bzdthetadrho,d2Bzdrho2,dBzdz;
3899 double BP,dBPdrho,dBPdtheta,d2BPdtheta2,d2BPdthetadrho,d2BPdrho2,dBPdz;
3900 double B,dBdrho,dBdtheta,d2Bdtheta2,d2Bdthetadrho,d2Bdrho2,dBdz;
3901 int flag_metric;
3902 {
3903     double Upsilon,dUpsilondrho,dUpsilondtheta,d2Upsilondtheta2,d2Upsilondthetadrho,d2Upsilondrho2;
3904     
3905     
3906     /*    WARNING: the definitions used in the DKE code, and here crucial for HXR calculations are the following
3907      1) the toroidal frame (R,Z,phi) is direct (phi is positive clockwise when the tokamak is seen from the top)
3908      2) the poloidal frame (r,theta,phi) is direct
3909      3) (psi,s,phi) must be direct : if Ip.phi > 0, then B.theta > 0 and psi > 0, and s.theta > 0 (s as the same direction of theta)
3910      4) the sign of psi is the sign of Ip.phi
3911      With the definitions above, if Ip is positive, psi is turned outward, Btheta is counterclockwise poloidally, and s too. The Ampere theorem is OK !
3912      This definition is used also for DKE and HXR calculations
3913      */
3914     
3915     
3916     if (isinf(equilparam.Rp[0]) == 1) {/* Toroidal factor. If Upsilon=1, cylindrical magnetic configuration */
3917         Upsilon = 1.0;
3918         dUpsilondrho = 0.0;
3919         dUpsilondtheta = 0.0;
3920     } else {
3921         Upsilon = 1.0 + x/equilparam.Rp[0];
3922         dUpsilondrho = dxdrho/equilparam.Rp[0];
3923         dUpsilondtheta = dxdtheta/equilparam.Rp[0];
3924     }
3925     if (flag_metric == 1)/*Curvilinear case*/
3926     {
3927         raymagnetic.Brhon[0] = 0.0;/* Normalized radial magnetic field */
3928         raymagnetic.dBrhondY[0] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3929         raymagnetic.dBrhondY[1] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3930         raymagnetic.dBrhondY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3931         
3932         raymagnetic.Bsn[0] = BP/B;/* Normalized poloidal magnetic field */
3933         raymagnetic.dBsndY[0] = (dBPdrho/B - BP*dBdrho/B/B);
3934         raymagnetic.dBsndY[1] = (dBPdtheta/B - BP*dBdtheta/B/B);
3935         raymagnetic.dBsndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3936         
3937         raymagnetic.Bzn[0] = Bz/B;/* Normlaized toroidal magnetic field */
3938         raymagnetic.dBzndY[0] = dBzdrho/B - Bz*dBdrho/B/B;
3939         raymagnetic.dBzndY[1] = dBzdtheta/B - Bz*dBdtheta/B/B;
3940         raymagnetic.dBzndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3941         
3942         raymagnetic.B[0] = B;/* Total magnetic field */
3943         raymagnetic.dBdY[0] = dBdrho;
3944         raymagnetic.dBdY[1] = dBdtheta;
3945         raymagnetic.dBdY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3946         
3947         raymagnetic.rn[0] = r/equilparam.ap[0];
3948         raymagnetic.drndY[0] = drdrho/equilparam.ap[0];
3949         raymagnetic.drndY[1] = drdtheta/equilparam.ap[0];
3950         raymagnetic.drndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3951         
3952         raymagnetic.xn[0] = x/equilparam.ap[0];
3953         raymagnetic.dxndY[0] = dxdrho/equilparam.ap[0];
3954         raymagnetic.dxndY[1] = dxdtheta/equilparam.ap[0];
3955         raymagnetic.dxndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3956         
3957         raymagnetic.yn[0] = y/equilparam.ap[0];
3958         raymagnetic.dyndY[0] = dydrho/equilparam.ap[0];
3959         raymagnetic.dyndY[1] = dydtheta/equilparam.ap[0];
3960         raymagnetic.dyndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3961         
3962         raymagnetic.calpha[0] = calpha;
3963         raymagnetic.dcalphadY[0] = dcalphadrho;
3964         raymagnetic.dcalphadY[1] = dcalphadtheta;
3965         raymagnetic.dcalphadY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3966         
3967         raymagnetic.salpha[0] = salpha;
3968         raymagnetic.dsalphadY[0] = dsalphadrho;
3969         raymagnetic.dsalphadY[1] = dsalphadtheta;
3970         raymagnetic.dsalphadY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3971         
3972         raymagnetic.gradrhon[0] = gradrho*equilparam.ap[0];
3973         raymagnetic.dgradrhondY[0] = dgradrhodrho*equilparam.ap[0];
3974         raymagnetic.dgradrhondY[1] = dgradrhodtheta*equilparam.ap[0];
3975         raymagnetic.dgradrhondY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3976         
3977         raymagnetic.Upsilonn[0] = Upsilon/equilparam.ap[0];
3978         raymagnetic.dUpsilonndY[0] = dUpsilondrho/equilparam.ap[0];
3979         raymagnetic.dUpsilonndY[1] = dUpsilondtheta/equilparam.ap[0];
3980         raymagnetic.dUpsilonndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3981         
3982         raymagnetic.rhorip[0] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3983         raymagnetic.drhoripdY[0] = 1.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3984         raymagnetic.drhoripdY[1] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3985         raymagnetic.drhoripdY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
3986     }
3987     else/*Cartesian case*/
3988     {
3989         /*-----Declaration of the derivatives needed for the chain rule operation----*/
3990         
3991         double theta = atan2(y,x);/*Analytical expression of theta(x,y)*/
3992         
3993         double calpha_theta = calpha*cos(theta) + salpha*sin(theta);/*cos(alpha-theta)*/
3994         double salpha_theta = salpha*cos(theta) - calpha*sin(theta);/*sin(alpha-theta)*/
3995         
3996         double drhodx = gradrho*equilparam.ap[0]*calpha_theta;/*drhodx for the change of variable (rho,theta)->(x,y)*/
3997         double drhody = -gradrho*equilparam.ap[0]*salpha_theta;/*drhody for the change of variable (rho,theta)->(x,y)*/
3998         double dthetadx = -sin(theta)*equilparam.ap[0]/r;/*dthetadx for the change of variable (rho,theta)->(x,y)*/
3999         double dthetady = cos(theta)*equilparam.ap[0]/r;/*dthetady for the change of variable (rho,theta)->(x,y)*/
4000         
4001         /*-Declaration of the cartesian equilibrium function and their derivatives-*/
4002         
4003         raymagnetic.Brhon[0] = 0.0;/* Normalized radial magnetic field */
4004         raymagnetic.dBrhondY[0] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4005         raymagnetic.dBrhondY[1] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4006         raymagnetic.dBrhondY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4007         
4008         raymagnetic.Bsn[0] = BP/B;/* Normalized poloidal magnetic field */
4009         raymagnetic.dBsndY[0] = drhodx*(dBPdrho/B - BP*dBdrho/B/B) + dthetadx*(dBPdtheta/B - BP*dBdtheta/B/B);
4010         raymagnetic.dBsndY[1] = drhody*(dBPdrho/B - BP*dBdrho/B/B) + dthetady*(dBPdtheta/B - BP*dBdtheta/B/B);
4011         raymagnetic.dBsndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4012         
4013         raymagnetic.Bzn[0] = Bz/B;/* Normlaized toroidal magnetic field */
4014         raymagnetic.dBzndY[0] = drhodx*(dBzdrho/B - Bz*dBdrho/B/B) + dthetadx*(dBzdtheta/B - Bz*dBdtheta/B/B);
4015         raymagnetic.dBzndY[1] = drhody*(dBzdrho/B - Bz*dBdrho/B/B) + dthetady*(dBzdtheta/B - Bz*dBdtheta/B/B);
4016         raymagnetic.dBzndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4017         
4018         raymagnetic.B[0] = B;/* Total magnetic field */
4019         raymagnetic.dBdY[0] = drhodx*dBdrho + dthetadx*dBdtheta;
4020         raymagnetic.dBdY[1] = drhody*dBdrho + dthetady*dBdtheta;
4021         raymagnetic.dBdY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4022         
4023         raymagnetic.rn[0] = r/equilparam.ap[0];
4024         raymagnetic.drndY[0] = drhodx*drdrho/equilparam.ap[0] + dthetadx*drdtheta/equilparam.ap[0];
4025         raymagnetic.drndY[1] = drhody*drdrho/equilparam.ap[0] + dthetady*drdtheta/equilparam.ap[0];
4026         raymagnetic.drndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4027         
4028         raymagnetic.xn[0] = x/equilparam.ap[0];
4029         raymagnetic.dxndY[0] = drhodx*dxdrho/equilparam.ap[0] + dthetadx*dxdtheta/equilparam.ap[0];
4030         raymagnetic.dxndY[1] = drhody*dxdrho/equilparam.ap[0] + dthetady*dxdtheta/equilparam.ap[0];
4031         raymagnetic.dxndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4032         
4033         raymagnetic.yn[0] = y/equilparam.ap[0];
4034         raymagnetic.dyndY[0] = drhodx*dydrho/equilparam.ap[0] + dthetadx*dydtheta/equilparam.ap[0];
4035         raymagnetic.dyndY[1] = drhody*dydrho/equilparam.ap[0] + dthetady*dydtheta/equilparam.ap[0];
4036         raymagnetic.dyndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4037         
4038         raymagnetic.calpha[0] = calpha;
4039         raymagnetic.dcalphadY[0] = drhodx*dcalphadrho + dthetadx*dcalphadtheta;
4040         raymagnetic.dcalphadY[1] = drhody*dcalphadrho + dthetady*dcalphadtheta;
4041         raymagnetic.dcalphadY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4042         
4043         raymagnetic.salpha[0] = salpha;
4044         raymagnetic.dsalphadY[0] = drhodx*dsalphadrho + dthetadx*dsalphadtheta;
4045         raymagnetic.dsalphadY[1] = drhody*dsalphadrho + dthetady*dsalphadtheta;
4046         raymagnetic.dsalphadY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4047         
4048         raymagnetic.gradrhon[0] = gradrho*equilparam.ap[0];
4049         raymagnetic.dgradrhondY[0] = (drhodx*dgradrhodrho*equilparam.ap[0] + dthetadx*dgradrhodtheta*equilparam.ap[0]);
4050         raymagnetic.dgradrhondY[1] = (drhody*dgradrhodrho*equilparam.ap[0] + dthetady*dgradrhodtheta*equilparam.ap[0]);
4051         raymagnetic.dgradrhondY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4052         
4053         raymagnetic.Upsilonn[0] = Upsilon/equilparam.ap[0];
4054         raymagnetic.dUpsilonndY[0] = drhodx*(dUpsilondrho/equilparam.ap[0]) + dthetadx*(dUpsilondtheta/equilparam.ap[0]);
4055         raymagnetic.dUpsilonndY[1] = drhody*(dUpsilondrho/equilparam.ap[0]) + dthetady*(dUpsilondtheta/equilparam.ap[0]);
4056         raymagnetic.dUpsilonndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4057         
4058         raymagnetic.rhorip[0] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4059         raymagnetic.drhoripdY[0] = drhodx;/* the unperturbed magnetic equilibrium is axisymmetric */
4060         raymagnetic.drhoripdY[1] = drhody;/* the unperturbed magnetic equilibrium is axisymmetric */
4061         raymagnetic.drhoripdY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4062     }
4063     
4064     /*
4065      mexPrintf("rn[0],drndY[0],drndY[1],xn[0],dxndY[0],dxndY[1],yn[0],dyndY[0],dyndY[1]:%g,%g,%g,%g,%g,%g,%g,%g,%g\n",raymagnetic.rn[0],raymagnetic.drndY[0],raymagnetic.drndY[1],raymagnetic.xn[0],raymagnetic.dxndY[0],raymagnetic.dxndY[1],raymagnetic.yn[0],raymagnetic.dyndY[0],raymagnetic.dyndY[1]);
4066      mexPrintf("Bsn[0],dBsndY[0],dBsndY[1]:%g,%g,%g\n",raymagnetic.Bsn[0],raymagnetic.dBsndY[0],raymagnetic.dBsndY[1]);
4067      mexPrintf("Bzn[0],dBzndY[0],dBzndY[1]:%g,%g,%g\n",raymagnetic.Bzn[0],raymagnetic.dBzndY[0],raymagnetic.dBzndY[1]);
4068      mexPrintf("B[0],dBdY[0],dBdY[1]:%g,%g,%g\n",raymagnetic.B[0],raymagnetic.dBdY[0],raymagnetic.dBdY[1]);
4069      mexPrintf("salpha[0],dsalphadY[0],dsalphadY[1]:%g,%g,%g\n",raymagnetic.salpha[0],raymagnetic.dsalphadY[0],raymagnetic.dsalphadY[1]);
4070      mexPrintf("calpha[0],dcalphadY[0],dcalphadY[1]:%g,%g,%g\n",raymagnetic.calpha[0],raymagnetic.dcalphadY[0],raymagnetic.dcalphadY[1]);
4071      mexPrintf("gradrhon[0],dgradrhondY[0],dgradrhondY[1]:%g,%g,%g\n",raymagnetic.gradrhon[0],raymagnetic.dgradrhondY[0],raymagnetic.dgradrhondY[1]);
4072      mexPrintf("psia_apRp:%g,%g,%g\n",equilparam.psia_apRp[0]);
4073      mexPrintf("Upsilon,dUpsilondrho,dUpsilondtheta:%g,%g,%g\n",Upsilon,dUpsilondrho,dUpsilondtheta);
4074      */
4075 }
4076 
4077 void interpequil_test(raymagnetic,rayprofiles,equilparam,Y,flag)/*Doesn't have to be modified under a change of metric*/
4078 raymagnetic_format raymagnetic;
4079 rayprofiles_format rayprofiles;
4080 equilparam_format equilparam;/* is an output in this case, since nothing is used from MatLab */
4081 double Y[];
4082 double flag;
4083 {
4084     /* toroidal circular equilibrium from Bonoli and Ott, PoF 25, 359 (1982) */
4085     
4086     /*  In this equilibrium the radial coordinate is psi = r/a.
4087      The Shafranov shift is neglected in first approximation.
4088      As a consequence, BT0 and BP0 are uniform.
4089      */
4090     
4091     double Te0,Tea,eTe;
4092     double ne0,nea,ene;
4093     double Ti0,Tia,eTi;
4094     double fi[3],zZi[4],zmi[4];
4095     
4096     double Zp,Rp,ap,rho,theta;
4097     double Bz0,BP0,dBP0dY1;
4098     double B,dBdrho,dBdtheta;
4099     double BP,dBPdrho,dBPdtheta;
4100     double Bz,dBzdrho,dBzdtheta;
4101     double x,dxdrho,dxdtheta;
4102     double y,dydrho,dydtheta;
4103     double Zeff0,Zeffa,eZeff,pZeff,dpZeffdrho;
4104     double lambda;
4105     
4106     double Ip,BPa,eq,qmin_Rpap,qmax_Rpap,q_Rpap,dqdrho_Rpap;
4107     
4108     double Upsilon,dUpsilondrho,dUpsilondtheta;
4109     
4110     int is,ns;
4111     
4112     rho = Y[0];
4113     theta = Y[1];
4114     
4115     load_idealequil_test(flag,&Zp,&Rp,&ap,&Bz0,&Ip,&eq,&qmin_Rpap,&Te0,&Tea,&eTe,&ne0,&nea,&ene,&Ti0,&Tia,&eTi,&Zeff0,&Zeffa,&eZeff,&ns,fi,zZi,zmi,&lambda);
4116     
4117     /*
4118      mexPrintf("ap,Rp,Zp,Bz0,Ip,eq,qmin_Rpap,Te0,Tea,eTe,ne0,nea,ene,Ti0,Tia,eTi,Zeff0,Zeffa,eZeff,lambda=%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g\n",ap,Rp,Zp,Bz0,Ip,eq,qmin_Rpap,Te0,Tea,eTe,ne0,nea,ene,Ti0,Tia,eTi,Zeff0,Zeffa,eZeff,lambda);
4119      mexPrintf("ns,fi[0],fi[1],fi[2],zZi[0],zZi[1],zZi[2],zmi[0],zmi[1],zmi[2]=%d,%g,%g,%g,%g,%g,%g,%g,%g,%g\n",ns,fi[0],fi[1],fi[2],zZi[0],zZi[1],zZi[2],zmi[0],zmi[1],zmi[2]);
4120      */
4121     
4122     
4123     if (zZi[0] > 0) {/*Vacuum case otherwise (no density, temperature...)*/
4124         
4125         pZeff = Zeff0 + (Zeffa-Zeff0)*pow(rho,eZeff);
4126         dpZeffdrho = eZeff*(Zeffa-Zeff0)*pow(rho,eZeff-1);
4127         
4128         if (ns > 4) {
4129             mexErrMsgTxt("Only one fully stripped impurity can be used !");
4130         }
4131         
4132         /*
4133          double *d2TedY2;
4134          double *d2nedY2;
4135          double **d2zTidY2;
4136          double **d2znidY2;
4137          */
4138         
4139         
4140         if ((fabs(flag) == 1) || (fabs(flag) == 2) || (fabs(flag) == 5) || (fabs(flag) == 6))  {/*Jetlike, RTtest, TORLH, RFP Madison*/
4141             
4142             rayprofiles.Te[0] = Tea + (Te0 - Tea)*pow(1 - rho*rho,eTe);
4143             rayprofiles.dTedY[0] = -2*rho*eTe*(Te0 - Tea)*pow(1 - rho*rho,eTe - 1);
4144             rayprofiles.dTedY[1] = 0.0;
4145             rayprofiles.dTedY[2] = 0.0;
4146             
4147             rayprofiles.ne[0] = nea + (ne0 - nea)*pow(1 - rho*rho,ene);
4148             rayprofiles.dnedY[0] = -2*rho*ene*(ne0 - nea)*pow(1 - rho*rho,ene - 1);
4149             rayprofiles.dnedY[1] = 0.0;
4150             rayprofiles.dnedY[2] = 0.0;
4151             
4152             
4153             for (is=0;iselse if ((fabs(flag) == 3) || (fabs(flag) == 4)) {/*VERSATOR2 and PLT */
4162             
4163             rayprofiles.Te[0] = Tea + (Te0 - Tea)*(exp(-eTe*Y[0]*Y[0]) - exp(-eTe))/(1 - exp(-eTe));
4164             rayprofiles.dTedY[0] = -2*eTe*Y[0]*(Te0 - Tea)*exp(-eTe*Y[0]*Y[0])/(1 - exp(-eTe));
4165             rayprofiles.dTedY[1] = 0.0;
4166             rayprofiles.dTedY[2] = 0.0;
4167             
4168             rayprofiles.ne[0] = nea + (ne0 - nea)*(exp(ene) - exp(ene*Y[0]*Y[0]))/(exp(ene) - 1);
4169             rayprofiles.dnedY[0] = -2*ene*Y[0]*(ne0 - nea)*exp(ene*Y[0]*Y[0])/(exp(ene) - 1);
4170             rayprofiles.dnedY[1] = 0.0;
4171             rayprofiles.dnedY[2] = 0.0;
4172             
4173             for (is=0;isfor (is=0;is<3;is++) { /*For a single impurity fully stripped. Only the first is selected after the isotope of hydrogen */
4182             rayprofiles.zni[is] = fi[is]*rayprofiles.ne[0]*(equilparam.zZi[3] - pZeff)/(equilparam.zZi[3]-1.0);
4183             rayprofiles.dznidY[is][0] = fi[is]*(rayprofiles.dnedY[0]*(equilparam.zZi[3] - pZeff) - rayprofiles.ne[0]*dpZeffdrho)/(equilparam.zZi[3]-1.0);
4184             rayprofiles.dznidY[is][1] = 0.0;
4185             rayprofiles.dznidY[is][2] = 0.0;
4186         }
4187         
4188         for (is=3;is/*For a single impurity fully stripped. Only the first is selected after the isotope of hydrogen */
4189             rayprofiles.zni[is] = rayprofiles.ne[0]*(pZeff - 1.0)/(equilparam.zZi[3]-1)/equilparam.zZi[3];
4190             rayprofiles.dznidY[is][0] = (rayprofiles.dnedY[0]*(pZeff - 1.0) + rayprofiles.ne[0]*dpZeffdrho)/(equilparam.zZi[3]-1)/equilparam.zZi[3];
4191             rayprofiles.dznidY[is][1] = 0.0;
4192             rayprofiles.dznidY[is][2] = 0.0;
4193         }
4194         
4195     }
4196     
4197     for (is=0;isif (isinf(equilparam.Rp[0]) == 1) {/* Toroidal factor. If Upsilon=1, cylindrical magnetic configuration */
4218         Upsilon = 1.0;
4219         dUpsilondrho = 0.0;
4220         dUpsilondtheta = 0.0;
4221     } else {
4222         Upsilon = 1.0 + x/Rp;
4223         dUpsilondrho = dxdrho/Rp;
4224         dUpsilondtheta = dxdtheta/Rp;
4225     }
4226     
4227     raymagnetic.xn[0] = x/ap;
4228     raymagnetic.dxndY[0] = dxdrho/ap;
4229     raymagnetic.dxndY[1] = dxdtheta/ap;
4230     raymagnetic.dxndY[2] = 0.0;
4231     
4232     y = ap*rho*sin(theta);
4233     dydrho = ap*sin(theta);
4234     dydtheta = ap*rho*cos(theta);
4235     
4236     raymagnetic.yn[0] = y/ap;
4237     raymagnetic.dyndY[0] = dydrho/ap;
4238     raymagnetic.dyndY[1] = dydtheta/ap;
4239     raymagnetic.dyndY[2] = 0.0;
4240     
4241     BPa = 0.2*fabs(Ip)/ap;/* MA */
4242     qmax_Rpap = fabs(Bz0)/BPa;/* cylindrical limit -> qmax*(Rp/ap)*/
4243     
4244     if ((fabs(flag) == 1) || (fabs(flag) == 3) ||(fabs(flag) == 4) || (fabs(flag) == 5))  {/*RTtest, VERSATOR2, PLT and TORLH */
4245         
4246         q_Rpap = (qmax_Rpap - qmin_Rpap)*pow(Y[0],eq) + qmin_Rpap;
4247         dqdrho_Rpap = eq*(qmax_Rpap - qmin_Rpap)*pow(Y[0],eq - 1.0);
4248         
4249         equilparam.psia_apRp[0] = ap*ap*fabs(Bz0)*log(qmax_Rpap/qmin_Rpap)/(qmax_Rpap - qmin_Rpap)/2;
4250         
4251     } else if (fabs(flag) == 2) {/*JETlike */
4252         
4253         if (Y[0] == 0.0) {
4254             q_Rpap = qmax_Rpap/(1+eq);
4255             dqdrho_Rpap = 0.0;
4256         } else {
4257             q_Rpap = qmax_Rpap*pow(Y[0],2)/(1 - pow(1-Y[0]*Y[0],1+eq));
4258             dqdrho_Rpap = 2*q_Rpap*(1 - (eq+1)*pow(1-Y[0]*Y[0],eq)*q_Rpap/qmax_Rpap)/Y[0];
4259         }
4260         
4261         equilparam.psia_apRp[0] = ap*ap*BPa*3/4;
4262         
4263     } else if (fabs(flag) == 6) {/*RFP Madison */
4264         
4265         q_Rpap = Y[0]*j0(lambda*Y[0])/j1(lambda*Y[0]);
4266         dqdrho_Rpap = j0(lambda*Y[0])/j1(lambda*Y[0]) - lambda*Y[0] - j0(lambda*Y[0])*(j0(lambda*Y[0]) - lambda*Y[0]*jn(2,lambda*Y[0]))/j1(lambda*Y[0])/j1(lambda*Y[0]);
4267         
4268         equilparam.psia_apRp[0] = ap*ap*fabs(Bz0)*(1.0 - j0(lambda*Y[0]))/lambda;
4269     }
4270     
4271     /* mexPrintf("qmax_Rpap,BPa,equilparam.psia_apRp[0] = %g,%g,%g\n",qmax_Rpap,BPa,equilparam.psia_apRp[0]);*/
4272     
4273     
4274     if (lambda == 0) {/* tokamak */
4275         
4276         Bz = Bz0/Upsilon;
4277         dBzdrho = -Bz0*dUpsilondrho/Upsilon/Upsilon;
4278         dBzdtheta = -Bz0*dUpsilondtheta/Upsilon/Upsilon;
4279         
4280         BP = qmax_Rpap*BPa*Y[0]/q_Rpap/Upsilon;/* Poloidal magnetic field, cylindrical limit */
4281         dBPdrho = qmax_Rpap*BPa*(1.0 - dqdrho_Rpap*Y[0]/q_Rpap - dUpsilondrho*Y[0]/Upsilon)/q_Rpap/Upsilon;
4282         dBPdtheta = -BP*dUpsilondtheta/Upsilon;
4283         
4284     } else {/* RFP */
4285         
4286         Bz = fabs(Bz0)*j0(lambda*Y[0])/Upsilon;
4287         dBzdrho = -fabs(Bz0)*lambda*j1(lambda*Y[0])/Upsilon - fabs(Bz0)*j0(lambda*Y[0])*dUpsilondrho/Upsilon/Upsilon;
4288         dBzdtheta = -Bz*dUpsilondtheta/Upsilon;
4289         
4290         BP = fabs(Bz0)*j1(lambda*Y[0])/Upsilon;
4291         dBPdrho = fabs(Bz0)*lambda*(j0(lambda*Y[0]) - jn(2,lambda*Y[0]))/Upsilon/2 - fabs(Bz0)*j1(lambda*Y[0])*dUpsilondrho/Upsilon/Upsilon;
4292         dBPdtheta = -BP*dUpsilondtheta/Upsilon;
4293     }
4294     
4295     /* mexPrintf("ap,Rp,BPa,rho,BP,Bz0,x,theta,dBPdrho,dBPdtheta:%g,%g,%g,%g,%g,%g,%g,%g,%g,%g\n",ap,Rp,BPa,rho,theta,BP,Bz0,x,dBPdrho,dBPdtheta);*/
4296     
4297     B = sqrt(BP*BP + Bz*Bz);
4298     dBdrho = (BP*dBPdrho + Bz*dBzdrho)/B;
4299     dBdtheta = (BP*dBPdtheta + Bz*dBzdtheta)/B;
4300     
4301     raymagnetic.Brhon[0] = 0.0;/* Normalized radial magnetic field */
4302     raymagnetic.dBrhondY[0] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4303     raymagnetic.dBrhondY[1] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4304     raymagnetic.dBrhondY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4305     
4306     raymagnetic.Bzn[0] = Bz/B;
4307     raymagnetic.dBzndY[0] = dBzdrho/B - Bz*dBdrho/B/B;
4308     raymagnetic.dBzndY[1] = dBzdtheta/B - Bz*dBdtheta/B/B;
4309     raymagnetic.dBzndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4310     
4311     raymagnetic.Bsn[0] = BP/B;
4312     raymagnetic.dBsndY[0] = dBPdrho/B - BP*dBdrho/B/B;
4313     raymagnetic.dBsndY[1] = dBPdtheta/B - BP*dBdtheta/B/B;
4314     raymagnetic.dBsndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4315     
4316     raymagnetic.B[0] = B;
4317     raymagnetic.dBdY[0] = dBdrho;
4318     raymagnetic.dBdY[1] = dBdtheta;
4319     raymagnetic.dBdY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4320     
4321     raymagnetic.calpha[0] = 1.0;
4322     raymagnetic.dcalphadY[0] = 0.0;
4323     raymagnetic.dcalphadY[1] = 0.0;
4324     raymagnetic.dcalphadY[2] = 0.0;
4325     
4326     raymagnetic.salpha[0] = 0.0;
4327     raymagnetic.dsalphadY[0] = 0.0;
4328     raymagnetic.dsalphadY[1] = 0.0;
4329     raymagnetic.dsalphadY[2] = 0.0;
4330     
4331     raymagnetic.gradrhon[0] = 1.0;
4332     raymagnetic.dgradrhondY[0] = 0.0;
4333     raymagnetic.dgradrhondY[1] = 0.0;
4334     raymagnetic.dgradrhondY[2] = 0.0;
4335     
4336     raymagnetic.rhorip[0] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4337     raymagnetic.drhoripdY[0] = 1.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4338     raymagnetic.drhoripdY[1] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4339     raymagnetic.drhoripdY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4340     
4341     raymagnetic.Upsilonn[0] = Upsilon/ap;
4342     raymagnetic.dUpsilonndY[0] = dUpsilondrho/ap;
4343     raymagnetic.dUpsilonndY[1] = dUpsilondtheta/ap;
4344     raymagnetic.dUpsilonndY[2] = 0.0;/* the unperturbed magnetic equilibrium is axisymmetric */
4345     
4346     /*
4347      
4348      mexPrintf("---- Interpequil_test ----\n");
4349      mexPrintf("rho,theta:%g,%g\n",rho,theta);
4350      mexPrintf("Te[0],dTedY[0],dTedY[1],ne[0],dnedY[0],dnedY[1]:%g,%g,%g,%g,%g,%g\n",rayprofiles.Te[0],rayprofiles.dTedY[0],rayprofiles.dTedY[1],rayprofiles.ne[0],rayprofiles.dnedY[0],rayprofiles.dnedY[1]);
4351      for (is=0;is<ns;is++) {
4352      mexPrintf("is,zTi[is],dzTidY[is][0],dzTidY[is][1],zni[is],dznidY[is][0],dznidY[is][1]:%d,%g,%g,%g,%g,%g,%g\n",is,rayprofiles.zTi[is],rayprofiles.dzTidY[is][0],rayprofiles.dzTidY[is][1],rayprofiles.zni[is],rayprofiles.dznidY[is][0],rayprofiles.dznidY[is][1]);
4353      }
4354      
4355      mexPrintf("rn[0],drndY[0],drndY[1],xn[0],dxndY[0],dxndY[1],yn[0],dyndY[0],dyndY[1]:%15.10g,%15.10g,%15.10g,%15.10g,%15.10g,%15.10g,%15.10g,%15.10g,%15.10g\n",raymagnetic.rn[0],raymagnetic.drndY[0],raymagnetic.drndY[1],raymagnetic.xn[0],raymagnetic.dxndY[0],raymagnetic.dxndY[1],raymagnetic.yn[0],raymagnetic.dyndY[0],raymagnetic.dyndY[1]);
4356      mexPrintf("Bsn[0],dBsndY[0],dBsndY[1]:%15.10g,%15.10g,%15.10g\n",raymagnetic.Bsn[0],raymagnetic.dBsndY[0],raymagnetic.dBsndY[1]);
4357      mexPrintf("Bzn[0],dBzndY[0],dBzndY[1]:%15.10g,%15.10g,%15.10g\n",raymagnetic.Bzn[0],raymagnetic.dBzndY[0],raymagnetic.dBzndY[1]);
4358      mexPrintf("B[0],dBdY[0],dBdY[1]:%15.10g,%15.10g,%15.10g\n",raymagnetic.B[0],raymagnetic.dBdY[0],raymagnetic.dBdY[1]);
4359      mexPrintf("salpha[0],dsalphadY[0],dsalphadY[1]:%15.10g,%15.10g,%15.10g\n",raymagnetic.salpha[0],raymagnetic.dsalphadY[0],raymagnetic.dsalphadY[1]);
4360      mexPrintf("calpha[0],dcalphadY[0],dcalphadY[1]:%15.10g,%15.10g,%15.10g\n",raymagnetic.calpha[0],raymagnetic.dcalphadY[0],raymagnetic.dcalphadY[1]);
4361      mexPrintf("gradrhon[0],dgradrhondY[0],dgradrhondY[1]:%15.10g,%15.10g,%15.10g\n",raymagnetic.gradrhon[0],raymagnetic.dgradrhondY[0],raymagnetic.dgradrhondY[1]);
4362      
4363      */
4364     
4365 }
4366 
4367 
4368 double sgn(x)
4369 double x;
4370 {
4371     if (x < 0.0) {return(-1.0);}
4372     else if (x == 0.0) {return(0.0);}
4373     else {return(1.0);}
4374     
4375 }
4376 
4377 
4378 void load_idealequil_test(flag,Zp,Rp,ap,Bz0,Ip,eq,qmin_Rpap,Te0,Tea,eTe,ne0,nea,ene,Ti0,Tia,eTi,Zeff0,Zeffa,eZeff,ns,fi,zZi,zmi,lambda)
4379 double *Zp,*Rp,*ap,*Bz0,*Ip,*eq,*qmin_Rpap,*Te0,*Tea,*eTe,*ne0,*nea,*ene,*Ti0,*Tia,*eTi,*Zeff0,*Zeffa,*eZeff,*lambda;
4380 double fi[],zZi[],zmi[];
4381 double flag;
4382 int *ns;
4383 {
4384     
4385     
4386     if (fabs(flag) == 1) {/* RTtest case */
4387         
4388         Rp[0] = 3.0;
4389         Zp[0] = 0;
4390         ap[0] = 0.9;
4391         Bz0[0] = 3.0;/* Signed toroidal magnetic component (T), see the conventions */
4392         Ip[0] = 1.0;/* Signed toroidal component of the plasma current (MA), see the conventions */
4393         qmin_Rpap[0] = 1.0*Rp[0]/ap[0];/* Edge safety factor q */
4394         eq[0] = 2.0;/* q=0 flat q profile */
4395         
4396         lambda[0] = 0;/* BFM magnetic equilbrium model for RFP */
4397         
4398         Te0[0] = 4.0;
4399         Tea[0] = Te0[0]/10.0;
4400         eTe[0] = 1.0;
4401         
4402         ne0[0] = 3.0e+19;
4403         nea[0] = 1e-10;
4404         ene[0] = 1.0;
4405         
4406         Ti0[0] = Te0[0];
4407         Tia[0] = Tea[0];
4408         eTi[0] = eTe[0];
4409         
4410         fi[0] = 1.0;
4411         fi[1] = 0.0;
4412         fi[2] = 0.0;
4413         
4414         if (flag < 0) {/* vacuum case */
4415             zZi[0] = 0.0;
4416             zZi[1] = 0.0;
4417             zZi[2] = 0.0;
4418             zZi[3] = 0.0;/* Carbon */
4419         } else {
4420             zZi[0] = 1.0;
4421             zZi[1] = 1.0;
4422             zZi[2] = 1.0;
4423             zZi[3] = 6.0;/* Carbon */
4424         }
4425         
4426         zmi[0] = 1.0;
4427         zmi[1] = 2.0;
4428         zmi[2] = 3.0;
4429         zmi[3] = 12.0;/* Carbon */
4430         
4431         ns[0] = 4;
4432         
4433         Zeff0[0] = 1.0;/* No impurity case, only hydrogen */
4434         Zeffa[0] = 1.0;
4435         eZeff[0] = 0.0;
4436         
4437     } else if (fabs(flag) == 2) {/* Jetlike case */
4438         
4439         Rp[0] = 3.05;
4440         Zp[0] = 0;
4441         ap[0] = 0.95;
4442         Bz0[0] = 3.2;/* Signed toroidal magnetic component (T), see the conventions */
4443         Ip[0] = 3.5;/* Signed toroidal component of the plasma current (MA), see the conventions */
4444         qmin_Rpap[0] = 1.0*Rp[0]/ap[0];/* Edge safety factor q */
4445         eq[0] = 1.0;/* q=0 flat q profile */
4446         
4447         lambda[0] = 0;/* BFM magnetic equilbrium model for RFP */
4448         
4449         Te0[0] = 6.0;
4450         Tea[0] = 0.1;
4451         eTe[0] = 1.5;
4452         
4453         ne0[0] = 5.0e+19;
4454         nea[0] = 0.01e+19;
4455         ene[0] = 1.0;
4456         
4457         Ti0[0] = Te0[0];
4458         Tia[0] = Tea[0];
4459         eTi[0] = eTe[0];
4460         
4461         fi[0] = 1.0;
4462         fi[1] = 0.0;
4463         fi[2] = 0.0;
4464         
4465         zZi[0] = 1.0;
4466         zZi[1] = 1.0;
4467         zZi[2] = 1.0;
4468         
4469         zmi[0] = 1.0;
4470         zmi[1] = 2.0;
4471         zmi[2] = 3.0;
4472         
4473         ns[0] = 3;
4474         
4475         Zeff0[0] = 1.0;/* No impurity case, only hydrogen */
4476         Zeffa[0] = 1.0;
4477         eZeff[0] = 0.0;
4478         
4479     } else if (fabs(flag) == 3) {/* VERSATOR2 case */
4480         
4481         Rp[0] = 0.4;
4482         Zp[0] = 0;
4483         ap[0] = 0.325*0.4;
4484         Bz0[0] = 1.4;/* Signed toroidal magnetic component (T), see the conventions */
4485         Ip[0] = 0.05;/* Signed toroidal component of the plasma current (MA), see the conventions */
4486         qmin_Rpap[0] = 1.0*Rp[0]/ap[0];/* Edge safety factor q */
4487         eq[0] = 2.0;/* q=0 flat q profile */
4488         
4489         lambda[0] = 0;/* BFM magnetic equilbrium model for RFP */
4490         
4491         Te0[0] = 0.40;
4492         Tea[0] = 0.02;
4493         eTe[0] = 3.94;
4494         
4495         ne0[0] = 2.0e19;
4496         nea[0] = 2e18;
4497         ene[0] = 0.1;
4498         
4499         Ti0[0] = 0.15;
4500         Tia[0] = 0.02;
4501         eTi[0] = 3.94;
4502         
4503         fi[0] = 1.0;
4504         fi[1] = 0.0;
4505         fi[2] = 0.0;
4506         
4507         zZi[0] = 1.0;
4508         zZi[1] = 1.0;
4509         zZi[2] = 1.0;
4510         zZi[3] = 6.0;
4511         
4512         zmi[0] = 1.0;
4513         zmi[1] = 2.0;
4514         zmi[2] = 3.0;
4515         zmi[3] = 12.0;
4516         
4517         ns[0] = 4;
4518         
4519         Zeff0[0] = 2.0;/* No impurity case, only hydrogen */
4520         Zeffa[0] = 2.0;
4521         eZeff[0] = 0.0;
4522         
4523     } else if (fabs(flag) == 4) {/* PLT case */
4524         
4525         Rp[0] = 1.32;
4526         Zp[0] = 0;
4527         ap[0] = 0.303*1.32;
4528         Bz0[0] = 3.1;/* Signed toroidal magnetic component (T), see the conventions */
4529         Ip[0] = 0.2;/* Signed toroidal component of the plasma current (MA), see the conventions */
4530         qmin_Rpap[0] = 1.0*Rp[0]/ap[0];/* Edge safety factor q */
4531         eq[0] = 2.0;/* q=0 flat q profile */
4532         
4533         lambda[0] = 0;/* BFM magnetic equilbrium model for RFP */
4534         
4535         Te0[0] = 1.5;
4536         Tea[0] = 0.03;
4537         eTe[0] = 3.99;
4538         
4539         ne0[0] = 0.5625e19;
4540         nea[0] = 0.5625e18;
4541         ene[0] = -0.571;
4542         
4543         Ti0[0] = 0.5;
4544         Tia[0] = 0.03;
4545         eTi[0] = 2.90;
4546         
4547         fi[0] = 1.0;
4548         fi[1] = 0.0;
4549         fi[2] = 0.0;
4550         
4551         zZi[0] = 1.0;
4552         zZi[1] = 1.0;
4553         zZi[2] = 1.0;
4554         zZi[3] = 6.0;
4555         
4556         zmi[0] = 1.0;
4557         zmi[1] = 2.0;
4558         zmi[2] = 3.0;
4559         zmi[3] = 12.0;
4560         
4561         ns[0] = 4;
4562         
4563         Zeff0[0] = 4.0;/* No impurity case, only hydrogen */
4564         Zeffa[0] = 4.0;
4565         eZeff[0] = 0.0;
4566         
4567     } else if (fabs(flag) == 5) {/* TORLH comparison */
4568         
4569         Rp[0] = 2.96;
4570         Zp[0] = 0;
4571         ap[0] = 1.25;
4572         Bz0[0] = 3.45;/* Signed toroidal magnetic component (T), see the conventions */
4573         Ip[0] = 2.276446368308309;/* Signed toroidal component of the plasma current (MA), see the conventions */
4574         qmin_Rpap[0] = 1.0*Rp[0]/ap[0];/* Edge safety factor q */
4575         eq[0] = 2.0;/* q=0 flat q profile */
4576         
4577         lambda[0] = 0;/* BFM magnetic equilbrium model for RFP */
4578         
4579         Te0[0] = 1.0;
4580         Tea[0] = 1.0;
4581         eTe[0] = 0.0;
4582         
4583         ne0[0] = 3.0e19;
4584         nea[0] = 3.0e18;
4585         ene[0] = 1;
4586         
4587         Ti0[0] = Te0[0];
4588         Tia[0] = Tea[0];
4589         eTi[0] = eTe[0];
4590         
4591         fi[0] = 0.0;
4592         fi[1] = 1.0;
4593         fi[2] = 0.0;
4594         
4595         zZi[0] = 1.0;
4596         zZi[1] = 1.0;
4597         zZi[2] = 1.0;
4598         zZi[3] = 6.0;
4599         
4600         zmi[0] = 1.0;
4601         zmi[1] = 2.0;
4602         zmi[2] = 3.0;
4603         zmi[3] = 12.0;
4604         
4605         ns[0] = 4;
4606         
4607         Zeff0[0] = 1.7;/* No impurity case, only hydrogen */
4608         Zeffa[0] = 1.7;
4609         eZeff[0] = 0.0;
4610         
4611     } else if (fabs(flag) == 6) {/* RFP madison comparison */
4612         
4613         Rp[0] = 1.50;
4614         Zp[0] = 0;
4615         ap[0] = 0.5;
4616         Bz0[0] = 0.2;/* Signed toroidal magnetic component (T), see the conventions */
4617         Ip[0] = 0.3;/* Signed toroidal component of the plasma current (MA), see the conventions */
4618         qmin_Rpap[0] = 0;/* Edge safety factor q */
4619         eq[0] = 0;/* q=0 flat q profile */
4620         
4621         lambda[0] = 2.2;/* BFM magnetic equilbrium model for RFP */
4622         
4623         Te0[0] = 1.3;
4624         Tea[0] = 0.10*Te0[0];
4625         eTe[0] = 1.1;
4626         
4627         ne0[0] = 1.4e19;
4628         nea[0] = 0.24*ne0[0];
4629         ene[0] = 1.3;
4630         
4631         Ti0[0] = 0.35;
4632         Tia[0] = 0.1*Ti0[0];
4633         eTi[0] = 1.1;
4634         
4635         fi[0] = 0.0;
4636         fi[1] = 1.0;
4637         fi[2] = 0.0;
4638         
4639         zZi[0] = 1.0;
4640         zZi[1] = 1.0;
4641         zZi[2] = 1.0;
4642         zZi[3] = 6.0;
4643         
4644         zmi[0] = 1.0;
4645         zmi[1] = 2.0;
4646         zmi[2] = 3.0;
4647         zmi[3] = 12.0;
4648         
4649         ns[0] = 4;
4650         
4651         Zeff0[0] = 2.0;/* No impurity case, only hydrogen */
4652         Zeffa[0] = 2.0;
4653         eZeff[0] = 0.0;
4654     }
4655     
4656     
4657     
4658     
4659 }
4660 
4661 
4662 void testparam(rayparam,equilparam,fluctparam,raymagnetic,rayprofiles,rayequil,rayfluctuations,distriparam,raydistri,flag_fluct,flag_f0,flag,y0_in)
4663 rayparam_format rayparam;
4664 equilparam_format equilparam;
4665 fluctparam_format fluctparam;
4666 raymagnetic_format raymagnetic;
4667 rayprofiles_format rayprofiles;
4668 rayequil_format rayequil;
4669 rayfluctuations_format rayfluctuations;
4670 distriparam_format distriparam;
4671 raydistri_format raydistri;
4672 int flag_fluct,flag_f0;
4673 double flag;
4674 double y0_in[MC];
4675 {
4676     
4677     double *Te,*ne,*zTi,*zni;
4678     double *dTedrho,*dnedrho,*dzTidrho,*dznidrho;
4679     double *d2Tedrho2,*d2nedrho2,*d2zTidrho2,*d2znidrho2;
4680     
4681     double *Bx,*dBxdrho,*dBxdtheta,*d2Bxdtheta2,*d2Bxdthetadrho,*d2Bxdrho2;
4682     double *By,*dBydrho,*dBydtheta,*d2Bydtheta2,*d2Bydthetadrho,*d2Bydrho2;
4683     double *Bz,*dBzdrho,*dBzdtheta,*d2Bzdtheta2,*d2Bzdthetadrho,*d2Bzdrho2;
4684     
4685     double *x,*dxdrho,*dxdtheta,*d2xdtheta2,*d2xdthetadrho,*d2xdrho2;
4686     double *y,*dydrho,*dydtheta,*d2ydtheta2,*d2ydthetadrho,*d2ydrho2;
4687     
4688     double *L_rho;
4689     double *xq,*dxqdrho;
4690     double *xL_theta,*dxL_thetadrho;
4691     double *xL_perp,*dxL_perpdrho;
4692     double *XL_phi,*dXL_phidrho,*dXL_phidtheta;
4693     
4694     double *sf,*dsfdrho,*dsfdtheta;
4695     double *sfx,*dsfxdrho,*dsfxdtheta;
4696     double *sfy,*dsfydrho,*dsfydtheta;
4697     double *sfz,*dsfzdrho,*dsfzdtheta;
4698     
4699     double *f0_fit,*df0drho_fit,*d2f0drho2_fit;
4700     double *PSI_fit;
4701     int ip_ref,jm_ref;
4702     
4703     double dummy1,dummy2,dummy3;
4704     
4705     int jf,ip,jm;
4706     
4707     double xm=-0.71,xp=0.71,ht,dht,d2ht;
4708     
4709     double ytest[MC];
4710     
4711     if (flag == 0) {/* numerical toroidal MHD equilibrium */
4712         if (equilparam.zZi[0] > 0) {
4713             mexPrintf("----------------------------------------\n");
4714             mexPrintf("Te_fit.coefs_f(1): %g\n",rayequil.Te_fit.coefs_f[0]);
4715             mexPrintf("Te_fit.coefs_dfdrho(1): %g\n",rayequil.Te_fit.coefs_dfdrho[0]);
4716             mexPrintf("Te_fit.coefs_d2fdrho2(1): %g\n",rayequil.Te_fit.coefs_d2fdrho2[0]);
4717         }
4718         
4719         mexPrintf("----------------------------------------\n");
4720         mexPrintf("Bz_fit.nfourier: %g\n",rayequil.Bz_fit.dim_dbndrho[0]);
4721         mexPrintf("Bz_fit.coefs_bn(1): %g\n",rayequil.Bz_fit.coefs_bn[0]);
4722         mexPrintf("Bz_fit.coefs_dbndrho(1): %g\n",rayequil.Bz_fit.coefs_dbndrho[0]);
4723         
4724         
4725         if (equilparam.zZi[0] > 0) {
4726             mexPrintf("----------------------------------------\n");
4727             Te = mxCalloc(1,sizeof(double));
4728             dTedrho = mxCalloc(1,sizeof(double));
4729             d2Tedrho2 = mxCalloc(1,sizeof(double));
4730             ppvald_1D(rayequil.Te_fit,rayparam.dS[0],0.25,Te,dTedrho,d2Tedrho2);
4731             mexPrintf("Te(0.25),dTedrho(0.25),d2Tedrho2(0.25) (keV): %g,%g,%g\n",Te[0],dTedrho[0],d2Tedrho2[0]);
4732             mxFree(Te);
4733             mxFree(dTedrho);
4734             mxFree(d2Tedrho2);
4735             
4736             ne = mxCalloc(1,sizeof(double));
4737             dnedrho = mxCalloc(1,sizeof(double));
4738             d2nedrho2 = mxCalloc(1,sizeof(double));
4739             ppvald_1D(rayequil.ne_fit,rayparam.dS[0],0.25,ne,dnedrho,d2nedrho2);
4740             mexPrintf("ne(0.25),dnedrho(0.25),d2nedrho2(0.25) (10+19 m-3): %g,%g,%g\n",ne[0]/1e19,dnedrho[0]/1e19,d2nedrho2[0]/1e19);
4741             mxFree(ne);
4742             mxFree(dnedrho);
4743             mxFree(d2nedrho2);
4744             
4745             zTi = mxCalloc(equilparam.ns[0],sizeof(double));
4746             dzTidrho = mxCalloc(equilparam.ns[0],sizeof(double));
4747             d2zTidrho2 = mxCalloc(equilparam.ns[0],sizeof(double));
4748             ppvald_1D(rayequil.zTi_fit,rayparam.dS[0],0.25,zTi,dzTidrho,d2zTidrho2);
4749             mexPrintf("zTi(2,0.25),dzTidrho(2,0.25),d2zTidrho2(2,0.25) (keV): %g,%g,%g\n",zTi[0],dzTidrho[0],d2zTidrho2[0]);
4750             mxFree(zTi);
4751             mxFree(dzTidrho);
4752             mxFree(d2zTidrho2);
4753             
4754             zni = mxCalloc(equilparam.ns[0],sizeof(double));
4755             dznidrho = mxCalloc(equilparam.ns[0],sizeof(double));
4756             d2znidrho2 = mxCalloc(equilparam.ns[0],sizeof(double));
4757             ppvald_1D(rayequil.zni_fit,rayparam.dS[0],0.25,zni,dznidrho,d2znidrho2);
4758             mexPrintf("zni(2,0.25),dznidrho(2,0.25),d2znidrho2(2,0.25) (10+19 m-3): %g,%g,%g\n",zni[0]/1e19,dznidrho[0]/1e19,d2znidrho2[0]/1e19);
4759             mxFree(zni);
4760             mxFree(dznidrho);
4761             mxFree(d2znidrho2);
4762         }
4763         
4764         mexPrintf("----------------------------------------\n");
4765         x = mxCalloc(1,sizeof(double));
4766         dxdrho = mxCalloc(1,sizeof(double));
4767         dxdtheta = mxCalloc(1,sizeof(double));
4768         d2xdtheta2 = mxCalloc(1,sizeof(double));
4769         d2xdthetadrho = mxCalloc(1,sizeof(double));
4770         d2xdrho2 = mxCalloc(1,sizeof(double));
4771         ppvald_2D(rayequil.x_fit,rayparam.dS[0],0.25,0.2,x,dxdrho,dxdtheta,d2xdtheta2,d2xdthetadrho,d2xdrho2);
4772         mexPrintf("x(0.25,0.2),dxdrho(0.25,0.2),dxdtheta(0.25,0.2) (m): %g,%g,%g\n",x[0],dxdrho[0],dxdtheta[0],d2xdtheta2[0],d2xdthetadrho[0]);
4773         mexPrintf("d2xdthetadrho(0.25,0.2),d2xdtheta2(0.25,0.2),d2xdrho2(0.25,0.2) (m): %g,%g,%g\n",d2xdthetadrho[0],d2xdtheta2[0],d2xdrho2[0]);
4774         mxFree(x);
4775         mxFree(dxdrho);
4776         mxFree(dxdtheta);
4777         mxFree(d2xdtheta2);
4778         mxFree(d2xdthetadrho);
4779         mxFree(d2xdrho2);
4780         
4781         y = mxCalloc(1,sizeof(double));
4782         dydrho = mxCalloc(1,sizeof(double));
4783         dydtheta = mxCalloc(1,sizeof(double));
4784         d2ydtheta2 = mxCalloc(1,sizeof(double));
4785         d2ydthetadrho = mxCalloc(1,sizeof(double));
4786         d2ydrho2 = mxCalloc(1,sizeof(double));
4787         ppvald_2D(rayequil.y_fit,rayparam.dS[0],0.25,0.2,y,dydrho,dydtheta,d2ydtheta2,d2ydthetadrho,d2ydrho2);
4788         mexPrintf("y(0.25,0.2),dydrho(0.25,0.2),dydtheta(0.25,0.2) (m): %g,%g,%g\n",y[0],dydrho[0],dydtheta[0],d2ydtheta2[0],d2ydthetadrho[0]);
4789         mexPrintf("d2ydthetadrho(0.25,0.2),d2ydtheta2(0.25,0.2),d2ydrho2(0.25,0.2) (m): %g,%g,%g\n",d2ydthetadrho[0],d2ydtheta2[0],d2ydrho2[0]);
4790         mxFree(y);
4791         mxFree(dydrho);
4792         mxFree(dydtheta);
4793         mxFree(d2ydtheta2);
4794         mxFree(d2ydthetadrho);
4795         mxFree(d2ydrho2);
4796         
4797         Bx = mxCalloc(1,sizeof(double));
4798         dBxdrho = mxCalloc(1,sizeof(double));
4799         dBxdtheta = mxCalloc(1,sizeof(double));
4800         d2Bxdtheta2 = mxCalloc(1,sizeof(double));
4801         d2Bxdthetadrho = mxCalloc(1,sizeof(double));
4802         d2Bxdrho2 = mxCalloc(1,sizeof(double));
4803         ppvald_2D(rayequil.Bx_fit,rayparam.dS[0],0.25,0.2,Bx,dBxdrho,dBxdtheta,d2Bxdtheta2,d2Bxdthetadrho,d2Bxdrho2);
4804         mexPrintf("Bx(0.25,0.2),dBxdrho(0.25,0.2),dBxdtheta(0.25,0.2) (T): %g,%g,%g\n",Bx[0],dBxdrho[0],dBxdtheta[0]);
4805         mexPrintf("d2Bxdthetadrho(0.25,0.2),d2Bxdtheta2(0.25,0.2),d2Bxdrho2(0.25,0.2) (m): %g,%g,%g\n",d2Bxdthetadrho[0],d2Bxdtheta2[0],d2Bxdrho2[0]);
4806         mxFree(Bx);
4807         mxFree(dBxdrho);
4808         mxFree(dBxdtheta);
4809         mxFree(d2Bxdtheta2);
4810         mxFree(d2Bxdthetadrho);
4811         mxFree(d2Bxdrho2);
4812         
4813         By = mxCalloc(1,sizeof(double));
4814         dBydrho = mxCalloc(1,sizeof(double));
4815         dBydtheta = mxCalloc(1,sizeof(double));
4816         d2Bydtheta2 = mxCalloc(1,sizeof(double));
4817         d2Bydthetadrho = mxCalloc(1,sizeof(double));
4818         d2Bydrho2 = mxCalloc(1,sizeof(double));
4819         ppvald_2D(rayequil.By_fit,rayparam.dS[0],0.25,0.2,By,dBydrho,dBydtheta,d2Bydtheta2,d2Bydthetadrho,d2Bydrho2);
4820         mexPrintf("By(0.25,0.2),dBydrho(0.25,0.2),dBydtheta(0.25,0.2) (T): %g,%g,%g\n",By[0],dBydrho[0],dBydtheta[0]);
4821         mexPrintf("d2Bydthetadrho(0.25,0.2),d2Bydtheta2(0.25,0.2),d2Bydrho2(0.25,0.2) (m): %g,%g,%g\n",d2Bydthetadrho[0],d2Bydtheta2[0],d2Bydrho2[0]);
4822         mxFree(By);
4823         mxFree(dBydrho);
4824         mxFree(dBydtheta);
4825         mxFree(d2Bydtheta2);
4826         mxFree(d2Bydthetadrho);
4827         mxFree(d2Bydrho2);
4828         
4829         Bz = mxCalloc(1,sizeof(double));
4830         dBzdrho = mxCalloc(1,sizeof(double));
4831         dBzdtheta = mxCalloc(1,sizeof(double));
4832         d2Bzdtheta2 = mxCalloc(1,sizeof(double));
4833         d2Bzdthetadrho = mxCalloc(1,sizeof(double));
4834         d2Bzdrho2 = mxCalloc(1,sizeof(double));
4835         ppvald_2D(rayequil.Bz_fit,rayparam.dS[0],0.25,0.2,Bz,dBzdrho,dBzdtheta,d2Bzdtheta2,d2Bzdthetadrho,d2Bzdrho2);
4836         mexPrintf("Bz(0.25,0.2),dBzdrho(0.25,0.2),dBzdtheta(0.25,0.2) (T): %g,%g,%g\n",Bz[0],dBzdrho[0],dBzdtheta[0]);
4837         mexPrintf("d2Bzdthetadrho(0.25,0.2),d2Bzdtheta2(0.25,0.2),d2Bzdrho2(0.25,0.2) (m): %g,%g,%g\n",d2Bzdthetadrho[0],d2Bzdtheta2[0],d2Bzdrho2[0]);
4838         mxFree(Bz);
4839         mxFree(dBzdrho);
4840         mxFree(dBzdtheta);
4841         mxFree(d2Bzdtheta2);
4842         mxFree(d2Bzdthetadrho);
4843         mxFree(d2Bzdrho2);
4844         
4845         
4846         if (flag_f0 == 1) {/*Wave aborption is calculated with a non-Maxwellian distribution function */
4847             
4848             mexPrintf("----------------------------------------\n");
4849             mexPrintf("tol : %g\n",rayparam.tol[0]);
4850             mexPrintf("zZi(2) : %g\n",equilparam.zZi[1]);
4851             
4852             mexPrintf("----------------------------------------\n");
4853             mexPrintf("Wave aborption is calculated with a non-Maxwellian distribution function.\n");
4854             mexPrintf("----------------------------------------\n");
4855             mexPrintf("npn, pn(1),pn(end) : %d,%g,%g\n",distriparam.npn[0],distriparam.pn[0],distriparam.pn[distriparam.npn[0]-1]);
4856             mexPrintf("nmhu, mhu(1),mhu(end) : %d,%g,%g\n",distriparam.nmhu[0],distriparam.mhu[0],distriparam.mhu[distriparam.nmhu[0]-1]);
4857             mexPrintf("ne_ref, betath_ref : %g,%g\n",distriparam.ne_ref[0],distriparam.betath_ref[0]);
4858             
4859             mexPrintf("----------------------------------------\n");
4860             mexPrintf("f0_fit.coefs_f(1): %g\n",raydistri.f0_fit.coefs_f[0]);
4861             mexPrintf("f0_fit.coefs_dfdrho(1): %g\n",raydistri.f0_fit.coefs_dfdrho[0]);
4862             mexPrintf("f0_fit.coefs_d2fdrho2(1): %g\n",raydistri.f0_fit.coefs_d2fdrho2[0]);
4863             
4864             mexPrintf("----------------------------------------\n");
4865             
4866             for (ip = 0; ip < distriparam.npn[0]; ip++) {
4867                 if (distriparam.pn[ip] < 4.0) ip_ref = ip;/*seek for the index of the closest value of pn less than 4.0 */
4868             }
4869             
4870             for (jm = 0; jm < distriparam.nmhu[0]; jm++) {
4871                 if (distriparam.mhu[jm] < 0.5) jm_ref = jm;/*seek for the index of the closest value of mhu less than 0.5 */
4872             }
4873             
4874             mexPrintf("ip_ref,pn(ip_ref): %d,%g\n",ip_ref,distriparam.pn[ip_ref]);
4875             mexPrintf("jm_ref,mhu(jm_ref): %d,%g\n",jm_ref,distriparam.mhu[jm_ref]);
4876             
4877             f0_fit = mxCalloc(distriparam.npn[0]*distriparam.nmhu[0],sizeof(double));
4878             df0drho_fit = mxCalloc(distriparam.npn[0]*distriparam.nmhu[0],sizeof(double));
4879             d2f0drho2_fit = mxCalloc(distriparam.npn[0]*distriparam.nmhu[0],sizeof(double));
4880             ppvald_1D(raydistri.f0_fit,rayparam.dS[0],0.25,f0_fit,df0drho_fit,d2f0drho2_fit);
4881             
4882             mexPrintf("f0_fit(ip_ref,jm_ref,rho=0.25): %g\n",f0_fit[jm_ref*distriparam.npn[0]+ip_ref]);
4883             mxFree(f0_fit);
4884             mxFree(df0drho_fit);
4885             mxFree(d2f0drho2_fit);
4886             
4887             mexPrintf("----------------------------------------\n");
4888             mexPrintf("PSI_fit.nfourier: %g\n",raydistri.PSI_fit.dim_dbndrho[0]);
4889             mexPrintf("PSI_fit.coefs_bn(1): %g\n",raydistri.PSI_fit.coefs_bn[0]);
4890             mexPrintf("PSI_fit.coefs_dbndrho(1): %g\n",raydistri.PSI_fit.coefs_dbndrho[0]);
4891             
4892             PSI_fit = mxCalloc(1,sizeof(double));
4893             ppvald_2D(raydistri.PSI_fit,rayparam.dS[0],0.25,0.2,PSI_fit,&dummy1,&dummy1,&dummy1,&dummy1);
4894             mexPrintf("PSI(0.25,0.2) : %g\n",PSI_fit[0]);
4895             mxFree(PSI_fit);
4896         }
4897         
4898         if (flag_fluct == 1) {
4899             
4900             mexPrintf("----------------------------------------\n");
4901             
4902             halftanh(xm,&ht,&dht,&d2ht);
4903             mexPrintf("Fluctuations -> halftanh(x),x,f,df,d2f: %25.15g,%25.15g,%25.15g,%25.15g\n",xm,ht,dht,d2ht);
4904             halftanh(xp,&ht,&dht,&d2ht);
4905             mexPrintf("Fluctuations -> halftanh(x),x,f,df,d2f: %25.15g,%25.15g,%25.15g,%25.15g\n",xp,ht,dht,d2ht);
4906             
4907             xq = mxCalloc(1,sizeof(double));
4908             dxqdrho = mxCalloc(1,sizeof(double));
4909             L_rho = mxCalloc(1,sizeof(double));
4910             xL_theta = mxCalloc(1,sizeof(double));
4911             dxL_thetadrho = mxCalloc(1,sizeof(double));
4912             xL_perp = mxCalloc(1,sizeof(double));
4913             dxL_perpdrho = mxCalloc(1,sizeof(double));
4914             XL_phi = mxCalloc(1,sizeof(double));
4915             dXL_phidrho = mxCalloc(1,sizeof(double));
4916             dXL_phidtheta = mxCalloc(1,sizeof(double));
4917             ppvald_0D(rayfluctuations.L_rho,L_rho);
4918             ppvald_1D(rayfluctuations.xq_fit,rayparam.dS[0],0.25,xq,dxqdrho,&dummy1);
4919             ppvald_1D(rayfluctuations.xL_theta_fit,rayparam.dS[0],0.25,xL_theta,dxL_thetadrho,&dummy1);
4920             ppvald_1D(rayfluctuations.xL_perp_fit,rayparam.dS[0],0.25,xL_perp,dxL_perpdrho,&dummy1);
4921             ppvald_2D(rayfluctuations.XL_phi_fit,rayparam.dS[0],0.25,0.2,XL_phi,dXL_phidrho,dXL_phidtheta,&dummy1,&dummy2);
4922             mexPrintf("----------------------------------------\n");
4923             mexPrintf("Fluctuations -> xq(0.25),dxqdrho(0.25): %g,%g\n",xq[0],dxqdrho[0]);
4924             mexPrintf("Fluctuations -> L_rho: %g\n",L_rho[0]);
4925             mexPrintf("Fluctuations -> xL_theta(0.25),dxL_thetadrho(0.25): %g,%g\n",xL_theta[0],dxL_thetadrho[0]);
4926             mexPrintf("Fluctuations -> xL_perp(0.25),dxL_perpdrho(0.25): %g,%g\n",xL_perp[0],dxL_perpdrho[0]);
4927             mexPrintf("Fluctuations -> XL_phi(0.25,0.2),dXL_phidrho(0.25,0.2),dXL_phidtheta(0.25,0.2): %g,%g,%g\n",XL_phi[0],dXL_phidrho[0],dXL_phidtheta[0]);
4928             mexPrintf("----------------------------------------\n");
4929             mxFree(xq);
4930             mxFree(dxqdrho);
4931             mxFree(L_rho);
4932             mxFree(xL_theta);
4933             mxFree(dxL_thetadrho);
4934             mxFree(xL_perp);
4935             mxFree(dxL_perpdrho);
4936             mxFree(XL_phi);
4937             mxFree(dXL_phidrho);
4938             mxFree(dXL_phidtheta);
4939             
4940             if (fluctparam.ne_nmodel[0]) {
4941                 mexPrintf("----------------------------------------\n");
4942                 mexPrintf("Fluctuations -> nmodel for ne: %d\n",fluctparam.ne_nmodel[0]);
4943                 for (jf=0; jf < fluctparam.ne_nmodel[0]; jf++) {
4944                     mexPrintf("--------------------------\n");
4945                     mexPrintf("Fluctuations for ne -> model(%d): %g\n",jf,fluctparam.ne_model[jf][0]);
4946                     if (fluctparam.ne_sigmar_max[jf] != NULL) mexPrintf("Fluctuations for ne -> ne_sigmar_max(%d): %g\n",0,fluctparam.ne_sigmar_max[jf][0]);
4947                     if (fluctparam.ne_sigmar_hwhm[jf] != NULL) mexPrintf("Fluctuations for ne -> ne_sigmar_hwhm(%d): %g\n",0,fluctparam.ne_sigmar_hwhm[jf][0]);
4948                     if (fluctparam.ne_sigmar_rho[jf] != NULL) mexPrintf("Fluctuations for ne -> ne_sigmar_rho(%d): %g\n",0,fluctparam.ne_sigmar_rho[jf][0]);
4949                     if (fluctparam.ne_polmode[jf] != NULL) mexPrintf("Fluctuations for ne -> ne_polmode(%d): %g\n",0,fluctparam.ne_polmode[jf][0]);
4950                     if (fluctparam.ne_epsi_rho[jf] != NULL) mexPrintf("Fluctuations for ne -> ne_epsi_rho(%d): %g\n",0,fluctparam.ne_epsi_rho[jf][0]);
4951                     if (fluctparam.ne_epsi_theta[jf] != NULL) mexPrintf("Fluctuations for ne -> ne_epsi_theta(%d): %g\n",0,fluctparam.ne_epsi_theta[jf][0]);
4952                     if (fluctparam.ne_epsi_phi[jf] != NULL) mexPrintf("Fluctuations for ne -> ne_epsi_phi(%d): %g\n",0,fluctparam.ne_epsi_phi[jf][0]);
4953                     if (fluctparam.ne_lmin[jf] != NULL) mexPrintf("Fluctuations for ne -> ne_lmin(%d): %g\n",0,fluctparam.ne_lmin[jf][0]);
4954                     if (fluctparam.ne_mmin[jf] != NULL) mexPrintf("Fluctuations for ne -> ne_mmin(%d): %g\n",0,fluctparam.ne_mmin[jf][0]);
4955                     if (fluctparam.ne_nmin[jf] != NULL) mexPrintf("Fluctuations for ne -> ne_nmin(%d): %g\n",0,fluctparam.ne_nmin[jf][0]);
4956                     if (fluctparam.ne_lmax[jf] != NULL) mexPrintf("Fluctuations for ne -> ne_lmax(%d): %g\n",0,fluctparam.ne_lmax[jf][0]);
4957                     if (fluctparam.ne_mmax[jf] != NULL) mexPrintf("Fluctuations for ne -> ne_mmax(%d): %g\n",0,fluctparam.ne_mmax[jf][0]);
4958                     if (fluctparam.ne_nmax[jf] != NULL) mexPrintf("Fluctuations for ne -> ne_nmax(%d): %g\n",0,fluctparam.ne_nmax[jf][0]);
4959                     if (fluctparam.ne_phase[jf] != NULL) mexPrintf("Fluctuations for ne -> phase(%d)(end): %g\n",jf,fluctparam.ne_phase[jf][fluctparam.ne_nphase[jf][0]-1]);
4960                     
4961                 }
4962             } else {
4963                 mexPrintf("Fluctuations -> no model for ne\n");
4964             }
4965             
4966             if (fluctparam.B_nmodel[0]) {
4967                 mexPrintf("----------------------------------------\n");
4968                 mexPrintf("Fluctuations -> nmodel for B: %d\n",fluctparam.B_nmodel[0]);
4969                 for (jf=0; jf < fluctparam.B_nmodel[0]; jf++) {
4970                     mexPrintf("--------------------------\n");
4971                     mexPrintf("Fluctuations for B -> model(%d): %g\n",jf,fluctparam.B_model[jf][0]);
4972                     if (fluctparam.B_sigmar_max[jf] != NULL) mexPrintf("Fluctuations for B -> B_sigmar_max(%d): %g\n",0,fluctparam.B_sigmar_max[jf][0]);
4973                     if (fluctparam.B_sigmar_hwhm[jf] != NULL) mexPrintf("Fluctuations for B -> B_sigmar_hwhm(%d): %g\n",0,fluctparam.B_sigmar_hwhm[jf][0]);
4974                     if (fluctparam.B_sigmar_rho[jf] != NULL) mexPrintf("Fluctuations for B -> B_sigmar_rho(%d): %g\n",0,fluctparam.B_sigmar_rho[jf][0]);
4975                     if (fluctparam.B_polmode[jf] != NULL) mexPrintf("Fluctuations for B -> B_polmode(%d): %g\n",0,fluctparam.B_polmode[jf][0]);
4976                     if (fluctparam.B_epsi_rho[jf] != NULL) mexPrintf("Fluctuations for B -> B_epsi_rho(%d): %g\n",0,fluctparam.B_epsi_rho[jf][0]);
4977                     if (fluctparam.B_epsi_theta[jf] != NULL) mexPrintf("Fluctuations for B -> B_epsi_theta(%d): %g\n",0,fluctparam.B_epsi_theta[jf][0]);
4978                     if (fluctparam.B_epsi_phi[jf] != NULL) mexPrintf("Fluctuations for B -> B_epsi_phi(%d): %g\n",0,fluctparam.B_epsi_phi[jf][0]);
4979                     if (fluctparam.B_lmin[jf] != NULL) mexPrintf("Fluctuations for B -> B_lmin(%d): %g\n",0,fluctparam.B_lmin[jf][0]);
4980                     if (fluctparam.B_mmin[jf] != NULL) mexPrintf("Fluctuations for B -> B_mmin(%d): %g\n",0,fluctparam.B_mmin[jf][0]);
4981                     if (fluctparam.B_nmin[jf] != NULL) mexPrintf("Fluctuations for B -> B_nmin(%d): %g\n",0,fluctparam.B_nmin[jf][0]);
4982                     if (fluctparam.B_lmax[jf] != NULL) mexPrintf("Fluctuations for B -> B_lmax(%d): %g\n",0,fluctparam.B_lmax[jf][0]);
4983                     if (fluctparam.B_mmax[jf] != NULL) mexPrintf("Fluctuations for B -> B_mmax(%d): %g\n",0,fluctparam.B_mmax[jf][0]);
4984                     if (fluctparam.B_nmax[jf] != NULL) mexPrintf("Fluctuations for B -> B_nmax(%d): %g\n",0,fluctparam.B_nmax[jf][0]);
4985                     if (fluctparam.B_phase[jf] != NULL) mexPrintf("Fluctuations for B -> phase(%d)(end): %g\n",jf,fluctparam.B_phase[jf][fluctparam.B_nphase[jf][0]-1]);
4986                     
4987                     if (rayfluctuations.B_sfx_fit[jf].dim_a0 != NULL) {
4988                         mexPrintf("--------------------------\n");
4989                         sfx = mxCalloc(1,sizeof(double));
4990                         dsfxdrho = mxCalloc(1,sizeof(double));
4991                         dsfxdtheta = mxCalloc(1,sizeof(double));
4992                         ppvald_2D(rayfluctuations.B_sfx_fit[jf],rayparam.dS[0],0.25,0.2,sfx,dsfxdrho,dsfxdtheta,&dummy1,&dummy2,&dummy3);
4993                         mexPrintf("B -> Xfx(0.25,0.2),dXfxdrho(0.25,0.2),dXfxdtheta(0.25,0.2): %g,%g,%g\n",sfx[0],dsfxdrho[0],dsfxdtheta[0]);
4994                         mxFree(sfx);
4995                         mxFree(dsfxdrho);
4996                         mxFree(dsfxdtheta);
4997                     }
4998                     
4999                     if (rayfluctuations.B_sfy_fit[jf].dim_a0 != NULL) {
5000                         sfy = mxCalloc(1,sizeof(double));
5001                         dsfydrho = mxCalloc(1,sizeof(double));
5002                         dsfydtheta = mxCalloc(1,sizeof(double));
5003                         ppvald_2D(rayfluctuations.B_sfy_fit[jf],rayparam.dS[0],0.25,0.2,sfy,dsfydrho,dsfydtheta,&dummy1,&dummy2,&dummy3);
5004                         mexPrintf("B -> Xfy(0.25,0.2),dXfydrho(0.25,0.2),dXfydtheta(0.25,0.2): %g,%g,%g\n",sfy[0],dsfydrho[0],dsfydtheta[0]);
5005                         mxFree(sfy);
5006                         mxFree(dsfydrho);
5007                         mxFree(dsfydtheta);
5008                     }
5009                     
5010                     if (rayfluctuations.B_sfz_fit[jf].dim_a0 != NULL) {
5011                         sfz = mxCalloc(1,sizeof(double));
5012                         dsfzdrho = mxCalloc(1,sizeof(double));
5013                         dsfzdtheta = mxCalloc(1,sizeof(double));
5014                         ppvald_2D(rayfluctuations.B_sfz_fit[jf],rayparam.dS[0],0.25,0.2,sfz,dsfzdrho,dsfzdtheta,&dummy1,&dummy2,&dummy3);
5015                         mexPrintf("B -> Xfz(0.25,0.2),dXfzdrho(0.25,0.2),dXfzdtheta(0.25,0.2): %g,%g,%g\n",sfz[0],dsfzdrho[0],dsfzdtheta[0]);
5016                         mxFree(sfz);
5017                         mxFree(dsfzdrho);
5018                         mxFree(dsfzdtheta);
5019                     }
5020                     
5021                 }
5022             } else {
5023                 mexPrintf("Fluctuations -> no model for B\n");
5024             }
5025         }
5026     } else {
5027         if (rayparam.testmode[0]) {/* for tests if necessary */
5028             
5029             ytest[0] = 0.25;
5030             ytest[1] = 0.2;
5031             
5032             interpequil_test(raymagnetic,rayprofiles,equilparam,ytest,flag);
5033             
5034             mexPrintf("Bessel functions -> J0(0.5),J1(0.5),J2(0.5): %g,%g,%d\n",j0(0.5),j1(0.5),jn(2,0.5));
5035             
5036             mexPrintf("tol : %g\n",rayparam.tol[0]);
5037             
5038             mexPrintf("zZi(1),zmi(1) : %g,%g\n",equilparam.zZi[0],equilparam.zmi[0]);
5039             mexPrintf("zZi(2),zmi(2) : %g,%g\n",equilparam.zZi[1],equilparam.zmi[1]);
5040             mexPrintf("ns : %d\n",equilparam.ns[0]);
5041             mexPrintf("Rp,ap,Zp,psia_apRp : %g,%g,%g,%g\n",equilparam.Rp[0],equilparam.ap[0],equilparam.Zp[0],equilparam.psia_apRp[0]);
5042             mexPrintf("--------------\n");
5043             
5044             if (equilparam.zZi[0] > 0) {
5045                 mexPrintf("Te(0.25),dTedrho(0.25) (keV): %g,%g\n",rayprofiles.Te[0],rayprofiles.dTedY[0]);
5046                 mexPrintf("ne(0.25),dnedrho(0.25) (10+19 m-3): %g,%g\n",rayprofiles.ne[0]/1e19,rayprofiles.dnedY[0]/1e19);
5047                 mexPrintf("zTi(2,0.25),dzTidrho(2,0.25) (keV): %g,%g\n",rayprofiles.zTi[0],rayprofiles.dzTidY[0][0]);
5048                 mexPrintf("zni(2,0.25),dznidrho(2,0.25) (10+19 m-3): %g,%g\n",rayprofiles.zni[0]/1e19,rayprofiles.dznidY[0][0]/1e19);
5049             }
5050             
5051             mexPrintf("xn(0.25,0.2),dxndrho(0.25,0.2),dxndtheta(0.25,0.2) (m): %g,%g,%g\n",raymagnetic.xn[0],raymagnetic.dxndY[0],raymagnetic.dxndY[1]);
5052             mexPrintf("yn(0.25,0.2),dyndrho(0.25,0.2),dyndtheta(0.25,0.2) (m): %g,%g,%g\n",raymagnetic.yn[0],raymagnetic.dyndY[0],raymagnetic.dyndY[1]);
5053             mexPrintf("Bsn(0.25,0.2),dBsndrho(0.25,0.2),dBsndtheta(0.25,0.2) (T): %g,%g,%g\n",raymagnetic.Bsn[0],raymagnetic.dBsndY[0],raymagnetic.dBsndY[1]);
5054             mexPrintf("Bzn(0.25,0.2),dBzndrho(0.25,0.2),dBzndtheta(0.25,0.2) (T): %g,%g,%g\n",raymagnetic.Bzn[0],raymagnetic.dBzndY[0],raymagnetic.dBzndY[1]);
5055             mexPrintf("B(0.25,0.2),dBdrho(0.25,0.2),dBdtheta(0.25,0.2) (T): %g,%g,%g\n",raymagnetic.B[0],raymagnetic.dBdY[0],raymagnetic.dBdY[1]);
5056             mexPrintf("salpha(0.25,0.2),dsalphadrho(0.25,0.2),dsalphadtheta(0.25,0.2) (T): %g,%g,%g\n",raymagnetic.salpha[0],raymagnetic.dsalphadY[0],raymagnetic.dsalphadY[1]);
5057             mexPrintf("calpha(0.25,0.2),dcalphadrho(0.25,0.2),dcalphadtheta(0.25,0.2) (T): %g,%g,%g\n",raymagnetic.calpha[0],raymagnetic.dcalphadY[0],raymagnetic.dcalphadY[1]);
5058             mexPrintf("gradrhon(0.25,0.2),dgradrhondrho(0.25,0.2),dgradrhondtheta(0.25,0.2) (T): %g,%g,%g\n",raymagnetic.gradrhon[0],raymagnetic.dgradrhondY[0],raymagnetic.dgradrhondY[1]);
5059             
5060             /*interpequil_test(raymagnetic,rayprofiles,equilparam,y0_in,flag); */
5061         }
5062         
5063         
5064     }
5065 }
5066 
5067 void halftanh(x,f,df,d2f)
5068 double x,*f,*df,*d2f;
5069 {
5070     if (x >= 0.0) {
5071         *f = x;
5072         *df = 1.0;
5073         *d2f = 0.0;
5074     } else {
5075         if (x < -400) {
5076             *f = -1;
5077             *df = 0;
5078             *d2f = 0;
5079         } else {
5080             *f = tanh(x);
5081             *df = 1.0/cosh(x)/cosh(x);
5082             *d2f = -2.0*df[0]*sinh(x)/cosh(x);
5083         }
5084     }
5085 }
5086 
5087 /*Minizimation schemes giving out rho from (x0,y0) */
5088 
5089 void rho1D_dichotomy(rayequil_format rayequil,rayparam_format rayparam, equilparam_format equilparam, double *rho,double *theta,double *Y)
5090 {
5091     double down[2],up[2],res[2];
5092     down[0]=0;
5093     up[0]=1;
5094     double dummy,x,y,dxdrho,dydrho;
5095     int k = 0;
5096     res[1]=1;
5097     int kmax = 60;
5098     double prec = 1e-10;
5099     while(k < kmax && fabs(res[1]) > prec)
5100     {
5101         k = k +1;
5102         
5103         res[0] = (down[0] + up[0])/2;
5104         
5105         ppvald_2D(rayequil.x_fit,rayparam.dS[0],down[0],theta[0],&x,&dxdrho,&dummy,&dummy,&dummy,&dummy);
5106         ppvald_2D(rayequil.y_fit,rayparam.dS[0],down[0],theta[0],&y,&dydrho,&dummy,&dummy,&dummy,&dummy);
5107         x=x/equilparam.ap[0];/*Mandatory normalization*/
5108         y=y/equilparam.ap[0];/*Mandatory normalization*/
5109         dxdrho=dxdrho/equilparam.ap[0];/*Mandatory normalization*/
5110         dydrho=dydrho/equilparam.ap[0];/*Mandatory normalization*/
5111         down[1] = dxdrho*(x-Y[0]) + dydrho*(y - Y[1]);
5112         
5113         ppvald_2D(rayequil.x_fit,rayparam.dS[0],res[0],theta[0],&x,&dxdrho,&dummy,&dummy,&dummy,&dummy);
5114         ppvald_2D(rayequil.y_fit,rayparam.dS[0],res[0],theta[0],&y,&dydrho,&dummy,&dummy,&dummy,&dummy);
5115         x=x/equilparam.ap[0];/*Mandatory normalization*/
5116         y=y/equilparam.ap[0];/*Mandatory normalization*/
5117         dxdrho=dxdrho/equilparam.ap[0];/*Mandatory normalization*/
5118         dydrho=dydrho/equilparam.ap[0];/*Mandatory normalization*/
5119         res[1] = dxdrho*(x-Y[0]) + dydrho*(y - Y[1]);
5120         
5121         if(down[1]*res[1]>0)
5122         {
5123             down[0]=res[0];
5124         }
5125         else
5126         {
5127             up[0]=res[0];
5128         }
5129     }
5130     rho[0]=res[0];
5131 }
5132 
5133 void rho1D_newton_numeric(rayequil_format rayequil,rayparam_format rayparam, equilparam_format equilparam, double *rho,double *theta,double *Y)
5134 {
5135     double down[2],res[2];
5136     down[0]=0.05;
5137     res[0]=0.05000000000001;
5138     double dummy,x,y,dxdrho,dydrho;
5139     int k = 0;
5140     res[1]=1;
5141     int kmax = 10;
5142     double prec = 1e-10;
5143     double save1,save2;
5144     while(k < kmax && fabs(res[1]) > prec)
5145     {
5146         ppvald_2D(rayequil.x_fit,rayparam.dS[0],down[0],theta[0],&x,&dxdrho,&dummy,&dummy,&dummy,&dummy,&dummy);
5147         ppvald_2D(rayequil.y_fit,rayparam.dS[0],down[0],theta[0],&y,&dydrho,&dummy,&dummy,&dummy,&dummy,&dummy);
5148         
5149         x=x/equilparam.ap[0];/*Mandatory normalization*/
5150         y=y/equilparam.ap[0];/*Mandatory normalization*/
5151         dxdrho=dxdrho/equilparam.ap[0];/*Mandatory normalization*/
5152         dydrho=dydrho/equilparam.ap[0];/*Mandatory normalization*/
5153         
5154         down[1] = dxdrho*(x-Y[0]) + dydrho*(y - Y[1]);
5155         
5156         ppvald_2D(rayequil.x_fit,rayparam.dS[0],res[0],theta[0],&x,&dxdrho,&dummy,&dummy,&dummy,&dummy,&dummy);
5157         ppvald_2D(rayequil.y_fit,rayparam.dS[0],res[0],theta[0],&y,&dydrho,&dummy,&dummy,&dummy,&dummy,&dummy);
5158         
5159         x=x/equilparam.ap[0];/*Mandatory normalization*/
5160         y=y/equilparam.ap[0];/*Mandatory normalization*/
5161         dxdrho=dxdrho/equilparam.ap[0];/*Mandatory normalization*/
5162         dydrho=dydrho/equilparam.ap[0];/*Mandatory normalization*/
5163         
5164         res[1] = dxdrho*(x-Y[0]) + dydrho*(y - Y[1]);
5165         
5166         save1 = res[0];
5167         save2 = res[1];
5168         res[0] = res[0] - res[1]*((res[0] - down[0])/(res[1] - down[1]));
5169         down[0] = save1;
5170         down[1] = save2;
5171         
5172         k = k +1;
5173         
5174     }
5175     rho[0]=res[0];
5176 }
5177 
5178 void rho1D_newton_analytic(rayequil_format rayequil,rayparam_format rayparam, equilparam_format equilparam, double *rho,double *theta,double *Y)
5179 {
5180     double res[3];
5181     
5182     res[0]=0.05;/*res[0]=rho, res[1] = d(distance^2/2)/drho, res[2]= d2(distance^2/2)drho2*/
5183     double dummy,x,y,dxdrho,dydrho,d2xdrho2,d2ydrho2;
5184     int k = 0;
5185     res[1]=1;
5186     int kmax = 10;
5187     double prec = 1e-9;
5188     while(k < kmax && fabs(res[1]) > prec)
5189     {
5190         ppvald_2D(rayequil.x_fit,rayparam.dS[0],res[0],theta[0],&x,&dxdrho,&dummy,&dummy,&dummy,&d2xdrho2);
5191         ppvald_2D(rayequil.y_fit,rayparam.dS[0],res[0],theta[0],&y,&dydrho,&dummy,&dummy,&dummy,&d2ydrho2);
5192         
5193         x=x/equilparam.ap[0];/*Mandatory normalization*/
5194         y=y/equilparam.ap[0];/*Mandatory normalization*/
5195         dxdrho=dxdrho/equilparam.ap[0];/*Mandatory normalization*/
5196         dydrho=dydrho/equilparam.ap[0];/*Mandatory normalization*/
5197         d2xdrho2=d2xdrho2/equilparam.ap[0];/*Mandatory normalization*/
5198         d2ydrho2=d2ydrho2/equilparam.ap[0];/*Mandatory normalization*/
5199         
5200         res[1] = dxdrho*(x-Y[0]) + dydrho*(y - Y[1]);
5201         
5202         res[2] = d2xdrho2*(x-Y[0]) + d2ydrho2*(y - Y[1]) + pow(dxdrho,2) + pow(dydrho,2);
5203         
5204         res[0] = res[0] - res[1]/res[2];
5205         
5206         k = k + 1;
5207     }
5208     rho[0]=res[0];
5209 }
5210 
5211 /*Minizimation schemes giving out rho and precise theta from (x0,y0) */
5212 
5213 void substitution_dichotomy_1D(rayequil_format rayequil,rayparam_format rayparam, equilparam_format equilparam, double *rho,double *theta,double *Y)
5214 {
5215     theta[0] = atan2(Y[1],Y[0]);
5216     rho1D_dichotomy(rayequil,rayparam,equilparam,rho,theta,Y);
5217 }
5218 
5219 void substitution_dichotomy_2D(rayequil_format rayequil,rayparam_format rayparam, equilparam_format equilparam, double *rho,double *theta,double *Y)
5220 {
5221     theta[0] = atan2(Y[1],Y[0]);
5222     double down_t[2],up_t[2],res_t[2];
5223     res_t[0] = theta[0];
5224     down_t[0] = theta[0]*0.9;
5225     up_t[0] = theta[0]*1.1;
5226     double dummy,x,y,dxdtheta,dydtheta,rho_d,rho_m;
5227     int k=0;
5228     int kmax = 60;
5229     double prec = 1e-11;
5230     res_t[1] = 1;
5231     while(k < kmax && fabs(res_t[1]) > prec)
5232     {
5233         k = k + 1;
5234         res_t[0] = (down_t[0] + up_t[0])/2;
5235         rho1D_dichotomy(rayequil,rayparam,equilparam,&rho_d,&down_t[0],Y);
5236         rho1D_dichotomy(rayequil,rayparam,equilparam,&rho_m,&res_t[0],Y);
5237         
5238         ppvald_2D(rayequil.x_fit,rayparam.dS[0],rho_d,down_t[0],&x,&dummy,&dxdtheta,&dummy,&dummy,&dummy);
5239         ppvald_2D(rayequil.y_fit,rayparam.dS[0],rho_d,down_t[0],&y,&dummy,&dydtheta,&dummy,&dummy,&dummy);
5240         x=x/equilparam.ap[0];/*Mandatory normalization*/
5241         y=y/equilparam.ap[0];/*Mandatory normalization*/
5242         dxdtheta=dxdtheta/equilparam.ap[0];/*Mandatory normalization*/
5243         dydtheta=dydtheta/equilparam.ap[0];/*Mandatory normalization*/
5244         down_t[1] = dxdtheta*(x-Y[0]) + dydtheta*(y-Y[1]);
5245         
5246         ppvald_2D(rayequil.x_fit,rayparam.dS[0],rho_m,res_t[0],&x,&dummy,&dxdtheta,&dummy,&dummy,&dummy);
5247         ppvald_2D(rayequil.y_fit,rayparam.dS[0],rho_m,res_t[0],&y,&dummy,&dydtheta,&dummy,&dummy,&dummy);
5248         x=x/equilparam.ap[0];/*Mandatory normalization*/
5249         y=y/equilparam.ap[0];/*Mandatory normalization*/
5250         dxdtheta=dxdtheta/equilparam.ap[0];/*Mandatory normalization*/
5251         dydtheta=dydtheta/equilparam.ap[0];/*Mandatory normalization*/
5252         res_t[1] = dxdtheta*(x-Y[0]) + dydtheta*(y-Y[1]);
5253         
5254         if(down_t[1]*res_t[1]>0)
5255         {
5256             down_t[0] = res_t[0];
5257         }
5258         else
5259         {
5260             up_t[0] = res_t[0];
5261         }
5262     }
5263     theta[0] = res_t[0];
5264     rho1D_dichotomy(rayequil,rayparam,equilparam,rho,theta,Y);
5265 }
5266 
5267 void substitution_newton_numeric_1D(rayequil_format rayequil,rayparam_format rayparam, equilparam_format equilparam, double *rho,double *theta,double *Y)
5268 {
5269     theta[0] = atan2(Y[1],Y[0]);
5270     rho1D_newton_numeric(rayequil,rayparam,equilparam,rho,theta,Y);
5271 
5272 }
5273 
5274 void substitution_newton_numeric_2D(rayequil_format rayequil,rayparam_format rayparam, equilparam_format equilparam, double *rho,double *theta,double *Y)
5275 {
5276     theta[0] = atan2(Y[1],Y[0]);
5277     double down_t[2],res_t[2];
5278     double dummy,x,y,dxdtheta,dydtheta,rho_d,rho_m;
5279     down_t[0] = theta[0];
5280     
5281     rho1D_newton_numeric(rayequil,rayparam,equilparam,&rho_d,&down_t[0],Y);
5282     ppvald_2D(rayequil.x_fit,rayparam.dS[0],rho_d,down_t[0],&x,&dummy,&dxdtheta,&dummy,&dummy,&dummy,&dummy);
5283     ppvald_2D(rayequil.y_fit,rayparam.dS[0],rho_d,down_t[0],&y,&dummy,&dydtheta,&dummy,&dummy,&dummy,&dummy);
5284     x=x/equilparam.ap[0];/*Mandatory normalization*/
5285     y=y/equilparam.ap[0];/*Mandatory normalization*/
5286     dxdtheta=dxdtheta/equilparam.ap[0];/*Mandatory normalization*/
5287     dydtheta=dydtheta/equilparam.ap[0];/*Mandatory normalization*/
5288     down_t[1] = dxdtheta*(x-Y[0]) + dydtheta*(y-Y[1]);
5289     
5290     res_t[0] = 1.0000000000001*down_t[0];
5291     int kt=0;
5292     int ktmax = 10;
5293     double prec = 1e-11;
5294     res_t[1] = 1;
5295     double save1,save2;
5296     while(kt < ktmax && fabs(res_t[1]) > prec)
5297     {
5298         rho1D_newton_numeric(rayequil,rayparam,equilparam,&rho_m,&res_t[0],Y);
5299         ppvald_2D(rayequil.x_fit,rayparam.dS[0],rho_m,res_t[0],&x,&dummy,&dxdtheta,&dummy,&dummy,&dummy,&dummy);
5300         ppvald_2D(rayequil.y_fit,rayparam.dS[0],rho_m,res_t[0],&y,&dummy,&dydtheta,&dummy,&dummy,&dummy,&dummy);
5301         x=x/equilparam.ap[0];/*Mandatory normalization*/
5302         y=y/equilparam.ap[0];/*Mandatory normalization*/
5303         dxdtheta=dxdtheta/equilparam.ap[0];/*Mandatory normalization*/
5304         dydtheta=dydtheta/equilparam.ap[0];/*Mandatory normalization*/
5305         res_t[1] = dxdtheta*(x-Y[0]) + dydtheta*(y-Y[1]);
5306         
5307         save1 = res_t[0];
5308         save2 = res_t[1];
5309         res_t[0] = res_t[0] - res_t[1]*((res_t[0] - down_t[0])/(res_t[1] - down_t[1]));
5310         down_t[0] = save1;
5311         down_t[1] = save2;
5312         
5313         kt = kt + 1;
5314         
5315     }
5316     theta[0] = res_t[0];
5317     rho1D_newton_numeric(rayequil,rayparam,equilparam,rho,theta,Y);
5318 }
5319 
5320 void substitution_newton_analytic_1D(rayequil_format rayequil,rayparam_format rayparam, equilparam_format equilparam, double *rho,double *theta,double *Y)
5321 {
5322     theta[0] = atan2(Y[1],Y[0]);
5323     rho1D_newton_analytic(rayequil,rayparam,equilparam,rho,theta,Y);
5324 }
5325 
5326 void substitution_newton_analytic_2D(rayequil_format rayequil,rayparam_format rayparam, equilparam_format equilparam, double *rho,double *theta,double *Y)
5327 {
5328     theta[0] = atan2(Y[1],Y[0]);
5329     double res_t[3];/*res_t[0]=theta, res_t[1]=d(distance^2/2)dtheta, res_t[2]=d2(distance^2/2)dtheta2*/
5330     res_t[0] = theta[0];
5331     double dummy,x,y,dxdtheta,dydtheta,d2xdtheta2,d2ydtheta2,rho_s;
5332     int kt=0;
5333     int ktmax = 15;
5334     double prec = 1e-9;
5335     res_t[1] = 1;
5336     while(kt < ktmax && fabs(res_t[1]) > prec)
5337     {
5338         rho1D_newton_analytic(rayequil,rayparam,equilparam,&rho_s,&res_t[0],Y);
5339         
5340         ppvald_2D(rayequil.x_fit,rayparam.dS[0],rho_s,res_t[0],&x,&dummy,&dxdtheta,&d2xdtheta2,&dummy,&dummy);
5341         ppvald_2D(rayequil.y_fit,rayparam.dS[0],rho_s,res_t[0],&y,&dummy,&dydtheta,&d2ydtheta2,&dummy,&dummy);
5342         
5343         x=x/equilparam.ap[0];/*Mandatory normalization*/
5344         y=y/equilparam.ap[0];/*Mandatory normalization*/
5345         dxdtheta=dxdtheta/equilparam.ap[0];/*Mandatory normalization*/
5346         dydtheta=dydtheta/equilparam.ap[0];/*Mandatory normalization*/
5347         d2xdtheta2=d2xdtheta2/equilparam.ap[0];/*Mandatory normalization*/
5348         d2ydtheta2=d2ydtheta2/equilparam.ap[0];/*Mandatory normalization*/
5349         
5350         res_t[1] = dxdtheta*(x-Y[0]) + dydtheta*(y-Y[1]);
5351         
5352         res_t[2] = d2xdtheta2*(x-Y[0]) + d2ydtheta2*(y-Y[1]) + pow(dxdtheta,2) + pow(dydtheta,2);
5353         
5354         res_t[0] = res_t[0] - res_t[1]/res_t[2];
5355         
5356         DUMP(res_t[0]);
5357         
5358         kt = kt + 1;
5359         
5360     }
5361     theta[0] = res_t[0];
5362     rho1D_newton_analytic(rayequil,rayparam,equilparam,rho,theta,Y);
5363 }
5364 
5365 void substitution_newton_mix_2D(rayequil_format rayequil,rayparam_format rayparam, equilparam_format equilparam, double *rho,double *theta,double *Y)
5366 {
5367     theta[0] = atan2(Y[1],Y[0]);
5368     double down_t[2],res_t[2];
5369     down_t[0] = theta[0];
5370     res_t[0] = 1.00000001*down_t[0];
5371     double dummy,x,y,dxdtheta,dydtheta,rho_d,rho_m;
5372     int kt=0;
5373     int ktmax = 15;
5374     double prec = 1e-9;
5375     res_t[1] = 1;
5376     double save;
5377     
5378     rho1D_newton_analytic(rayequil,rayparam,equilparam,&rho_d,&down_t[0],Y);
5379     
5380     ppvald_2D(rayequil.x_fit,rayparam.dS[0],rho_d,down_t[0],&x,&dummy,&dxdtheta,&dummy,&dummy,&dummy);
5381     ppvald_2D(rayequil.y_fit,rayparam.dS[0],rho_d,down_t[0],&y,&dummy,&dydtheta,&dummy,&dummy,&dummy);
5382     
5383     x=x/equilparam.ap[0];/*Mandatory normalization*/
5384     y=y/equilparam.ap[0];/*Mandatory normalization*/
5385     dxdtheta=dxdtheta/equilparam.ap[0];/*Mandatory normalization*/
5386     dydtheta=dydtheta/equilparam.ap[0];/*Mandatory normalization*/
5387     down_t[1] = dxdtheta*(x-Y[0]) + dydtheta*(y-Y[1]);
5388     
5389     while(kt < ktmax && fabs(res_t[1]) > prec)
5390     {
5391         rho1D_newton_analytic(rayequil,rayparam,equilparam,&rho_m,&res_t[0],Y);
5392         
5393         ppvald_2D(rayequil.x_fit,rayparam.dS[0],rho_m,res_t[0],&x,&dummy,&dxdtheta,&dummy,&dummy,&dummy);
5394         ppvald_2D(rayequil.y_fit,rayparam.dS[0],rho_m,res_t[0],&y,&dummy,&dydtheta,&dummy,&dummy,&dummy);
5395         x=x/equilparam.ap[0];/*Mandatory normalization*/
5396         y=y/equilparam.ap[0];/*Mandatory normalization*/
5397         dxdtheta=dxdtheta/equilparam.ap[0];/*Mandatory normalization*/
5398         dydtheta=dydtheta/equilparam.ap[0];/*Mandatory normalization*/
5399         
5400         res_t[1] = dxdtheta*(x-Y[0]) + dydtheta*(y-Y[1]);
5401         
5402         save = res_t[0];
5403         res_t[0] = res_t[0] - res_t[1]*((res_t[0] - down_t[0])/(res_t[1] - down_t[1]));
5404         down_t[0] = save;
5405         down_t[1] = res_t[1];
5406         
5407         kt = kt + 1;
5408         
5409     }
5410     theta[0] = res_t[0];
5411     rho1D_newton_analytic(rayequil,rayparam,equilparam,rho,theta,Y);
5412 }
5413 
5414 void substitution(rayequil_format rayequil,rayparam_format rayparam, equilparam_format equilparam, double *rho,double *theta,double *Y)
5415 {
5416     if((int)rayparam.substitution_method[0] == 1)
5417     {
5418         substitution_dichotomy_1D(rayequil,rayparam,equilparam,rho,theta,Y);
5419     }
5420     else
5421     {
5422         if((int)rayparam.substitution_method[0] == 2)
5423         {
5424             substitution_dichotomy_2D(rayequil,rayparam,equilparam,rho,theta,Y);
5425         }
5426         else
5427         {
5428             if((int)rayparam.substitution_method[0] == 3)
5429             {
5430                 substitution_newton_numeric_1D(rayequil,rayparam,equilparam,rho,theta,Y);
5431             }
5432             else
5433             {
5434                 if((int)rayparam.substitution_method[0] == 4)
5435                 {
5436                     substitution_newton_numeric_2D(rayequil,rayparam,equilparam,rho,theta,Y);
5437                 }
5438                 else
5439                 {
5440                     if((int)rayparam.substitution_method[0] == 4)
5441                     {
5442                         substitution_newton_numeric_2D(rayequil,rayparam,equilparam,rho,theta,Y);
5443                     }
5444                     else
5445                     {
5446                         if((int)rayparam.substitution_method[0] == 5)
5447                         {
5448                             substitution_newton_analytic_1D(rayequil,rayparam,equilparam,rho,theta,Y);
5449                         }
5450                         else
5451                         {
5452                             if((int)rayparam.substitution_method[0] == 6)
5453                             {
5454                                 substitution_newton_analytic_2D(rayequil,rayparam,equilparam,rho,theta,Y);
5455                             }
5456                             else
5457                             {
5458                                 substitution_newton_mix_2D(rayequil,rayparam,equilparam,rho,theta,Y);
5459                             }
5460                         }
5461                     }
5462                 }
5463             }
5464         }
5465     }
5466 }
5467 
5468 void rhotheta2xy(rayparam_format rayparam, rayequil_format rayequil, equilparam_format equilparam, double *rho, double *theta, double *krho, double *m)/*Subfunction giving the cartesian from the curvilinear generalized vector, need to give each relevant components separately*/
5469 {
5470     double *save;
5471     save = mxCalloc(4,sizeof(double));/*Saveguard of the relevant coordinates*/
5472     save[0] = rho[0];
5473     save[1] = theta[0];
5474     save[2] = krho[0];
5475     save[3] = m[0];
5476     
5477     double dfdrho,dfdtheta,d2fdtheta2,d2fdthetadrho,d2fdrho2;
5478     double gradrho,r,calpha,salpha;
5479     
5480     ppvald_2D(rayequil.x_fit,rayparam.dS[0],save[0],save[1],rho,&dfdrho,&dfdtheta,&d2fdtheta2,&d2fdthetadrho,&d2fdrho2);/*Input x into the variable rho*/
5481     ppvald_2D(rayequil.y_fit,rayparam.dS[0],save[0],save[1],theta,&dfdrho,&dfdtheta,&d2fdtheta2,&d2fdthetadrho,&d2fdrho2);/*Input y into the variable theta*/
5482     
5483     rho[0]=rho[0]/equilparam.ap[0];/*Normalization, rho stands for x*/
5484     theta[0]=theta[0]/equilparam.ap[0];/*Normalization, theta stands for y*/
5485     
5486     ppvald_2D(rayequil.gradrho_fit,rayparam.dS[0],save[0],save[1],&gradrho,&dfdrho,&dfdtheta,&d2fdtheta2,&d2fdthetadrho,&d2fdrho2);/*Gives out gradrho*/
5487     ppvald_2D(rayequil.r_fit,rayparam.dS[0],save[0],save[1],&r,&dfdrho,&dfdtheta,&d2fdtheta2,&d2fdthetadrho,&d2fdrho2);/*Gives out r*/
5488     ppvald_2D(rayequil.calpha_fit,rayparam.dS[0],save[0],save[1],&calpha,&dfdrho,&dfdtheta,&d2fdtheta2,&d2fdthetadrho,&d2fdrho2);/*Gives out cos alpha*/
5489     ppvald_2D(rayequil.salpha_fit,rayparam.dS[0],save[0],save[1],&salpha,&dfdrho,&dfdtheta,&d2fdtheta2,&d2fdthetadrho,&d2fdrho2);/*Gives out sin alpha*/
5490     
5491     r=r/equilparam.ap[0];/*Normalization*/
5492     gradrho=gradrho*equilparam.ap[0];/*Normalization*/
5493     
5494     double cat = calpha*cos(save[1]) + salpha*sin(save[1]);/*Gives out cos(alpha - theta)*/
5495     double sat = salpha*cos(save[1]) - sin(save[1])*calpha;/*Gives out sin(alpha - theta)*/
5496     
5497     krho[0] = gradrho*cat*save[2] -(sin(save[1])/r)*save[3];/*Input kx into the variable krho*/
5498     m[0] = -gradrho*sat*save[2] + (cos(save[1])/r)*save[3];/*Input ky into the variable m*/
5499     
5500     mxFree(save);
5501 }
5502 
5503 void xy2rhotheta(rayparam_format rayparam, rayequil_format rayequil, equilparam_format equilparam, double *x, double *y, double *kx, double *ky)/*Subfunction giving the curvilinear from the cartesian generalized vector, need to give each relevant components separately, here rho stand for x, theta for y, krho for kx and m for ky.*/
5504 {
5505     double *save;/*Saveguard of the relevant coordinates*/
5506     save = mxCalloc(4,sizeof(double));
5507     save[0] = x[0];
5508     save[1] = y[0];
5509     save[2] = kx[0];
5510     save[3] = ky[0];
5511     
5512     substitution(rayequil,rayparam,equilparam,x,y,save);/*Input rho and theta respectively in the variables x and y*/
5513     
5514     double dfdrho,dfdtheta,d2fdtheta2,d2fdthetadrho,d2fdrho2;
5515     double gradrho,r,calpha,salpha;
5516     
5517     ppvald_2D(rayequil.gradrho_fit,rayparam.dS[0],x[0],y[0],&gradrho,&dfdrho,&dfdtheta,&d2fdtheta2,&d2fdthetadrho,&d2fdrho2);/*Gives out gradrho*/
5518     ppvald_2D(rayequil.r_fit,rayparam.dS[0],x[0],y[0],&r,&dfdrho,&dfdtheta,&d2fdtheta2,&d2fdthetadrho,&d2fdrho2);/*Gives out r*/
5519     ppvald_2D(rayequil.calpha_fit,rayparam.dS[0],x[0],y[0],&calpha,&dfdrho,&dfdtheta,&d2fdtheta2,&d2fdthetadrho,&d2fdrho2);/*Gives out cos alpha*/
5520     ppvald_2D(rayequil.salpha_fit,rayparam.dS[0],x[0],y[0],&salpha,&dfdrho,&dfdtheta,&d2fdtheta2,&d2fdthetadrho,&d2fdrho2);/*Gives out sin alpha*/
5521     
5522     r=r/equilparam.ap[0];/*Normalization*/
5523     gradrho=gradrho*equilparam.ap[0];/*Normalization*/
5524     
5525     double theta = y[0];
5526     double cat = calpha*cos(theta) + salpha*sin(theta);/*Gives out cos(alpha - theta)*/
5527     double sat = salpha*cos(theta) - sin(theta)*calpha;/*Gives out sin(alpha - theta)*/
5528     
5529     kx[0] = (1/(gradrho*calpha))*(cos(theta)*save[2] + sin(theta)*save[3]);/*Input krho into the variable kx*/
5530     ky[0] = (r/calpha)*(sat*save[2] + cat*save[3]);/*Input m into the variable ky*/
5531     
5532     mxFree(save);
5533 }

Community support and wiki are available on Redmine. Last update: 18-Apr-2019.