def P_BTZn(n,R,rh,l,pm1,Om,lam,sig):
    b = fp.sqrt(R**2-rh**2)/l
    lim = 20*sig*rh/b/l**2
    print('limit: ',lim)
    Zm = fp.mpf(1) #rh**2/(R**2-rh**2)*(R**2/rh**2 * fp.cosh(2*fp.pi*rh/l * n) - 1)
    Zp = rh**2/(R**2-rh**2)*(R**2/rh**2 * fp.cosh(2*fp.pi*rh/l * n) + 1)
    print('Zm: ',Zm, 'Zp: ',Zp, 'acosh(Zp): ', fp.mpf(mp.acosh(Zp)))
    #print(Zm,fp.acosh(Zm))
#    plt.figure()
#    xaxis = fp.linspace(0,lim/5,50)
#    yaxis = [f02(x,n,R,rh,l,pm1,Om,lam,sig) for x in xaxis]
#    plt.plot(xaxis,yaxis)
#    plt.show()
    if pm1==-1 or pm1==1 or pm1==0:
        if n==0:
            return 0\
                 - fp.quad(lambda x: f02(x,n,R,rh,l,pm1,Om,lam,sig),[0,fp.mpf(mp.acosh(Zp))])\
                 - fp.quad(lambda x: f02(x,n,R,rh,l,pm1,Om,lam,sig),[fp.mpf(mp.acosh(Zp)),lim])
                 #fp.quad(lambda x: f01(x,n,R,rh,l,pm1,Om,lam,sig),[-fp.inf,fp.inf])
#        else:
#            if fp.cosh(lim) < Zm or Zm < 1:
#                return fp.quad(lambda x: fn1(x,n,R,rh,l,pm1,Om,lam,sig)\
#                                      - fn2(x,n,R,rh,l,pm1,Om,lam,sig),[0,lim])
#            else:
#                return fp.quad(lambda x: fn1(x,n,R,rh,l,pm1,Om,lam,sig)\
#                                      - fn2(x,n,R,rh,l,pm1,Om,lam,sig),[0,fp.mpf(mp.acosh(Zm))])\
#                     - fp.quad(lambda x: fn1(x,n,R,rh,l,pm1,Om,lam,sig)\
#                                      - fn2(x,n,R,rh,l,pm1,Om,lam,sig),[fp.mpf(mp.acosh(Zm)),lim])
    else:
        print("Please enter a value of 1, -1, or 0 for pm1.")
Exemple #2
0
 def discrete_util(self, tick, elapsed=0.0):
     lower = Time.tick2min(tick) - Time.TIMEUNIT/2.0
     upper = lower + Time.TIMEUNIT
     if tick == 0:
         util = fp.quad(self._marginal_util, [0.0, Time.TIMEUNIT/2.0]) + \
                fp.quad(self._marginal_util, [Time.TIMELENG-Time.TIMEUNIT/2.0, Time.TIMELENG])
     else:
         util = fp.quad(self._marginal_util, [lower, upper])
     return util
Exemple #3
0
 def discrete_util(self, tick, elapsed=0.0):
     lower = Time.tick2min(tick) - Time.TIMEUNIT / 2.0
     upper = lower + Time.TIMEUNIT
     if tick == 0:
         util = fp.quad(self._marginal_util, [0.0, Time.TIMEUNIT/2.0]) + \
                fp.quad(self._marginal_util, [Time.TIMELENG-Time.TIMEUNIT/2.0, Time.TIMELENG])
     else:
         util = fp.quad(self._marginal_util, [lower, upper])
     return util
