//Compute the force in the z direction double SCFPotentialzforce(double R,double Z, double phi, double t, struct potentialArg * potentialArgs) { double r; double theta; cyl_to_spher(R, Z,&r, &theta); double dr_dz = Z/r; double dtheta_dz = -R/(r*r); double dphi_dz = 0; double F[3]; computeForce(R, Z, phi, t,potentialArgs, &F[0]) ; return *(F + 0)*dr_dz + *(F + 1)*dtheta_dz + *(F + 2)*dphi_dz; }
//Compute the force in the phi direction double SCFPotentialphiforce(double R,double Z, double phi, double t, struct potentialArg * potentialArgs) { double r; double theta; cyl_to_spher(R, Z, &r, &theta); double dr_dphi = 0; double dtheta_dphi = 0; double dphi_dphi = 1; double F[3]; computeForce(R, Z, phi, t,potentialArgs, &F) ; return *(F + 0)*dr_dphi + *(F + 1)*dtheta_dphi + *(F + 2)*dphi_dphi; }
//Compute the force in the R direction double SCFPotentialRforce(double R,double Z, double phi, double t, struct potentialArg * potentialArgs) { double r; double theta; cyl_to_spher(R, Z, &r, &theta); // The derivatives double dr_dR = R/r; double dtheta_dR = Z/(r*r); double dphi_dR = 0; double F[3]; computeForce(R, Z, phi, t,potentialArgs, &F[0]) ; return *(F + 0)*dr_dR + *(F + 1)*dtheta_dR + *(F + 2)*dphi_dR; }
//Compute the Potential double SCFPotentialEval(double R,double Z, double phi, double t, struct potentialArg * potentialArgs) { double * args= potentialArgs->args; //Get args double a = *args++; int isNonAxi = (int)*args++; int N = *args++; int L = *args++; int M = *args++; double* Acos = args; double* Asin; if (isNonAxi==1) //LCOV_EXCL_START { Asin = args + N*L*M; } //LCOV_EXCL_STOP //convert R,Z to r, theta double r; double theta; cyl_to_spher(R, Z,&r, &theta); double xi; calculateXi(r, a, &xi); //Compute the gegenbauer polynomials and its derivative. double C[N*L]; compute_C(xi, N, L, &C[0]); //Compute phiTilde and its derivative double phiTilde[L*N]; compute_phiTilde(r, a, N, L, &C[0], &phiTilde[0]); //Compute Associated Legendre Polynomials int M_eff = M; int size = 0; if (isNonAxi==0) { M_eff = 1; size = L; } else{ //LCOV_EXCL_START size = L*L - L*(L-1)/2; } //LCOV_EXCL_STOP double P[size]; compute_P(cos(theta), L,M_eff, &P[0]); double potential; double (*PhiTilde_Pointer[1]) = {&phiTilde[0]}; double (*P_Pointer[1]) = {&P[0]}; double Constant[1] = {1.}; if (isNonAxi==1) //LCOV_EXCL_START { double (*Eq[1])(double, double, double, double, double, double, int) = {&computePhi}; equations e = {Eq,&PhiTilde_Pointer[0],&P_Pointer[0],&Constant[0]}; computeNonAxi(a, N, L, M,r, theta, phi, Acos, Asin, 1, e, &potential); } //LCOV_EXCL_STOP else { double (*Eq[1])(double, double, double) = {&computeAxiPhi}; axi_equations e = {Eq,&PhiTilde_Pointer[0],&P_Pointer[0],&Constant[0]}; compute(a, N, L, M,r, theta, phi, Acos, 1, e, &potential); } return potential; }
//Compute the Derivatives void computeDeriv(double R,double Z, double phi, double t, struct potentialArg * potentialArgs, double * F) { double * args= potentialArgs->args; //Get args double a = *args++; int isNonAxi = (int)*args++; int N = *args++; int L = *args++; int M = *args++; double* Acos = args; double * caching_i = (args + (isNonAxi + 1)*N*L*M); double *Asin; if (isNonAxi == 1) { Asin = args + N*L*M; } double *cached_type = caching_i; double * cached_coords = (caching_i+ 1); double * cached_values = (caching_i + 4); if ((int)*cached_type==DERIV) { if (*cached_coords == R && *(cached_coords + 1) == Z && *(cached_coords + 2) == phi) { *F = *cached_values; *(F + 1) = *(cached_values + 1); *(F + 2) = *(cached_values + 2); return; } } double r; double theta; cyl_to_spher(R, Z, &r, &theta); double xi; calculateXi(r, a, &xi); //Compute the gegenbauer polynomials and its derivative. double C[N*L]; double dC[N*L]; double d2C[N*L]; compute_C(xi, N, L, &C[0]); compute_dC(xi, N, L, &dC[0]); compute_d2C(xi, N, L, &d2C[0]); //Compute phiTilde and its derivative double phiTilde[L*N]; compute_phiTilde(r, a, N, L, &C[0], &phiTilde[0]); double dphiTilde[L*N]; compute_dphiTilde(r, a, N, L, &C[0], &dC[0], &dphiTilde[0]); double d2phiTilde[L*N]; compute_d2phiTilde(r, a, N, L, &C[0], &dC[0], &d2C[0], &d2phiTilde[0]); //Compute Associated Legendre Polynomials int M_eff = M; int size = 0; if (isNonAxi==0) { M_eff = 1; size = L; } else{ size = L*L - L*(L-1)/2; } double P[size]; compute_P(cos(theta), L,M_eff, &P[0]); double (*PhiTilde_Pointer[3])= {&d2phiTilde[0],&phiTilde[0],&dphiTilde[0]}; double (*P_Pointer[3]) = {&P[0], &P[0], &P[0]}; double Constant[3] = {1., 1., 1.}; if (isNonAxi==1) { double (*Eq[3])(double, double, double, double, double, double, int) = {&computeF_rr, &computeF_phiphi, &computeF_rphi}; equations e = {Eq,&PhiTilde_Pointer[0],&P_Pointer[0],&Constant[0]}; computeNonAxi(a, N, L, M,r, theta, phi, Acos, Asin, 3, e, F); } else { double (*Eq[3])(double, double, double) = {&computeAxiF_rr, &computeAxiF_phiphi, &computeAxiF_rphi}; axi_equations e = {Eq,&PhiTilde_Pointer[0],&P_Pointer[0],&Constant[0]}; compute(a, N, L, M,r, theta, phi, Acos, 3, e, F); } //Caching *cached_type = (double)DERIV; * cached_coords = R; * (cached_coords + 1) = Z; * (cached_coords + 2) = phi; * (cached_values) = *F; * (cached_values + 1) = *(F + 1); * (cached_values + 2) = *(F + 2); }