Loading src/include/sph_subs.h 0 → 100644 +701 −0 Original line number Diff line number Diff line /*! \file sph_subs.h * * \brief C++ porting of SPH functions, subroutines and data structures. * * Remember that FORTRAN passes arguments by reference, so, every time we use * a subroutine call, we need to add a referencing layer to the C++ variable. * All the functions defined below need to be properly documented and ported * to C++. * * Currently, only basic documenting information about functions and parameter * types are given, to avoid doxygen warning messages. */ #ifndef SRC_INCLUDE_SPH_SUBS_H_ #define SRC_INCLUDE_SPH_SUBS_H_ #include <complex> //! \brief A structure representing the common block C1 struct C1 { std::complex<double> rmi[40][2]; std::complex<double> rei[40][2]; std::complex<double> w[3360][4]; std::complex<double> fsas[2]; std::complex<double> sas[2][2][2]; std::complex<double> vints[2][16]; double sscs[2]; double sexs[2]; double sabs[2]; double sqscs[2]; double sqexs[2]; double sqabs[2]; double gcsv[2]; double rxx[1]; double ryy[1]; double rzz[1]; double ros[2]; double rc[2][8]; int iog[2]; int nshl[2]; }; //! \brief A structure representing the common block C1 struct C2 { std::complex<double> ris[999]; std::complex<double> dlri[999]; std::complex<double> dc0[5]; std::complex<double> vkt[2]; double vsz[2]; }; //! \brief Write a message to test FORTRAN -> C++ communication extern "C" void testme_(); /*! \brief C++ porting of DIEL * * \param npntmo: `int` * \param ns: `int` * \param i: `int` * \param ic: `int` * \param vk: `double` * \param c1: `C1 *` * \param c2: `C2 *` */ void diel(int npntmo, int ns, int i, int ic, double vk, C1 *c1, C2 *c2) { double dif = c1->rc[i - 1][ns] - c1->rc[i - 1][ns - 1]; double half_step = 0.5 * dif / npntmo; double rr = c1->rc[i - 1][ns - 1]; std::complex<double> delta = c2->dc0[ic] - c2->dc0[ic - 1]; int kpnt = npntmo + npntmo; c2->ris[kpnt] = c2->dc0[ic]; c2->dlri[kpnt] = std::complex<double>(0.0, 0.0); for (int np90 = 0; np90 < kpnt; np90++) { double ff = (rr - c1->rc[i - 1][ns - 1]) / dif; c2->ris[np90] = delta * ff * ff * (-2.0 * ff + 3.0) + c2->dc0[ic - 1]; c2->dlri[np90] = 3.0 * delta * ff * (1.0 - ff) / (dif * vk * c2->ris[np90]); rr += half_step; } } /*! \brief C++ porting of ENVJ * * \param n: `int` * \param x: `double` * \return result: `double` */ double envj(int n, double x) { double result = 0.0; double xn; if (n == 0) { xn = 1.0e-100; result = 0.5 * log10(6.28 * xn) - xn * log10(1.36 * x / xn); } else { result = 0.5 * log10(6.28 * n) - n * log10(1.36 * x / n); } return result; } /*! \brief C++ porting of MSTA1 * * \param x: `double` * \param mp: `int` * \return result: `int` */ int msta1(double x, int mp) { int result = 0; double a0 = x; if (a0 < 0.0) a0 *= -1.0; int n0 = (int)(1.1 * a0) + 1; double f0 = envj(n0, a0) - mp; int n1 = n0 + 5; double f1 = envj(n1, a0) - mp; for (int it10 = 0; it10 < 20; it10++) { int nn = n1 - (int)((n1 - n0) / (1.0 - f0 / f1)); double f = envj(nn, a0) - mp; int test_n = nn - n1; if (test_n < 0) test_n *= -1; if (test_n < 1) { return nn; } n0 = n1; f0 = f1; n1 = nn; f1 = f; result = nn; } return result; } /*! \brief C++ porting of MSTA2 * * \param x: `double` * \param n: `int` * \param mp: `int` * \return result: `int` */ int msta2(double x, int n, int mp) { int result = 0; double a0 = x; if (a0 < 0) a0 *= -1.0; double half_mp = 0.5 * mp; double ejn = envj(n, a0); double obj; int n0; if (ejn <= half_mp) { obj = 1.0 * mp; n0 = (int)(1.1 * a0) + 1; } else { obj = half_mp + ejn; n0 = n; } double f0 = envj(n0, a0) - obj; int n1 = n0 + 5; double f1 = envj(n1, a0) - obj; for (int it10 = 0; it10 < 20; it10 ++) { int nn = n1 - (int)((n1 - n0) / (1.0 - f0 / f1)); double f = envj(nn, a0) - obj; int test_n = nn - n1; if (test_n < 0) test_n *= -1; if (test_n < 1) return (nn + 10); n0 = n1; f0 = f1; n1 = nn; f1 = f; result = nn + 10; } return result; } /*! \brief C++ porting of CBF * * This is the Complex Bessel Function. * * \param n: `int` * \param z: `complex\<double\>` * \param nm: `int &` * \param csj: Vector of complex. */ void cbf(int n, std::complex<double> z, int &nm, std::complex<double> csj[]) { /* * FROM CSPHJY OF LIBRARY specfun * * ========================================================== * Purpose: Compute spherical Bessel functions j * Input : z --- Complex argument of j * n --- Order of j ( n = 0,1,2,... ) * Output: csj(n+1) --- j * nm --- Highest order computed * Routines called: * msta1 and msta2 for computing the starting * point for backward recurrence * ========================================================== */ double zz = z.real() * z.real() + z.imag() * z.imag(); double a0 = sqrt(zz); nm = n; if (a0 < 1.0e-60) { for (int k = 2; k <= n + 1; k++) { csj[k - 1] = 0.0; } csj[0] = std::complex<double>(1.0, 0.0); return; } csj[0] = std::sin(z) / z; if (n == 0) { return; } csj[1] = (csj[0] -std::cos(z)) / z; if (n == 1) { return; } std::complex<double> csa = csj[0]; std::complex<double> csb = csj[1]; int m = msta1(a0, 200); if (m < n) nm = m; else m = msta2(a0, n, 15); std::complex<double> cf0 = 0.0; std::complex<double> cf1 = 1.0e-100; std::complex<double> cf, cs; for (int k = m; k >= 0; k--) { cf = (2.0 * k + 3.0) * cf1 / z - cf0; if (k <= nm) csj[k] = cf; cf0 = cf1; cf1 = cf; } double abs_csa = sqrt(csa.real() * csa.real() + csa.imag() * csa.imag()); double abs_csb = sqrt(csb.real() * csb.real() + csb.imag() * csb.imag()); if (abs_csa > abs_csb) cs = csa / cf; else cs = csb / cf0; for (int k = 0; k <= nm; k++) { csj[k] = cs * csj[k]; } } /*! \brief C++ porting of RBF * * This is the Real Bessel Function. * * \param n: `int` * \param x: `double` * \param nm: `int &` * \param sj: `double[]` */ void rbf(int n, double x, int &nm, double sj[]) { /* * FROM SPHJ OF LIBRARY specfun * * ========================================================== * Purpose: Compute spherical Bessel functions j * Input : x --- Argument of j * n --- Order of j ( n = 0,1,2,... ) * Output: sj(n+1) --- j * nm --- Highest order computed * Routines called: * msta1 and msta2 for computing the starting * point for backward recurrence * ========================================================== */ double a0 = x; if (a0 < 0.0) a0 *= -1.0; nm = n; if (a0 < 1.0e-60) { for (int k = 2; k <= n + 1; k++) sj[k - 1] = 0.0; sj[0] = 1.0; return; } sj[0] = sin(x) / x; if (n == 0) { return; } sj[1] = (sj[0] - cos(x)) / x; if (n == 1) { return; } double sa = sj[0]; double sb = sj[1]; int m = msta1(a0, 200); if (m < n) nm = m; else m = msta2(a0, n, 15); double f0 = 0.0; double f1 = 1.0e-100; double f; for (int k = m; k >= 0; k--) { f = (2.0 * k +3.0) * f1 / x - f0; if (k <= nm) sj[k] = f; f0 = f1; f1 = f; } double cs; double abs_sa = sa; if (abs_sa < 0.0) abs_sa *= -1.0; double abs_sb = sb; if (abs_sb < 0.0) abs_sb *= -1.0; if (abs_sa > abs_sb) cs = sa / f; else cs = sb / f0; for (int k = 0; k <= nm; k++) { sj[k] = cs * sj[k]; } } /*! \brief C++ porting of RKC * * \param npntmo: `int` * \param step: `double` * \param dcc: `complex\<double\>` * \param x: `double &` * \param lpo: `int` * \param y1: `complex\<double\> &` * \param y2: `complex\<double\> &` * \param dy1: `complex\<double\> &` * \param dy2: `complex\<double\> &` */ void rkc( int npntmo, double step, std::complex<double> dcc, double &x, int lpo, std::complex<double> &y1, std::complex<double> &y2, std::complex<double> &dy1, std::complex<double> &dy2 ) { std::complex<double> cy1, cdy1, c11, cy23, yc2, c12, c13; std::complex<double> cy4, yy, c14, c21, c22, c23, c24; double half_step = 0.5 * step; double cl = 1.0 * lpo * (lpo - 1); for (int ipnt60 = 1; ipnt60 <= npntmo; ipnt60++) { cy1 = cl / (x * x) - dcc; cdy1 = -2.0 / x; c11 = (cy1 * y1 + cdy1 * dy1) * step; double xh = x + half_step; cy23 = cl / (xh * xh) - dcc; double cdy23 = -2.0 / xh; yc2 = y1 + dy1 * half_step; c12 = (cy23 * yc2 + cdy23 * (dy1 + 0.5 * c11)) * step; c13 = (cy23 * (yc2 + 0.25 * c11 * step) + cdy23 * (dy1 + 0.5 * c12)) * step; double xn = x + step; cy4 = cl / (xn * xn) - dcc; double cdy4 = -2.0 / xn; yy = y1 + dy1 * step; c14 = (cy4 * (yy + 0.5 * c12 * step) + cdy4 * (dy1 + c13)) * step; y1 = yy + (c11 + c12 + c13) * step / 6.0; dy1 += (0.5 * c11 + c12 + c13 + 0.5 * c14) / 3.0; c21 = (cy1 * y2 + cdy1 * dy2) * step; yc2 = y2 + dy2 * half_step; c22 = (cy23 * yc2 + cdy23 * (dy2 + 0.5 * c21)) * step; c23= (cy23 * (yc2 + 0.25 * c21 * step) + cdy23 * (dy2 + 0.5 * c22)) * step; yy = y2 + dy2 * step; c24 = (cy4 * (yc2 + 0.5 * c22 * step) + cdy4 * (dy2 + c23)) * step; y2 = yy + (c21 + c22 + c23) * step / 6.0; dy2 += (0.5 * c21 + c22 + c23 + 0.5 * c24) / 3.0; x = xn; } } /*! \brief C++ porting of RKT * * \param npntmo: `int` * \param step: `double` * \param x: `double &` * \param lpo: `int` * \param y1: `complex\<double\> &` * \param y2: `complex\<double\> &` * \param dy1: `complex\<double\> &` * \param dy2: `complex\<double\> &` * \param c2: `C2 *` */ void rkt( int npntmo, double step, double &x, int lpo, std::complex<double> &y1, std::complex<double> &y2, std::complex<double> &dy1, std::complex<double> &dy2, C2 *c2 ) { std::complex<double> cy1, cdy1, c11, cy23, cdy23, yc2, c12, c13; std::complex<double> cy4, cdy4, yy, c14, c21, c22, c23, c24; double half_step = 0.5 * step; double cl = 1.0 * lpo * (lpo - 1); for (int ipnt60 = 1; ipnt60 <= npntmo; ipnt60++) { int jpnt = ipnt60 + ipnt60 - 1; cy1 = cl / (x * x) - c2->ris[jpnt - 1]; cdy1 = -2.0 / x; c11 = (cy1 * y1 + cdy1 * dy1) * step; double xh = x + half_step; int jpntpo = jpnt + 1; cy23 = cl / (xh * xh) - c2->ris[jpntpo - 1]; cdy23 = -2.0 / xh; yc2 = y1 + dy1 * half_step; c12 = (cy23 * yc2 + cdy23 * (dy1 + 0.5 * c11)) * step; c13= (cy23 * (yc2 + 0.25 * c11 *step) + cdy23 * (dy1 + 0.5 * c12)) * step; double xn = x + step; int jpntpt = jpnt + 2; cy4 = cl / (xn * xn) - c2->ris[jpntpt - 1]; cdy4 = -2.0 / xn; yy = y1 + dy1 * step; c14 = (cy4 * (yy + 0.5 * c12 * step) + cdy4 * (dy1 + c13)) * step; y1= yy + (c11 + c12 + c13) * step / 6.0; dy1 += (0.5 * c11 + c12 + c13 + 0.5 *c14) /3.0; cy1 -= cdy1 * c2->dlri[jpnt - 1]; cdy1 += 2.0 * c2->dlri[jpnt - 1]; c21 = (cy1 * y2 + cdy1 * dy2) * step; cy23 -= cdy23 * c2->dlri[jpntpo - 1]; cdy23 += 2.0 * c2->dlri[jpntpo - 1]; yc2 = y2 + dy2 * half_step; c22 = (cy23 * yc2 + cdy23 * (dy2 + 0.5 * c21)) * step; c23 = (cy23 * (yc2 + 0.25 * c21 * step) + cdy23 * (dy2 + 0.5 * c22)) * step; cy4 -= cdy4 * c2->dlri[jpntpt - 1]; cdy4 += 2.0 * c2->dlri[jpntpt - 1]; yy = y2 + dy2 * step; c24 = (cy4 * (yc2 + 0.5 * c22 * step) + cdy4 * (dy2 + c23)) * step; y2 = yy + (c21 + c22 + c23) * step / 6.0; dy2 += (0.5 * c21 + c22 + c23 + 0.5 * c24) / 3.0; x = xn; } } /*! \brief C++ porting of RNF * * This is a real spherical Bessel function. * * \param n: `int` * \param x: `double` * \param nm: `int &` * \param sj: `double[]` */ void rnf(int n, double x, int &nm, double sy[]) { /* * FROM SPHJY OF LIBRARY specfun * * ========================================================== * Purpose: Compute spherical Bessel functions y * Input : x --- Argument of y ( x > 0 ) * n --- Order of y ( n = 0,1,2,... ) * Output: sy(n+1) --- y * nm --- Highest order computed * ========================================================== */ if (x < 1.0e-60) { for (int k = 0; k <= n; k++) sy[k] = -1.0e300; return; } sy[0] = -1.0 * cos(x) / x; if (n == 0) { return; } sy[1] = (sy[0] - sin(x)) / x; if (n == 1) { return; } double f0 = sy[0]; double f1 = sy[1]; double f; for (int k = 2; k <= n; k++) { f = (2.0 * k - 1.0) * f1 / x - f0; sy[k] = f; double abs_f = f; if (abs_f < 0.0) abs_f *= -1.0; if (abs_f >= 1.0e300) { nm = k; break; } f0 = f1; f1 = f; nm = k; } return; } /*! \brief C++ porting of SSCR0 * * \param tfsas: `complex<double> &` * \param nsph: `int` * \param lm: `int` * \param vk: `double` * \param exri: `double` * \param c1: `C1 *` */ void sscr0(std::complex<double> &tfsas, int nsph, int lm, double vk, double exri, C1 *c1) { std::complex<double> sum21, rm, re, cc0, csam; cc0 = std::complex<double>(0.0, 0.0); double exdc = exri * exri; double ccs = 4.0 * acos(0.0) / (vk * vk); double cccs = ccs / exdc; csam = -(ccs / (exri * vk)) * std::complex<double>(0.0, 0.5); tfsas = cc0; for (int i12 = 1; i12 <= nsph; i12++) { int iogi = c1->iog[i12 - 1]; if (iogi >= i12) { double sums = 0.0; std::complex<double> sum21 = cc0; for (int l10 = 1; l10 <= lm; l10++) { double fl = 1.0 + l10 + l10; rm = 1.0 / c1->rmi[l10 - 1][i12 - 1]; re = 1.0 / c1->rei[l10 - 1][i12 - 1]; std::complex<double> rm_cnjg = std::complex<double>(rm.real(), -rm.imag()); std::complex<double> re_cnjg = std::complex<double>(re.real(), -re.imag()); sums += (rm_cnjg * rm + re_cnjg * re).real() * fl; sum21 += (rm + re) * fl; } sum21 *= -1.0; double scasec = cccs * sums; double extsec = -cccs * sum21.real(); double abssec = extsec - scasec; c1->sscs[i12 - 1] = scasec; c1->sexs[i12 - 1] = extsec; c1->sabs[i12 - 1] = abssec; double gcss = c1-> gcsv[i12 - 1]; c1->sqscs[i12 - 1] = scasec / gcss; c1->sqexs[i12 - 1] = extsec / gcss; c1->sqabs[i12 - 1] = abssec / gcss; c1->fsas[i12 - 1] = sum21 * csam; } tfsas += c1->fsas[iogi - 1]; } } /*! \brief C++ porting of THDPS * * \param lm: `int` * \param zpv: `double ****` */ void thdps(int lm, double ****zpv) { // WARNING: unclear nested loop in THDPS // The optimized interpretation was adopted here. for (int l10 = 1; l10 <= lm; l10++) { for (int ilmp = 1; ilmp <= 3; ilmp++) { zpv[l10 - 1][ilmp - 1][0][0] = 0.0; zpv[l10 - 1][ilmp - 1][0][1] = 0.0; zpv[l10 - 1][ilmp - 1][1][0] = 0.0; zpv[l10 - 1][ilmp - 1][1][1] = 0.0; } } for (int l15 = 1; l15 <= lm; l15++) { double xd = 1.0 * l15 * (l15 + 1); double zp = -1.0 / sqrt(xd); zpv[l15 - 1][1][0][1] = zp; zpv[l15 - 1][1][1][0] = zp; } if (lm != 1) { for (int l20 = 2; l20 <= lm; l20++) { double xn = 1.0 * (l20 - 1) * (l20 + 1); double xd = 1.0 * l20 * (l20 + l20 + 1); double zp = sqrt(xn / xd); zpv[l20 - 1][0][0][0] = zp; zpv[l20 - 1][0][1][1] = zp; } int lmmo = lm - 1; for (int l25 = 1; l25 <= lmmo; l25++) { double xn = 1.0 * l25 * (l25 + 2); double xd = (l25 + 1) * (l25 + l25 + 1); double zp = -1.0 * sqrt(xn / xd); zpv[l25 - 1][2][0][0] = zp; zpv[l25 - 1][2][1][1] = zp; } } } /*! \brief C++ porting of DME * * \param li: `int` * \param i: `int` * \param npnt: `int` * \param npntts: `int` * \param vk: `double` * \param exdc: `double` * \param exri: `double` * \param c1: `C1 *` * \param c2: `C2 *` * \param jer: `int &` * \param lcalc: `int &` * \param arg: `complex<double> &`. */ void dme( int li, int i, int npnt, int npntts, double vk, double exdc, double exri, C1 *c1, C2 *c2, int &jer, int &lcalc, std::complex<double> &arg) { //double rfj[42], rfn[42]; double *rfj = new double[42]; double *rfn = new double[42]; std::complex<double> cfj[42], fbi[42], fb[42], fn[42]; std::complex<double> rmf[40], drmf[40], ref[40], dref[40]; std::complex<double> dfbi, dfb, dfn, ccna, ccnb, ccnc, ccnd; std::complex<double> y1, dy1, y2, dy2, arin, cri, uim; jer = 0; uim = std::complex<double>(0.0, 1.0); int nstp = npnt - 1; int nstpts = npntts - 1; int lipo = li + 1; int lipt = li + 2; double sz = vk * c1->ros[i - 1]; c2->vsz[i - 1] = sz; double vkr1 = vk * c1->rc[i - 1][0]; int nsh = c1->nshl[i - 1]; c2->vkt[i - 1] = std::sqrt(c2->dc0[0]); arg = vkr1 * c2->vkt[i - 1]; arin = arg; bool goto32 = false; if (arg.imag() != 0.0) { cbf(lipo, arg, lcalc, cfj); if (lcalc < lipo) { jer = 5; return; } for (int j24 = 1; j24 <= lipt; j24++) fbi[j24 - 1] = cfj[j24 - 1]; goto32 = true; } if (!goto32) { rbf(lipo, arg.real(), lcalc, rfj); if (lcalc < lipo) { jer = 5; return; } for (int j30 = 1; j30 <= lipt; j30++) fbi[j30 - 1] = rfj[j30 - 1]; } double arex = sz * exri; arg = arex; rbf(lipo, arex, lcalc, rfj); if (lcalc < lipo) { jer = 7; return; } rnf(lipo, arex, lcalc, rfn); if (lcalc < lipo) { jer = 8; return; } for (int j43 = 1; j43 <= lipt; j43++) { fb[j43 - 1] = rfj[j43 - 1]; //printf("DEBUG: fb[%d] = (%lE,%lE)\n", j43, fb[j43 - 1].real(), fb[j43 - 1].imag()); fn[j43 - 1] = rfn[j43 - 1]; //printf("DEBUG: fn[%d] = (%lE,%lE)\n", j43, fn[j43 - 1].real(), fn[j43 - 1].imag()); } if (nsh <= 1) { cri = c2->dc0[0] / exdc; for (int l60 = 1; l60 <= li; l60++) { int lpo = l60 + 1; int ltpo = lpo + l60; int lpt = lpo + 1; dfbi = ((1.0 * l60) * fbi[l60 - 1] - (1.0 * lpo) * fbi[lpt - 1]) * arin + fbi[lpo - 1] * (1.0 * ltpo); dfb = ((1.0 * l60) * fb[l60 - 1] - (1.0 * lpo) * fb[lpt - 1]) * arex + fb[lpo - 1] * (1.0 * ltpo); dfn = ((1.0 * l60) * fn[l60 - 1] - (1.0 * lpo) * fn[lpt - 1]) * arex + fn[lpo - 1] * (1.0 * ltpo); ccna = fbi[lpo - 1] * dfn; ccnb = fn[lpo - 1] * dfbi; ccnc = fbi[lpo - 1] * dfb; ccnd = fb[lpo - 1] * dfbi; c1->rmi[l60 - 1][i - 1] = 1.0 + uim * (ccna - ccnb) / (ccnc - ccnd); c1->rei[l60 - 1][i - 1] = 1.0 + uim * (cri * ccna - ccnb) / (cri * ccnc - ccnd); } } else { // nsh > 1 int ic = 1; for (int l80 = 1; l80 <= li; l80++) { int lpo = l80 + 1; int ltpo = lpo + l80; int lpt = lpo + 1; int dltpo = ltpo; y1 = fbi[lpo - 1]; dy1 = ((1.0 * l80) * fbi[l80 - 1] - (1.0 * lpo) * fbi[lpt - 1]) * c2->vkt[i - 1] / (1.0 * dltpo); y2 = y1; dy2 = dy1; ic = 1; for (int ns76 = 2; ns76 <= nsh; ns76++) { int nsmo = ns76 - 1; double vkr = vk * c1->rc[i - 1][nsmo - 1]; if (ns76 % 2 != 0) { ic += 1; double step = 1.0 * nstp; step = vk * (c1->rc[i - 1][ns76 - 1] - c1->rc[i - 1][nsmo - 1]) / step; arg = c2->dc0[ic - 1]; rkc(nstp, step, arg, vkr, lpo, y1, y2, dy1, dy2); } else { diel(nstpts, nsmo, i, ic, vk, c1, c2); double stepts = 1.0 * nstpts; stepts = vk * (c1->rc[i - 1][ns76 - 1] - c1->rc[i - 1][nsmo - 1]) / stepts; rkt(nstpts, stepts, vkr, lpo, y1, y2, dy1, dy2, c2); } } rmf[l80 - 1] = y1 * sz; drmf[l80 - 1] = dy1 * sz + y1; ref[l80 - 1] = y2 * sz; dref[l80 - 1] = dy2 * sz + y2; } cri = 1.0 + uim * 0.0; if (nsh % 2 != 0) cri = c2->dc0[ic - 1] / exdc; for (int l90 = 1; l90 <= li; l90++) { int lpo = l90 + 1; int ltpo = lpo + l90; int lpt = lpo + 1; dfb = ((1.0 * l90) * fb[l90 - 1] - (1.0 * lpo) * fb[lpt - 1]) * arex + fb[lpo - 1] * (1.0 * ltpo); dfn = ((1.0 * l90) * fn[l90 - 1] - (1.0 * lpo) * fn[lpt - 1]) * arex + fn[lpo - 1] * (1.0 * ltpo); ccna = rmf[l90 - 1] * dfn; ccnb = drmf[l90 - 1] * fn[lpo - 1] * (1.0 * sz * ltpo); ccnc = rmf[l90 - 1] * dfb; ccnd = drmf[l90 - 1] * fb[lpo -1] * (1.0 * sz * ltpo); c1->rmi[l90 - 1][i - 1] = 1.0 + uim *(ccna - ccnb) / (ccnc - ccnd); //printf("DEBUG: gone 90, rmi[%d][%d] = (%lE,%lE)\n", l90, i, c1->rmi[l90 - 1][i - 1].real(), c1->rmi[l90 - 1][i - 1].imag()); ccna = ref[l90 - 1] * dfn; ccnb = dref[l90 - 1] * fn[lpo - 1] * (1.0 * sz * ltpo); ccnc = ref[l90 - 1] * dfb; ccnd = dref[l90 - 1] *fb[lpo - 1] * (1.0 * sz * ltpo); c1->rei[l90 - 1][i - 1] = 1.0 + uim * (cri * ccna - ccnb) / (cri * ccnc - ccnd); //printf("DEBUG: gone 90, rei[%d][%d] = (%lE,%lE)\n", l90, i, c1->rei[l90 - 1][i - 1].real(), c1->rei[l90 - 1][i - 1].imag()); } } // nsh <= 1 ? return; } #endif /* SRC_INCLUDE_SPH_SUBS_H_ */ Loading
src/include/sph_subs.h 0 → 100644 +701 −0 Original line number Diff line number Diff line /*! \file sph_subs.h * * \brief C++ porting of SPH functions, subroutines and data structures. * * Remember that FORTRAN passes arguments by reference, so, every time we use * a subroutine call, we need to add a referencing layer to the C++ variable. * All the functions defined below need to be properly documented and ported * to C++. * * Currently, only basic documenting information about functions and parameter * types are given, to avoid doxygen warning messages. */ #ifndef SRC_INCLUDE_SPH_SUBS_H_ #define SRC_INCLUDE_SPH_SUBS_H_ #include <complex> //! \brief A structure representing the common block C1 struct C1 { std::complex<double> rmi[40][2]; std::complex<double> rei[40][2]; std::complex<double> w[3360][4]; std::complex<double> fsas[2]; std::complex<double> sas[2][2][2]; std::complex<double> vints[2][16]; double sscs[2]; double sexs[2]; double sabs[2]; double sqscs[2]; double sqexs[2]; double sqabs[2]; double gcsv[2]; double rxx[1]; double ryy[1]; double rzz[1]; double ros[2]; double rc[2][8]; int iog[2]; int nshl[2]; }; //! \brief A structure representing the common block C1 struct C2 { std::complex<double> ris[999]; std::complex<double> dlri[999]; std::complex<double> dc0[5]; std::complex<double> vkt[2]; double vsz[2]; }; //! \brief Write a message to test FORTRAN -> C++ communication extern "C" void testme_(); /*! \brief C++ porting of DIEL * * \param npntmo: `int` * \param ns: `int` * \param i: `int` * \param ic: `int` * \param vk: `double` * \param c1: `C1 *` * \param c2: `C2 *` */ void diel(int npntmo, int ns, int i, int ic, double vk, C1 *c1, C2 *c2) { double dif = c1->rc[i - 1][ns] - c1->rc[i - 1][ns - 1]; double half_step = 0.5 * dif / npntmo; double rr = c1->rc[i - 1][ns - 1]; std::complex<double> delta = c2->dc0[ic] - c2->dc0[ic - 1]; int kpnt = npntmo + npntmo; c2->ris[kpnt] = c2->dc0[ic]; c2->dlri[kpnt] = std::complex<double>(0.0, 0.0); for (int np90 = 0; np90 < kpnt; np90++) { double ff = (rr - c1->rc[i - 1][ns - 1]) / dif; c2->ris[np90] = delta * ff * ff * (-2.0 * ff + 3.0) + c2->dc0[ic - 1]; c2->dlri[np90] = 3.0 * delta * ff * (1.0 - ff) / (dif * vk * c2->ris[np90]); rr += half_step; } } /*! \brief C++ porting of ENVJ * * \param n: `int` * \param x: `double` * \return result: `double` */ double envj(int n, double x) { double result = 0.0; double xn; if (n == 0) { xn = 1.0e-100; result = 0.5 * log10(6.28 * xn) - xn * log10(1.36 * x / xn); } else { result = 0.5 * log10(6.28 * n) - n * log10(1.36 * x / n); } return result; } /*! \brief C++ porting of MSTA1 * * \param x: `double` * \param mp: `int` * \return result: `int` */ int msta1(double x, int mp) { int result = 0; double a0 = x; if (a0 < 0.0) a0 *= -1.0; int n0 = (int)(1.1 * a0) + 1; double f0 = envj(n0, a0) - mp; int n1 = n0 + 5; double f1 = envj(n1, a0) - mp; for (int it10 = 0; it10 < 20; it10++) { int nn = n1 - (int)((n1 - n0) / (1.0 - f0 / f1)); double f = envj(nn, a0) - mp; int test_n = nn - n1; if (test_n < 0) test_n *= -1; if (test_n < 1) { return nn; } n0 = n1; f0 = f1; n1 = nn; f1 = f; result = nn; } return result; } /*! \brief C++ porting of MSTA2 * * \param x: `double` * \param n: `int` * \param mp: `int` * \return result: `int` */ int msta2(double x, int n, int mp) { int result = 0; double a0 = x; if (a0 < 0) a0 *= -1.0; double half_mp = 0.5 * mp; double ejn = envj(n, a0); double obj; int n0; if (ejn <= half_mp) { obj = 1.0 * mp; n0 = (int)(1.1 * a0) + 1; } else { obj = half_mp + ejn; n0 = n; } double f0 = envj(n0, a0) - obj; int n1 = n0 + 5; double f1 = envj(n1, a0) - obj; for (int it10 = 0; it10 < 20; it10 ++) { int nn = n1 - (int)((n1 - n0) / (1.0 - f0 / f1)); double f = envj(nn, a0) - obj; int test_n = nn - n1; if (test_n < 0) test_n *= -1; if (test_n < 1) return (nn + 10); n0 = n1; f0 = f1; n1 = nn; f1 = f; result = nn + 10; } return result; } /*! \brief C++ porting of CBF * * This is the Complex Bessel Function. * * \param n: `int` * \param z: `complex\<double\>` * \param nm: `int &` * \param csj: Vector of complex. */ void cbf(int n, std::complex<double> z, int &nm, std::complex<double> csj[]) { /* * FROM CSPHJY OF LIBRARY specfun * * ========================================================== * Purpose: Compute spherical Bessel functions j * Input : z --- Complex argument of j * n --- Order of j ( n = 0,1,2,... ) * Output: csj(n+1) --- j * nm --- Highest order computed * Routines called: * msta1 and msta2 for computing the starting * point for backward recurrence * ========================================================== */ double zz = z.real() * z.real() + z.imag() * z.imag(); double a0 = sqrt(zz); nm = n; if (a0 < 1.0e-60) { for (int k = 2; k <= n + 1; k++) { csj[k - 1] = 0.0; } csj[0] = std::complex<double>(1.0, 0.0); return; } csj[0] = std::sin(z) / z; if (n == 0) { return; } csj[1] = (csj[0] -std::cos(z)) / z; if (n == 1) { return; } std::complex<double> csa = csj[0]; std::complex<double> csb = csj[1]; int m = msta1(a0, 200); if (m < n) nm = m; else m = msta2(a0, n, 15); std::complex<double> cf0 = 0.0; std::complex<double> cf1 = 1.0e-100; std::complex<double> cf, cs; for (int k = m; k >= 0; k--) { cf = (2.0 * k + 3.0) * cf1 / z - cf0; if (k <= nm) csj[k] = cf; cf0 = cf1; cf1 = cf; } double abs_csa = sqrt(csa.real() * csa.real() + csa.imag() * csa.imag()); double abs_csb = sqrt(csb.real() * csb.real() + csb.imag() * csb.imag()); if (abs_csa > abs_csb) cs = csa / cf; else cs = csb / cf0; for (int k = 0; k <= nm; k++) { csj[k] = cs * csj[k]; } } /*! \brief C++ porting of RBF * * This is the Real Bessel Function. * * \param n: `int` * \param x: `double` * \param nm: `int &` * \param sj: `double[]` */ void rbf(int n, double x, int &nm, double sj[]) { /* * FROM SPHJ OF LIBRARY specfun * * ========================================================== * Purpose: Compute spherical Bessel functions j * Input : x --- Argument of j * n --- Order of j ( n = 0,1,2,... ) * Output: sj(n+1) --- j * nm --- Highest order computed * Routines called: * msta1 and msta2 for computing the starting * point for backward recurrence * ========================================================== */ double a0 = x; if (a0 < 0.0) a0 *= -1.0; nm = n; if (a0 < 1.0e-60) { for (int k = 2; k <= n + 1; k++) sj[k - 1] = 0.0; sj[0] = 1.0; return; } sj[0] = sin(x) / x; if (n == 0) { return; } sj[1] = (sj[0] - cos(x)) / x; if (n == 1) { return; } double sa = sj[0]; double sb = sj[1]; int m = msta1(a0, 200); if (m < n) nm = m; else m = msta2(a0, n, 15); double f0 = 0.0; double f1 = 1.0e-100; double f; for (int k = m; k >= 0; k--) { f = (2.0 * k +3.0) * f1 / x - f0; if (k <= nm) sj[k] = f; f0 = f1; f1 = f; } double cs; double abs_sa = sa; if (abs_sa < 0.0) abs_sa *= -1.0; double abs_sb = sb; if (abs_sb < 0.0) abs_sb *= -1.0; if (abs_sa > abs_sb) cs = sa / f; else cs = sb / f0; for (int k = 0; k <= nm; k++) { sj[k] = cs * sj[k]; } } /*! \brief C++ porting of RKC * * \param npntmo: `int` * \param step: `double` * \param dcc: `complex\<double\>` * \param x: `double &` * \param lpo: `int` * \param y1: `complex\<double\> &` * \param y2: `complex\<double\> &` * \param dy1: `complex\<double\> &` * \param dy2: `complex\<double\> &` */ void rkc( int npntmo, double step, std::complex<double> dcc, double &x, int lpo, std::complex<double> &y1, std::complex<double> &y2, std::complex<double> &dy1, std::complex<double> &dy2 ) { std::complex<double> cy1, cdy1, c11, cy23, yc2, c12, c13; std::complex<double> cy4, yy, c14, c21, c22, c23, c24; double half_step = 0.5 * step; double cl = 1.0 * lpo * (lpo - 1); for (int ipnt60 = 1; ipnt60 <= npntmo; ipnt60++) { cy1 = cl / (x * x) - dcc; cdy1 = -2.0 / x; c11 = (cy1 * y1 + cdy1 * dy1) * step; double xh = x + half_step; cy23 = cl / (xh * xh) - dcc; double cdy23 = -2.0 / xh; yc2 = y1 + dy1 * half_step; c12 = (cy23 * yc2 + cdy23 * (dy1 + 0.5 * c11)) * step; c13 = (cy23 * (yc2 + 0.25 * c11 * step) + cdy23 * (dy1 + 0.5 * c12)) * step; double xn = x + step; cy4 = cl / (xn * xn) - dcc; double cdy4 = -2.0 / xn; yy = y1 + dy1 * step; c14 = (cy4 * (yy + 0.5 * c12 * step) + cdy4 * (dy1 + c13)) * step; y1 = yy + (c11 + c12 + c13) * step / 6.0; dy1 += (0.5 * c11 + c12 + c13 + 0.5 * c14) / 3.0; c21 = (cy1 * y2 + cdy1 * dy2) * step; yc2 = y2 + dy2 * half_step; c22 = (cy23 * yc2 + cdy23 * (dy2 + 0.5 * c21)) * step; c23= (cy23 * (yc2 + 0.25 * c21 * step) + cdy23 * (dy2 + 0.5 * c22)) * step; yy = y2 + dy2 * step; c24 = (cy4 * (yc2 + 0.5 * c22 * step) + cdy4 * (dy2 + c23)) * step; y2 = yy + (c21 + c22 + c23) * step / 6.0; dy2 += (0.5 * c21 + c22 + c23 + 0.5 * c24) / 3.0; x = xn; } } /*! \brief C++ porting of RKT * * \param npntmo: `int` * \param step: `double` * \param x: `double &` * \param lpo: `int` * \param y1: `complex\<double\> &` * \param y2: `complex\<double\> &` * \param dy1: `complex\<double\> &` * \param dy2: `complex\<double\> &` * \param c2: `C2 *` */ void rkt( int npntmo, double step, double &x, int lpo, std::complex<double> &y1, std::complex<double> &y2, std::complex<double> &dy1, std::complex<double> &dy2, C2 *c2 ) { std::complex<double> cy1, cdy1, c11, cy23, cdy23, yc2, c12, c13; std::complex<double> cy4, cdy4, yy, c14, c21, c22, c23, c24; double half_step = 0.5 * step; double cl = 1.0 * lpo * (lpo - 1); for (int ipnt60 = 1; ipnt60 <= npntmo; ipnt60++) { int jpnt = ipnt60 + ipnt60 - 1; cy1 = cl / (x * x) - c2->ris[jpnt - 1]; cdy1 = -2.0 / x; c11 = (cy1 * y1 + cdy1 * dy1) * step; double xh = x + half_step; int jpntpo = jpnt + 1; cy23 = cl / (xh * xh) - c2->ris[jpntpo - 1]; cdy23 = -2.0 / xh; yc2 = y1 + dy1 * half_step; c12 = (cy23 * yc2 + cdy23 * (dy1 + 0.5 * c11)) * step; c13= (cy23 * (yc2 + 0.25 * c11 *step) + cdy23 * (dy1 + 0.5 * c12)) * step; double xn = x + step; int jpntpt = jpnt + 2; cy4 = cl / (xn * xn) - c2->ris[jpntpt - 1]; cdy4 = -2.0 / xn; yy = y1 + dy1 * step; c14 = (cy4 * (yy + 0.5 * c12 * step) + cdy4 * (dy1 + c13)) * step; y1= yy + (c11 + c12 + c13) * step / 6.0; dy1 += (0.5 * c11 + c12 + c13 + 0.5 *c14) /3.0; cy1 -= cdy1 * c2->dlri[jpnt - 1]; cdy1 += 2.0 * c2->dlri[jpnt - 1]; c21 = (cy1 * y2 + cdy1 * dy2) * step; cy23 -= cdy23 * c2->dlri[jpntpo - 1]; cdy23 += 2.0 * c2->dlri[jpntpo - 1]; yc2 = y2 + dy2 * half_step; c22 = (cy23 * yc2 + cdy23 * (dy2 + 0.5 * c21)) * step; c23 = (cy23 * (yc2 + 0.25 * c21 * step) + cdy23 * (dy2 + 0.5 * c22)) * step; cy4 -= cdy4 * c2->dlri[jpntpt - 1]; cdy4 += 2.0 * c2->dlri[jpntpt - 1]; yy = y2 + dy2 * step; c24 = (cy4 * (yc2 + 0.5 * c22 * step) + cdy4 * (dy2 + c23)) * step; y2 = yy + (c21 + c22 + c23) * step / 6.0; dy2 += (0.5 * c21 + c22 + c23 + 0.5 * c24) / 3.0; x = xn; } } /*! \brief C++ porting of RNF * * This is a real spherical Bessel function. * * \param n: `int` * \param x: `double` * \param nm: `int &` * \param sj: `double[]` */ void rnf(int n, double x, int &nm, double sy[]) { /* * FROM SPHJY OF LIBRARY specfun * * ========================================================== * Purpose: Compute spherical Bessel functions y * Input : x --- Argument of y ( x > 0 ) * n --- Order of y ( n = 0,1,2,... ) * Output: sy(n+1) --- y * nm --- Highest order computed * ========================================================== */ if (x < 1.0e-60) { for (int k = 0; k <= n; k++) sy[k] = -1.0e300; return; } sy[0] = -1.0 * cos(x) / x; if (n == 0) { return; } sy[1] = (sy[0] - sin(x)) / x; if (n == 1) { return; } double f0 = sy[0]; double f1 = sy[1]; double f; for (int k = 2; k <= n; k++) { f = (2.0 * k - 1.0) * f1 / x - f0; sy[k] = f; double abs_f = f; if (abs_f < 0.0) abs_f *= -1.0; if (abs_f >= 1.0e300) { nm = k; break; } f0 = f1; f1 = f; nm = k; } return; } /*! \brief C++ porting of SSCR0 * * \param tfsas: `complex<double> &` * \param nsph: `int` * \param lm: `int` * \param vk: `double` * \param exri: `double` * \param c1: `C1 *` */ void sscr0(std::complex<double> &tfsas, int nsph, int lm, double vk, double exri, C1 *c1) { std::complex<double> sum21, rm, re, cc0, csam; cc0 = std::complex<double>(0.0, 0.0); double exdc = exri * exri; double ccs = 4.0 * acos(0.0) / (vk * vk); double cccs = ccs / exdc; csam = -(ccs / (exri * vk)) * std::complex<double>(0.0, 0.5); tfsas = cc0; for (int i12 = 1; i12 <= nsph; i12++) { int iogi = c1->iog[i12 - 1]; if (iogi >= i12) { double sums = 0.0; std::complex<double> sum21 = cc0; for (int l10 = 1; l10 <= lm; l10++) { double fl = 1.0 + l10 + l10; rm = 1.0 / c1->rmi[l10 - 1][i12 - 1]; re = 1.0 / c1->rei[l10 - 1][i12 - 1]; std::complex<double> rm_cnjg = std::complex<double>(rm.real(), -rm.imag()); std::complex<double> re_cnjg = std::complex<double>(re.real(), -re.imag()); sums += (rm_cnjg * rm + re_cnjg * re).real() * fl; sum21 += (rm + re) * fl; } sum21 *= -1.0; double scasec = cccs * sums; double extsec = -cccs * sum21.real(); double abssec = extsec - scasec; c1->sscs[i12 - 1] = scasec; c1->sexs[i12 - 1] = extsec; c1->sabs[i12 - 1] = abssec; double gcss = c1-> gcsv[i12 - 1]; c1->sqscs[i12 - 1] = scasec / gcss; c1->sqexs[i12 - 1] = extsec / gcss; c1->sqabs[i12 - 1] = abssec / gcss; c1->fsas[i12 - 1] = sum21 * csam; } tfsas += c1->fsas[iogi - 1]; } } /*! \brief C++ porting of THDPS * * \param lm: `int` * \param zpv: `double ****` */ void thdps(int lm, double ****zpv) { // WARNING: unclear nested loop in THDPS // The optimized interpretation was adopted here. for (int l10 = 1; l10 <= lm; l10++) { for (int ilmp = 1; ilmp <= 3; ilmp++) { zpv[l10 - 1][ilmp - 1][0][0] = 0.0; zpv[l10 - 1][ilmp - 1][0][1] = 0.0; zpv[l10 - 1][ilmp - 1][1][0] = 0.0; zpv[l10 - 1][ilmp - 1][1][1] = 0.0; } } for (int l15 = 1; l15 <= lm; l15++) { double xd = 1.0 * l15 * (l15 + 1); double zp = -1.0 / sqrt(xd); zpv[l15 - 1][1][0][1] = zp; zpv[l15 - 1][1][1][0] = zp; } if (lm != 1) { for (int l20 = 2; l20 <= lm; l20++) { double xn = 1.0 * (l20 - 1) * (l20 + 1); double xd = 1.0 * l20 * (l20 + l20 + 1); double zp = sqrt(xn / xd); zpv[l20 - 1][0][0][0] = zp; zpv[l20 - 1][0][1][1] = zp; } int lmmo = lm - 1; for (int l25 = 1; l25 <= lmmo; l25++) { double xn = 1.0 * l25 * (l25 + 2); double xd = (l25 + 1) * (l25 + l25 + 1); double zp = -1.0 * sqrt(xn / xd); zpv[l25 - 1][2][0][0] = zp; zpv[l25 - 1][2][1][1] = zp; } } } /*! \brief C++ porting of DME * * \param li: `int` * \param i: `int` * \param npnt: `int` * \param npntts: `int` * \param vk: `double` * \param exdc: `double` * \param exri: `double` * \param c1: `C1 *` * \param c2: `C2 *` * \param jer: `int &` * \param lcalc: `int &` * \param arg: `complex<double> &`. */ void dme( int li, int i, int npnt, int npntts, double vk, double exdc, double exri, C1 *c1, C2 *c2, int &jer, int &lcalc, std::complex<double> &arg) { //double rfj[42], rfn[42]; double *rfj = new double[42]; double *rfn = new double[42]; std::complex<double> cfj[42], fbi[42], fb[42], fn[42]; std::complex<double> rmf[40], drmf[40], ref[40], dref[40]; std::complex<double> dfbi, dfb, dfn, ccna, ccnb, ccnc, ccnd; std::complex<double> y1, dy1, y2, dy2, arin, cri, uim; jer = 0; uim = std::complex<double>(0.0, 1.0); int nstp = npnt - 1; int nstpts = npntts - 1; int lipo = li + 1; int lipt = li + 2; double sz = vk * c1->ros[i - 1]; c2->vsz[i - 1] = sz; double vkr1 = vk * c1->rc[i - 1][0]; int nsh = c1->nshl[i - 1]; c2->vkt[i - 1] = std::sqrt(c2->dc0[0]); arg = vkr1 * c2->vkt[i - 1]; arin = arg; bool goto32 = false; if (arg.imag() != 0.0) { cbf(lipo, arg, lcalc, cfj); if (lcalc < lipo) { jer = 5; return; } for (int j24 = 1; j24 <= lipt; j24++) fbi[j24 - 1] = cfj[j24 - 1]; goto32 = true; } if (!goto32) { rbf(lipo, arg.real(), lcalc, rfj); if (lcalc < lipo) { jer = 5; return; } for (int j30 = 1; j30 <= lipt; j30++) fbi[j30 - 1] = rfj[j30 - 1]; } double arex = sz * exri; arg = arex; rbf(lipo, arex, lcalc, rfj); if (lcalc < lipo) { jer = 7; return; } rnf(lipo, arex, lcalc, rfn); if (lcalc < lipo) { jer = 8; return; } for (int j43 = 1; j43 <= lipt; j43++) { fb[j43 - 1] = rfj[j43 - 1]; //printf("DEBUG: fb[%d] = (%lE,%lE)\n", j43, fb[j43 - 1].real(), fb[j43 - 1].imag()); fn[j43 - 1] = rfn[j43 - 1]; //printf("DEBUG: fn[%d] = (%lE,%lE)\n", j43, fn[j43 - 1].real(), fn[j43 - 1].imag()); } if (nsh <= 1) { cri = c2->dc0[0] / exdc; for (int l60 = 1; l60 <= li; l60++) { int lpo = l60 + 1; int ltpo = lpo + l60; int lpt = lpo + 1; dfbi = ((1.0 * l60) * fbi[l60 - 1] - (1.0 * lpo) * fbi[lpt - 1]) * arin + fbi[lpo - 1] * (1.0 * ltpo); dfb = ((1.0 * l60) * fb[l60 - 1] - (1.0 * lpo) * fb[lpt - 1]) * arex + fb[lpo - 1] * (1.0 * ltpo); dfn = ((1.0 * l60) * fn[l60 - 1] - (1.0 * lpo) * fn[lpt - 1]) * arex + fn[lpo - 1] * (1.0 * ltpo); ccna = fbi[lpo - 1] * dfn; ccnb = fn[lpo - 1] * dfbi; ccnc = fbi[lpo - 1] * dfb; ccnd = fb[lpo - 1] * dfbi; c1->rmi[l60 - 1][i - 1] = 1.0 + uim * (ccna - ccnb) / (ccnc - ccnd); c1->rei[l60 - 1][i - 1] = 1.0 + uim * (cri * ccna - ccnb) / (cri * ccnc - ccnd); } } else { // nsh > 1 int ic = 1; for (int l80 = 1; l80 <= li; l80++) { int lpo = l80 + 1; int ltpo = lpo + l80; int lpt = lpo + 1; int dltpo = ltpo; y1 = fbi[lpo - 1]; dy1 = ((1.0 * l80) * fbi[l80 - 1] - (1.0 * lpo) * fbi[lpt - 1]) * c2->vkt[i - 1] / (1.0 * dltpo); y2 = y1; dy2 = dy1; ic = 1; for (int ns76 = 2; ns76 <= nsh; ns76++) { int nsmo = ns76 - 1; double vkr = vk * c1->rc[i - 1][nsmo - 1]; if (ns76 % 2 != 0) { ic += 1; double step = 1.0 * nstp; step = vk * (c1->rc[i - 1][ns76 - 1] - c1->rc[i - 1][nsmo - 1]) / step; arg = c2->dc0[ic - 1]; rkc(nstp, step, arg, vkr, lpo, y1, y2, dy1, dy2); } else { diel(nstpts, nsmo, i, ic, vk, c1, c2); double stepts = 1.0 * nstpts; stepts = vk * (c1->rc[i - 1][ns76 - 1] - c1->rc[i - 1][nsmo - 1]) / stepts; rkt(nstpts, stepts, vkr, lpo, y1, y2, dy1, dy2, c2); } } rmf[l80 - 1] = y1 * sz; drmf[l80 - 1] = dy1 * sz + y1; ref[l80 - 1] = y2 * sz; dref[l80 - 1] = dy2 * sz + y2; } cri = 1.0 + uim * 0.0; if (nsh % 2 != 0) cri = c2->dc0[ic - 1] / exdc; for (int l90 = 1; l90 <= li; l90++) { int lpo = l90 + 1; int ltpo = lpo + l90; int lpt = lpo + 1; dfb = ((1.0 * l90) * fb[l90 - 1] - (1.0 * lpo) * fb[lpt - 1]) * arex + fb[lpo - 1] * (1.0 * ltpo); dfn = ((1.0 * l90) * fn[l90 - 1] - (1.0 * lpo) * fn[lpt - 1]) * arex + fn[lpo - 1] * (1.0 * ltpo); ccna = rmf[l90 - 1] * dfn; ccnb = drmf[l90 - 1] * fn[lpo - 1] * (1.0 * sz * ltpo); ccnc = rmf[l90 - 1] * dfb; ccnd = drmf[l90 - 1] * fb[lpo -1] * (1.0 * sz * ltpo); c1->rmi[l90 - 1][i - 1] = 1.0 + uim *(ccna - ccnb) / (ccnc - ccnd); //printf("DEBUG: gone 90, rmi[%d][%d] = (%lE,%lE)\n", l90, i, c1->rmi[l90 - 1][i - 1].real(), c1->rmi[l90 - 1][i - 1].imag()); ccna = ref[l90 - 1] * dfn; ccnb = dref[l90 - 1] * fn[lpo - 1] * (1.0 * sz * ltpo); ccnc = ref[l90 - 1] * dfb; ccnd = dref[l90 - 1] *fb[lpo - 1] * (1.0 * sz * ltpo); c1->rei[l90 - 1][i - 1] = 1.0 + uim * (cri * ccna - ccnb) / (cri * ccnc - ccnd); //printf("DEBUG: gone 90, rei[%d][%d] = (%lE,%lE)\n", l90, i, c1->rei[l90 - 1][i - 1].real(), c1->rei[l90 - 1][i - 1].imag()); } } // nsh <= 1 ? return; } #endif /* SRC_INCLUDE_SPH_SUBS_H_ */