Exemple #4
0
def integrand_btz_n(u, tau, n, R, rh, l, pm1, Om, lam, sig, deltaphi=0):
    s_int_fnc = lambda s: lam**2 * fp.exp(-s**2/4/sig**2)\
                * (fp.exp(-fp.j*Om*s) * wightman_btz_n(s,n,R,rh,l,pm1,Om,lam,sig))

    if n != 0 or deltaphi != 0:
        pt1 = fp.mpf(
            mp.acosh(rh**2 / (R**2 - rh**2) *
                     (R**2 / rh**2 * fp.cosh(rh / l *
                                             (deltaphi - 2 * fp.pi * n)) - 1)))
    pt2 = fp.mpf(
        mp.acosh(rh**2 / (R**2 - rh**2) *
                 (R**2 / rh**2 * fp.cosh(rh / l *
                                         (deltaphi - 2 * fp.pi * n)) + 1)))
    uplim = 2 * tau - u

    if n == 0:
        if uplim < pt2:
            output = fp.quad(s_int_fnc, [0, uplim])
        else:
            output = fp.quad(s_int_fnc, [0, pt2]) + fp.quad(
                s_int_fnc, [pt2, uplim])

    else:
        if uplim < pt1:
            output = fp.quad(s_int_fnc, [0, uplim])
        elif uplim < pt2:
            output = fp.quad(s_int_fnc, [0, pt1]) + fp.quad(
                s_int_fnc, [pt1, uplim])
        else:
            output = fp.quad(s_int_fnc,[0,pt1]) + fp.quad(s_int_fnc,[pt1,pt2])\
                        + fp.quad(s_int_fnc,[pt2,uplim])

    output *= fp.exp(-u**2 / 4 / sig**2)
    return output
def Xn_plus(n, RA, RB, rh, l, pm1, Om, lam, tau0, width, deltaphi, isP):

    intlim2 = l**2/rh * mp.acosh( (RA*RB/rh**2 * fp.mpf( mp.cosh(rh/l * (deltaphi-2*fp.pi*n)) ) + 1)\
                / fp.sqrt(RA**2-rh**2)/fp.sqrt(RB**2-rh**2)*rh**2)
    #print('plus, %.4f ;'%intlim2)
    f = lambda y: integrandof_Xn_plus(y, n, RA, RB, rh, l, pm1, Om, lam, tau0,
                                      width, deltaphi, isP)

    if intlim2 < width:
        return fp.quad(f, [0, intlim2]) + fp.quad(f, [intlim2, width])
    else:
        return fp.quad(f, [0, width])
def XG_plusBA(n, RA, RB, rh, l, pm1, Om, lam, tau0, width, deltaphi, isP):
    bA = mp.sqrt(RA**2 - rh**2) / l
    bB = mp.sqrt(RB**2 - rh**2) / l
    f = lambda y: 2/Om/(bB-bA) * fp.exp(-fp.j*Om/2*(bB+bA)*y)\
                    * h_n2(y,n,RA,RB,rh,l,pm1,deltaphi,isP)\
                    * fp.sin( Om/2*(bB-bA)*(2*(tau0+width)-y))
    return fp.quad(f, [2 * tau0 + width, 2 * (tau0 + width)])
def XG_minusAB(n, RA, RB, rh, l, pm1, Om, lam, tau0, width, deltaphi, isP):
    bA = mp.sqrt(RA**2 - rh**2) / l
    bB = mp.sqrt(RB**2 - rh**2) / l
    f = lambda y: 2/Om/(bB-bA) * fp.exp(-fp.j*Om/2*(bB+bA)*y)\
                    * h_n1(y,n,RA,RB,rh,l,pm1,deltaphi,isP)\
                    * fp.sin( Om/2*(bB-bA)*(y-2*tau0))
    return fp.quad(f, [2 * tau0, 2 * tau0 + width])
Exemple #8
0
def PGEON_n(n, R, rh, l, pm1, Om, lam, sig):
    """
    Om = energy difference
    lam = coupling constant
    """
    if pm1 == -1 or pm1 == 1 or pm1 == 0:
        return lam**2*sig*fp.sqrt(fp.pi) * fp.mpf(mp.exp(-sig**2 * Om**2)) *\
        fp.quad(lambda x: h_n(x,n,R,rh,l,pm1) * PGEON_gaussian(x,sig), [-fp.inf, fp.inf])
    else:
        print("Please enter a value of 1, -1, or 0 for pm1.")
def P_BTZn(n,
           RA,
           RB,
           rh,
           l,
           pm1,
           Om,
           lam,
           tau0,
           width,
           deltaphi=0,
           eps=1e-8,
           isP=True):
    f = lambda y: integrandof_P_BTZn(y, n, RA, RB, rh, l, pm1, Om, lam, tau0,
                                     width, deltaphi, isP)

    if n == 0 and deltaphi == 0 and RA == RB:
        # P0m
        P0m = 2 * fp.quad(
            lambda x: integrandPBTZ_0m(x, RA, rh, l, pm1, Om, lam, tau0, width,
                                       eps), [0, width])

        intlim = l**2/rh * mp.acosh( (RA*RB/rh**2 * fp.mpf( mp.cosh(rh/l * (deltaphi-2*fp.pi*n)) ) + 1)\
                / fp.sqrt(RA**2-rh**2)/fp.sqrt(RB**2-rh**2)*rh**2)
        if intlim < width:
            return fp.quad(f, [0, intlim]) + fp.quad(f, [intlim, width]) + P0m
        else:
            return fp.quad(f, [0, width]) + P0m

    else:

        intlim1 = l**2/rh * mp.acosh( (RA*RB/rh**2 * fp.mpf( mp.cosh(rh/l * (deltaphi-2*fp.pi*n)) ) - 1)\
                / fp.sqrt(RA**2-rh**2)/fp.sqrt(RB**2-rh**2)*rh**2)
        intlim2 = l**2/rh * mp.acosh( (RA*RB/rh**2 * fp.mpf( mp.cosh(rh/l * (deltaphi-2*fp.pi*n)) ) + 1)\
                / fp.sqrt(RA**2-rh**2)/fp.sqrt(RB**2-rh**2)*rh**2)
        #print('%.4f, %.4f'%(intlim1,intlim2))
        if intlim2 < width:
            return fp.quad(f, [0, intlim1]) + fp.quad(
                f, [intlim1, intlim2]) + fp.quad(f, [intlim2, width])
        elif intlim1 < width:
            return fp.quad(f, [0, intlim1]) + fp.quad(f, [intlim1, width])
        else:
            return fp.quad(f, [0, width])
Exemple #10
0
def P_BTZn(n, R, rh, l, pm1, Om, lam, sig):
    b = fp.sqrt(R**2 - rh**2) / l
    lim = 20 * sig * rh / b / l**2
    #Zp = mp.mpf(rh**2/(R**2-rh**2)*(R**2/rh**2 * fp.cosh(2*fp.pi*rh/l * n) + 1))
    #print('Zm: ',Zm, 'Zp: ',Zp)
    #print(Zm,fp.acosh(Zm))
    if pm1 == -1 or pm1 == 1 or pm1 == 0:
        if n == 0:
            return fp.quad(lambda x: f01(x, n, R, rh, l, pm1, Om, lam, sig),
                           [-fp.inf, fp.inf])
        else:
            Zm = rh**2 / (R**2 - rh**2) * (
                R**2 / rh**2 * fp.cosh(2 * fp.pi * rh / l * n) - 1)
            if fp.cosh(lim) < Zm or Zm < 1:
                return fp.quad(lambda x: fn1(x,n,R,rh,l,pm1,Om,lam,sig)\
                                      - fn2(x,n,R,rh,l,pm1,Om,lam,sig),[0,lim])
            else:
                return fp.quad(lambda x: fn1(x,n,R,rh,l,pm1,Om,lam,sig)\
                                      - fn2(x,n,R,rh,l,pm1,Om,lam,sig),[0,fp.mpf(mp.acosh(Zm))])\
                     - fp.quad(lambda x: fn1(x,n,R,rh,l,pm1,Om,lam,sig)\
                                      - fn2(x,n,R,rh,l,pm1,Om,lam,sig),[fp.mpf(mp.acosh(Zm)),lim])
    else:
        print("Please enter a value of 1, -1, or 0 for pm1.")
Exemple #11
0
def T_PGEON_n(tau, n, R, rh, l, pm1, Om, lam, sig, deltaphi=0):
    return fp.quad(
        lambda x: T_P_int_geon(
            x, tau, n, R, rh, l, pm1, Om, lam, sig, deltaphi=0),
        [-10 * sig, 2 * tau])
Exemple #12
0
def P_BTZ_n_tau(tau, n, R, rh, l, pm1, Om, lam, sig, deltaphi=0):
    return fp.quad(
        lambda u: integrand_btz_n(
            u, tau, n, R, rh, l, pm1, Om, lam, sig, deltaphi=0),
        [-10 * sig, 2 * tau])
Exemple #13
0
def integral1(a):
    return fp.quad(lambda x: integrand1(x, a), [-fp.inf, a])
Exemple #14
0
def Pdot_n(tau, n, R, rh, l, pm1, Om, lam, sig, deltaphi=0, eps=1e-6):
    if n == 0:
        if deltaphi == 0:
            lim2 = fp.mpf(mp.acosh(mp.mpf(rh**2/(R**2-rh**2)\
                                          *(R**2/rh**2 * fp.cosh(rh/l * (deltaphi - 2*fp.pi*n)) + 1))))
            #print(lim2)
            fmins = lambda s: integrand_Pdotm_n(s, tau, 0, R, rh, l, pm1, Om,
                                                lam, sig, deltaphi, eps).real
            fplus = lambda s: integrand_Pdotp_n(s, tau, 0, R, rh, l, pm1, Om,
                                                lam, sig, deltaphi, eps).real
            return fp.quad(fmins, [0, tau + 10 * sig]) + fp.quad(
                fplus, [0, lim2]) + fp.quad(fplus, [lim2, tau + 10 * sig])
        else:
            lim1 = fp.mpf(mp.acosh(mp.mpf(rh**2/(R**2-rh**2)\
                                          *(R**2/rh**2 * fp.cosh(rh/l * (deltaphi - 2*fp.pi*n)) - 1))))
            lim2 = fp.mpf(mp.acosh(mp.mpf(rh**2/(R**2-rh**2)\
                                          *(R**2/rh**2 * fp.cosh(rh/l * (deltaphi - 2*fp.pi*n)) + 1))))
            fmins = lambda s: integrand_Pdotm_n(s, tau, 0, R, rh, l, pm1, Om,
                                                lam, sig, deltaphi, 0).real
            fplus = lambda s: integrand_Pdotp_n(s, tau, 0, R, rh, l, pm1, Om,
                                                lam, sig, deltaphi, 0).real
            return fp.quad(fmins,[0,lim1]) + fp.quad(fmins,[lim1,tau+10*sig])\
                   + fp.quad(fplus,[0,lim2]) + fp.quad(fplus,[lim2,tau+10*sig])
    else:
        lim1 = fp.mpf(mp.acosh(mp.mpf(rh**2/(R**2-rh**2)\
                                      *(R**2/rh**2 * fp.cosh(rh/l * (deltaphi - 2*fp.pi*n)) - 1))))
        lim2 = fp.mpf(mp.acosh(mp.mpf(rh**2/(R**2-rh**2)\
                                      *(R**2/rh**2 * fp.cosh(rh/l * (deltaphi - 2*fp.pi*n)) + 1))))
        fmins = lambda s: integrand_Pdotm_n(s, tau, n, R, rh, l, pm1, Om, lam,
                                            sig, deltaphi, 0).real
        fplus = lambda s: integrand_Pdotp_n(s, tau, n, R, rh, l, pm1, Om, lam,
                                            sig, deltaphi, 0).real
        return fp.quad(fmins,[0,lim1]) + fp.quad(fmins,[lim1,tau+10*sig])\
               + fp.quad(fplus,[0,lim2]) + fp.quad(fplus,[lim2,tau+10*sig])
Exemple #15
0
def DeltaPdot_n(tau, n, R, rh, l, pm1, Om, lam, sig, deltaphi=0):
    f = lambda s: integrand_deltaPdot_n(s, tau, n, R, rh, l, pm1, Om, lam, sig,
                                        deltaphi)
    return fp.quad(f, [0, tau + 10 * sig])
Exemple #16
0
        counter += 1
        value = integrand_Pdotm_n(si, t, n, R, rh, l, pm1, Om[0], lam, sig, 0,
                                  eps)
        integrandminus_re.append(value.real)
        #integrandminus_im.append(value.imag)

    plt.plot(s, integrandminus_re, label='tau = ' + str(t))
    integrandminus_re = []
    #plt.plot(s,integrandminus_im,label='imag')
plt.legend()
plt.xlabel('integration variable')
plt.ylabel('integrand')
plt.title('n=0')

f = lambda x: integrand_Pdotm_n(x, tau, n, R, rh, l, pm1, Om, lam, sig, 0, 0)
print('\nintegral is: ', fp.quad(f, [0, tau + 10 * sig]))
#%% check

for En in Om:

    for ii in range(len(M)):
        nmax = converge_cutoff(M[ii], 0.002)
        print('nmax =', nmax)

        tau = np.linspace(-5, 5, num=81)
        tr_rate = 0 * tau
        tr_rate_geon = 0 * tau

        for n in range(nmax + 1):
            print('n =', n)
            print('i =', end='')
Exemple #17
0
def integrand2(u, a):
    f = lambda s: fp.exp(-s**2) * (fp.exp(fp.j*(s+u)) * fp.mpf(mp.exp(-np.abs(u)))\
                                  + fp.exp(fp.j*u) * fp.mpf(mp.exp(-np.abs(s+u))) )
    return fp.quad(f, [0, fp.inf])
Exemple #18
0
def integrand1(x, a):
    f = lambda x2: fp.exp(-(x - x2)**2) * fp.exp(-fp.j * x) * fp.exp(-np.abs(x2
                                                                             ))
    return fp.quad(f, [-fp.inf, a])
Exemple #19
0
def integral2(a):
    return fp.quad(lambda u: integrand2(u, a), [-fp.inf, a])
################################

y = np.linspace(-0.5, 4, num=101)

th_re, th_im, gau_re, gau_im = [], [], [], []

for yi in y:
    th = integrandPBTZ_0m(yi, RA, rh, l, pm1, Om, lam, 0, width, eps)
    th_re.append(th.real)
    th_im.append(th.imag)
    gau = integrandPBTZ_0m_GAUSS(yi, RA, rh, l, pm1, Om, lam, sig, eps)
    gau_re.append(gau.real)
    gau_im.append(gau.imag)

gau_integral = fp.quad(
    lambda y: integrandPBTZ_0m_GAUSS(y, RA, rh, l, pm1, Om, lam, sig, eps),
    [0, 10])
th_integral = fp.quad(
    lambda y: integrandPBTZ_0m(y, RA, rh, l, pm1, Om, lam, tau0, width, eps),
    [0, width])

###
fig2 = plt.figure(figsize=(5, 4))
plt.plot(y, th_im, label='top hat imaginary')
plt.plot(y, gau_im, label='gaussian imaginary')
plt.legend()

###
fig = plt.figure(figsize=(9, 5))
plt.plot(y, th_re, label='top hat')
plt.plot(y, gau_re, label='gaussian')
def PGEON_n(n, RA, RB, rh, l, pm1, Om, lam, tau0, width, deltaphi=0, isP=True):
    return fp.quad(lambda y: integrandof_PGEON_n(y,n,RA,RB,rh,l,pm1,Om,lam,tau0,width,deltaphi,isP)\
                   , [0,width])
def P0m_GAUSS(R, rh, l, pm1, Om, lam, sig, eps=1e-8):
    f = lambda y: integrandPBTZ_0m_GAUSS(y, R, rh, l, pm1, Om, lam, sig, eps)
    return fp.quad(f, [0, fp.inf])
Exemple #23
0
def integrate(f, limx, limy, limz, method):
    if method == "mp-gl":
        if limz != 0:
            return mp.quad(f, limx, limy, limz, method="gauss-legendre")
        else:
            if limy != 0:
                return mp.quad(f, limx, limy, method="gauss-legendre")
            else:
                return mp.quad(f, limx, method="gauss-legendre")
    elif method == "mp-ts":
        if limz != 0:
            return mp.quad(f, limx, limy, limz, method="tanh-sinh")
        else:
            if limy != 0:
                return mp.quad(f, limx, limy, method="tanh-sinh")
            else:
                return mp.quad(f, limx, method="tanh-sinh")
    elif method == "fp-gl":
        if limz != 0:
            return fp.quad(f, limx, limy, limz, method="gauss-legendre")
        else:
            if limy != 0:
                return fp.quad(f, limx, limy, method="gauss-legendre")
            else:
                return fp.quad(f, limx, method="gauss-legendre")
    elif method == "fp-ts":
        if limz != 0:
            return fp.quad(f, limx, limy, limz, method="tanh-sinh")
        else:
            if limy != 0:
                return fp.quad(f, limx, limy, method="tanh-sinh")
            else:
                return fp.quad(f, limx, method="tanh-sinh")
    elif method == "sp-quad":
        if limz != 0:
            return spint.tplquad(f, limz[0], limz[1], limy[0], limy[1],
                                 limx[0], limx[1])[0]
        else:
            if limy != 0:
                return spint.dblquad(f, limy[0], limy[1], limx[0], limx[1])[0]
            else:
                return spint.quad(f, limx[0], limx[1])[0]

    elif method == "romberg":
        if not np.ndim(limx) == 0:
            limx = [float(limx[0]), float(limx[1])]
        if not np.ndim(limy) == 0:
            limy = [float(limy[0]), float(limy[1])]
        if not np.ndim(limz) == 0:
            limz = [float(limz[0]), float(limz[1])]

        reltol = 1e-16
        abstol = 1e-16

        if limz != 0:
            return spint.romberg(lambda z: spint.romberg(
                lambda y: spint.romberg(lambda x: float(f(x, y, z)),
                                        limx[0],
                                        limx[1],
                                        tol=abstol,
                                        rtol=reltol),
                limy[0],
                limy[1],
                tol=abstol,
                rtol=reltol),
                                 limz[0],
                                 limz[1],
                                 tol=abstol,
                                 rtol=reltol)
        else:
            if limy != 0:
                return spint.romberg(
                    lambda y: spint.romberg(lambda x: float(f(x, y)),
                                            limx[0],
                                            limy[1],
                                            tol=abstol,
                                            rtol=reltol),
                    limy[0],
                    limy[1],
                    tol=abstol,
                    rtol=reltol)
            else:
                return spint.romberg(lambda x: float(f(x)),
                                     limx[0],
                                     limx[1],
                                     tol=abstol,
                                     rtol=reltol)

    #currently broken, but slow so unused
    elif method == "sp-gauss":
        if not np.ndim(limx) == 0:
            limx = [float(limx[0]), float(limx[1])]
        if not np.ndim(limy) == 0:
            limy = [float(limy[0]), float(limy[1])]
        if not np.ndim(limz) == 0:
            limz = [float(limz[0]), float(limz[1])]

        order = 7

        if limz != 0:
            return spint.fixed_quad(
                lambda z: spint.fixed_quad(lambda y: spint.fixed_quad(
                    lambda x: f(x, y, z), limx[0], limx[1], n=order)[0],
                                           limy[0],
                                           limy[1],
                                           n=order)[0],
                limz[0],
                limz[1],
                n=order)[0]
        else:
            if limy != 0:
                return spint.fixed_quad(lambda y: spint.romberg(
                    lambda x: f(x, y), limx[0], limy[1], n=order)[0],
                                        limy[0],
                                        limy[1],
                                        n=order)[0]
            else:
                return spint.fixed_quad(lambda x: f(x),
                                        limx[0],
                                        limx[1],
                                        n=order)[0]

    elif method == "w-cumsum":
        if not np.ndim(limx) == 0:
            limx = [float(limx[0]), float(limx[1])]
        if not np.ndim(limy) == 0:
            limy = [float(limy[0]), float(limy[1])]
        if not np.ndim(limz) == 0:
            limz = [float(limz[0]), float(limz[1])]

        if limz != 0:
            dx = (limx[1] - limx[0]) / def_nodes
            dy = (limy[1] - limy[0]) / def_nodes
            dz = (limz[1] - limz[0]) / def_nodes

            loop = 0
            lastres = 0
            while True:
                xl = np.arange(limx[0], limx[1], dx)
                yl = np.arange(limy[0], limy[1], dy)
                zl = np.arange(limz[0], limz[1], dz)

                X, Y, Z = np.meshgrid(xl, yl, zl)

                fx = []
                for i in range(0, len(X)):
                    fy = []
                    for j in range(0, len(Y)):
                        fz = []
                        for k in range(0, len(Z)):
                            fz.append(f(X[i][j][k], Y[i][j][k], zl[k]))
                        fy.append(spint.simps(fz, dx=dz))
                    fx.append(spint.simps(fy, dx=dy))
                res = spint.simps(fx, dx=dx)
                if loop != 0:
                    if np.abs(res - lastres) / res < err_rel:
                        return res
                    else:
                        ad = (1 / 2)**loop
                        #linear to begin with
                        dx = dx * ad
                        dy = dy * ad
                        dz = dz * ad
                        lastres = res
                if loop > maxloop:
                    break
                loop += 1
            else:
                if limy != 0:
                    dx = def_dx
                    dy = def_dx

                    loop = 0
                    lastres = 0
                    while True:
                        xl = np.arange(limx[0], limx[1], dx)
                        yl = np.arange(limy[0], limy[1], dy)

                        X, Y = np.meshgrid(xl, yl)

                        fx = []
                        for i in range(0, len(X)):
                            fy = []
                            for j in range(0, len(Y)):
                                fy.append(f(X[i][j], yl[j]))
                            fx.append(spint.simps(fy, dx=dy))
                        res = spint.simps(fx, dx=dx)
                        if loop != 0:
                            if np.abs(res - lastres) / res < err_rel:
                                return res
                            else:
                                ad = (1 / 2)**loop
                                #linear to begin with
                                dx = dx * ad
                                dy = dy * ad
                                lastres = res
                        if loop > maxloop:
                            break
                        loop += 1
                else:
                    dx = def_dx

                    loop = 0
                    lastres = 0
                    while True:
                        xl = np.arange(limx[0], limx[1], dx)

                        fx = []
                        for i in range(0, len(X)):
                            fx.append(f(xl[i]))

                        res = spint.simps(fx, dx=dx)
                        if loop != 0:
                            if np.abs(res - lastres) / res < err_rel:
                                return res
                        else:
                            ad = (1 / 2)**loop
                            #linear to begin with
                            dx = dx * ad
                            lastres = res
                        if loop > maxloop:
                            break
                        loop += 1

    #still a bit broken but proved slower than mp-gl
    elif method == "monte-carlo":
        N = int(1e6)

        if limz != 0:
            N = int(round(N**(1 / 3)))
            x = np.random.rand(N) * (limx[1] - limx[0]) + limx[0]
            y = np.random.rand(N) * (limy[1] - limy[0]) + limy[0]
            z = np.random.rand(N) * (limz[1] - limy[0]) + limz[0]

            X, Y, Z = np.meshgrid(x, y, z)

            fxyz = []
            for i in range(0, len(X)):
                fxy = []
                for j in range(0, len(Y)):
                    fx = []
                    for k in range(0, len(Z)):
                        fx.append(f(X[i][j][k], Y[i][j][k], Z[i][j][k]))
                    fxy.append(fx)
                fxyz.append(fxy)

            wmax = np.max(fxyz)
            wmin = np.min(fxyz)

            W = np.random.rand(N, N, N) * (wmax - wmin) + wmin

            est = 0
            for i in range(0, len(fxyz)):
                for j in range(0, len(fxyz[i])):
                    for k in range(0, len(fxyz[i][j])):
                        if W[i][j][k] > 0 and W[i][j][k] < fxyz[i][j][k]:
                            est = est + fxyz[i][j][k]
                        elif W[i][j][k] < 0 and W[i][j][k] > fxyz[i][j][k]:
                            est = est + fxyz[i][j][k]

                return (est / (N**3)) * (limx[1] - limx[0]) * (
                    limy[1] - limy[0]) * (limz[1] - limz[0]) * (wmax - wmin)
        else:
            if limy != 0:
                N = int(round(N**(1 / 2)))
                x = np.random.rand(N) * (limx[1] - limx[0]) + limx[0]
                y = np.random.rand(N) * (limy[1] - limy[0]) + limy[0]

                X, Y = np.meshgrid(x, y)

                fxy = []
                for i in range(0, len(X)):
                    fx = []
                    for j in range(0, len(Y)):
                        fx.append(f(X[i][j], Y[i][j]))
                    fxy.append(fx)

                zmax = np.max(fxy)
                zmin = np.min(fxy)

                Z = np.random.rand(N, N) * (zmax - zmin) + zmin

                est = 0
                for i in range(0, len(fxy)):
                    for j in range(0, len(fxy[i])):
                        if Z[i][j] > 0 and Z[i][j] < fxy[i][j]:
                            est = est + fxy[i][j]
                        elif Z[i][j] < 0 and Z[i][j] > fxy[i][j]:
                            est = est + fxy[i][j]

                return (est / (N**2)) * (limx[1] - limx[0]) * (
                    limy[1] - limy[0]) * (zmax - zmin)
            else:
                X = np.random.rand(N) * (limx[1] - limx[0]) + limx[0]

                fx = []
                for i in range(0, len(X)):
                    fx.append(f(X[i]))

                ymax = np.max(fx)
                ymin = np.min(fx)

                Y = np.random.rand(N) * (ymax - ymin) + ymin

                est = 0
                for i in range(0, len(fx)):
                    if Y[i] > 0 and Y[i] < fx[i]:
                        est = est + fx[i]
                    elif Y[i] < 0 and Y[i] > fx[i]:
                        est = est + fx[i]

                return (est / N) * (limx[1] - limx[0]) * (ymax - ymin)

    #preallocated, expected to be slow
    elif method == "sp-simps":
        if limz != 0:
            dx = (limx[1] - limx[0]) / def_nodes
            dy = (limy[1] - limy[0]) / def_nodes
            dz = (limz[1] - limz[0]) / def_nodes

            loop = 0
            lastres = 0
            while True:
                xl = np.arange(limx[0], limx[1], dx)
                yl = np.arange(limy[0], limy[1], dy)
                zl = np.arange(limz[0], limz[1], dz)

                X, Y, Z = np.meshgrid(xl, yl, zl)

                fx = []
                for i in range(0, len(X)):
                    fy = []
                    for j in range(0, len(Y)):
                        fz = []
                        for k in range(0, len(Z)):
                            fz.append(f(X[i][j][k], Y[i][j][k], zl[k]))
                        fy.append(spint.simps(fz, dx=dz))
                    fx.append(spint.simps(fy, dx=dy))
                res = spint.simps(fx, dx=dx)
                if loop != 0:
                    if np.abs(res - lastres) / res < err_rel:
                        return res
                    else:
                        ad = (1 / 2)**loop
                        #linear to begin with
                        dx = dx * ad
                        dy = dy * ad
                        dz = dz * ad
                        lastres = res
                if loop > maxloop:
                    break
                loop += 1
            else:
                if limy != 0:
                    dx = def_dx
                    dy = def_dx

                    loop = 0
                    lastres = 0
                    while True:
                        xl = np.arange(limx[0], limx[1], dx)
                        yl = np.arange(limy[0], limy[1], dy)

                        X, Y = np.meshgrid(xl, yl)

                        fx = []
                        for i in range(0, len(X)):
                            fy = []
                            for j in range(0, len(Y)):
                                fy.append(f(X[i][j], yl[j]))
                            fx.append(spint.simps(fy, dx=dy))
                        res = spint.simps(fx, dx=dx)
                        if loop != 0:
                            if np.abs(res - lastres) / res < err_rel:
                                return res
                            else:
                                ad = (1 / 2)**loop
                                #linear to begin with
                                dx = dx * ad
                                dy = dy * ad
                                lastres = res
                        if loop > maxloop:
                            break
                        loop += 1
                else:
                    dx = def_dx

                    loop = 0
                    lastres = 0
                    while True:
                        xl = np.arange(limx[0], limx[1], dx)

                        fx = []
                        for i in range(0, len(X)):
                            fx.append(f(xl[i]))

                        res = spint.simps(fx, dx=dx)
                        if loop != 0:
                            if np.abs(res - lastres) / res < err_rel:
                                return res
                        else:
                            ad = (1 / 2)**loop
                            #linear to begin with
                            dx = dx * ad
                            lastres = res
                        if loop > maxloop:
                            break
                        loop += 1

            return res