Ejemplo n.º 1
0
    def Ie(self,n,z):
        """even first-kind radial Mathieu function (Ie) 
        analogous to I Bessel functions, called Ce in McLachlan p248 (eq 1&2), 
        for scalar or vector orders or argument

        n: order (scalar or vector)
        z: radial argument (scalar or vector)"""

        from scipy.special import ive
        n,z,sqrtq,v1,v2,M,EV,OD = self._RadFuncSetup(n,z)
        y = np.empty((n.shape[0],z.shape[0]),dtype=complex)

        ord = self.ord[0:M+1]
        sgn = self.sgnord[0:M,None,None]
        I1 = ive(ord[0:M+1,None],v1[None,:])[:,None,:]
        I2 = ive(ord[0:M+1,None],v2[None,:])[:,None,:]
        j = n[:]//2

        y[EV,:] = (np.sum(sgn*self.A[0:M,j[EV],0,:]*I1[0:M,:,:]*I2[0:M,:,:],axis=0)/
                   self.A[0,j[EV],0,:])
        
        y[OD,:] = (np.sum(sgn*self.B[0:M,j[OD],1,:] * 
                     (I1[0:M,:,:]*I2[1:M+1,:,:] + I1[1:M+1,:,:]*I2[0:M,:,:]),axis=0)/
                   self.B[0,j[OD],1,:])

	# scaling factor to un-scale products of Bessel functions from ive()
        y *= np.exp(np.abs(v1.real) + np.abs(v2.real))[None,:]
        return np.squeeze(y)
Ejemplo n.º 2
0
    def Io(self,n,z):
        """odd first-kind radial Mathieu function (Io) 
        analogous to I Bessel functions, called Se in McLachlan p248 (eq 3&4), 
        for scalar or vector orders or argument

        n: order (scalar or vector)
        z: radial argument (scalar or vector)"""
        
        from scipy.special import ive
        n,z,sqrtq,v1,v2,M,EV,OD = self._RadFuncSetup(n,z)
        y = np.empty((n.shape[0],z.shape[0]),dtype=complex)

        ord = self.ord[0:M+2]
        sgn = self.sgnord[0:M,None,None]
        I1 = ive(ord[0:M+2,None],v1[None,:])[:,None,:]
        I2 = ive(ord[0:M+2,None],v2[None,:])[:,None,:]        
        j = (n[:]-1)//2  # Io_0() invalid

        y[EV,:] = (np.sum(sgn*self.B[0:M,j[EV],0,:] *
                     (I1[0:M,:,:]*I2[2:M+2,:,:] - I1[2:M+2,:,:]*I2[0:M,:,:]),axis=0)/
                    self.B[0,j[EV],0,:])

        y[OD,:] = (np.sum(sgn*self.A[0:M,j[OD],1,:] *
                     (I1[0:M,:,:]*I2[1:M+1,:,:] - I1[1:M+1,:,:]*I2[0:M,:,:]),axis=0)/
                    self.A[0,j[OD],1,:])

        y *= np.exp(np.abs(v1.real) + np.abs(v2.real))[None,:]
        y[n==0,:] = np.NaN
        return np.squeeze(y)
Ejemplo n.º 3
0
    def dIo(self,n,z):
        """odd first-kind radial Mathieu function derivative (DIo) 
        (analogous to I Bessel functions, called Se in McLachlan p248), 
        for scalar or vector orders or argument

        n: order (scalar or vector)
        z: radial argument (scalar or vector)"""
        
        from scipy.special import ive
        n,z,sqrtq,enz,epz,v1,v2,M,EV,OD = self._RadDerivFuncSetup(n,z)
        dy = np.empty((n.shape[0],z.shape[0]),dtype=complex)

        ord = self.ord[0:M+2]
        sgn = self.sgnord[0:M,None,None]
        I1 = ive(ord[0:M+2,None],v1[None,:])[:,None,:]
        I2 = ive(ord[0:M+2,None],v2[None,:])[:,None,:]
        dI1 = self._deriv(v1,I1[0:M+2,0,:],0)[:,None,:]
        dI2 = self._deriv(v2,I2[0:M+2,0,:],0)[:,None,:]
        j = (n[:]-1)//2

        dy[EV,:] = (sqrtq/self.B[0,j[EV],0,:]*np.sum(sgn*self.B[0:M,j[EV],0,:] *
                     (epz*I1[0:M,:,:]*dI2[2:M+2,:,:] - enz*dI1[0:M,:,:]*I2[2:M+2,:,:] - 
                     (epz*I1[2:M+2,:,:]*dI2[0:M,:,:] - enz*dI1[2:M+2,:,:]*I2[0:M,:,:])),axis=0))

        dy[OD,:] = (sqrtq/self.A[0,j[OD],1,:]*np.sum(sgn*self.A[0:M,j[OD],1,:] * 
                     (epz*I1[0:M,:,:]*dI2[1:M+1,:,:] - enz*dI1[0:M,:,:]*I2[1:M+1,:,:] - 
                     (epz*I1[1:M+1,:,:]*dI2[0:M,:,:] - enz*dI1[1:M+1,:,:]*I2[0:M,:,:])),axis=0))
        
        dy *= np.exp(np.abs(v1.real) + np.abs(v2.real))[None,:]
        dy[n==0,:] = np.NaN # dIo_0() invalid
        return np.squeeze(dy)
Ejemplo n.º 4
0
    def dKo(self,n,z):
        """odd second-kind radial Mathieu function derivative (DKo) 
        (analogous to K Bessel functions, called Gek in McLachlan p248), 
        for scalar or vector orders or argument

        n: order (scalar or vector)
        z: radial argument (scalar or vector)"""
        
        from scipy.special import kve,ive
        n,z,sqrtq,enz,epz,v1,v2,M,EV,OD = self._RadDerivFuncSetup(n,z)
        dy = np.empty((n.shape[0],z.shape[0]),dtype=complex)

        ord = self.ord[0:M+2]
        I = ive(ord[0:M+2,None],v1[None,:])[:,None,:]
        K = kve(ord[0:M+2,None],v2[None,:])[:,None,:]
        dI = self._deriv(v1,I[0:M+2,0,:],0)[:,None,:]
        dK = self._deriv(v2,K[0:M+2,0,:],1)[:,None,:]
        j = (n[:]-1)//2 

        dy[EV,:] = (sqrtq/self.B[0,j[EV],0,:]*np.sum(self.B[0:M,j[EV],0,:] *
                     (epz*I[0:M,:,:]*dK[2:M+2,:,:] - enz*dI[0:M,:,:]*K[2:M+2,:,:] -
                     (epz*I[2:M+2,:,:]*dK[0:M,:,:] - enz*dI[2:M+2,:,:]*K[0:M,:,:])),axis=0))

        dy[OD,:] = (sqrtq/self.A[0,j[OD],1,:]*np.sum(self.A[0:M,j[OD],1,:] *
                     (epz*I[0:M,:,:]*dK[1:M+1,:,:] - enz*dI[0:M,:,:]*K[1:M+1,:,:] + 
                      epz*I[1:M+1,:,:]*dK[0:M,:,:] - enz*dI[1:M+1,:,:]*K[0:M,:,:]),axis=0))

        dy *= np.exp(np.abs(v1.real) - v2)[None,:]
        dy[n==0,:] = np.NaN  # dKo_0() invalid
        return np.squeeze(dy)
Ejemplo n.º 5
0
    def __init__(self,pset,psf_model):   
        PDF.__init__(self,pset)
        self._psf_model = copy.deepcopy(psf_model)
#        self._pid = [pnorm.pid(),psigma.pid()]

        x = np.linspace(-4,4,800)
        self._ive = UnivariateSpline(x,spfn.ive(0,10**x),s=0,k=2)
Ejemplo n.º 6
0
    def Ko(self,n,z):
        """odd second-kind radial Mathieu function (Ko) 
        (analogous to K Bessel functions, called Gek in McLachlan p248), 
        for scalar or vector orders or argument

        n: order (scalar or vector)
        z: radial argument (scalar or vector)"""
        
        from scipy.special import kve,ive
        n,z,sqrtq,v1,v2,M,EV,OD = self._RadFuncSetup(n,z)
        y = np.empty((n.shape[0],z.shape[0]),dtype=complex)

        ord = self.ord[0:M+2]
        I = ive(ord[0:M+2,None],v1[None,:])[:,None,:]
        K = kve(ord[0:M+2,None],v2[None,:])[:,None,:]
        j = (n[:]-1)//2  

        y[EV,:] = (np.sum(self.B[0:M,j[EV],0,:] *
                     (I[0:M,:,:]*K[2:M+2,:,:] - I[2:M+2,:,:]*K[0:M,:,:]),axis=0)/
                   self.B[0,j[EV],0,:])

        y[OD,:] = (np.sum(self.A[0:M,j[OD],1,:] *
                     (I[0:M,:,:]*K[1:M+1,:,:] + I[1:M+1,:,:]*K[0:M,:,:]),axis=0)/
                   self.A[0,j[OD],1,:])

        y *= np.exp(np.abs(v1.real) - v2)[None,:]
        y[n==0,:] = np.NaN   # Ko_0() invalid
        return np.squeeze(y)
Ejemplo n.º 7
0
def convolve2d_gauss(fn, r, sig, nstep=200):
    """Evaluate the convolution f'(r) = f(r) * g(r) where f(r) is
    azimuthally symmetric function in two dimensions and g is a
    2D gaussian with standard deviation s given by:

    g(r) = 1/(2*pi*s^2) Exp[-r^2/(2*s^2)]

    Parameters
    ----------

    fn : function
      Input function that takes a single radial coordinate parameter.

    r :  `~numpy.ndarray`
      Array of points at which the convolution is to be evaluated.

    sig : float
      Width parameter of the gaussian.

    nstep : int
      Number of sampling point for numeric integration.

    """
    r = np.array(r, ndmin=1)
    sig = np.array(sig, ndmin=1)

    rmin = r - 10 * sig
    rmax = r + 10 * sig
    rmin[rmin < 0] = 0
    delta = (rmax - rmin) / nstep

    redge = (rmin[:, np.newaxis] +
             delta[:, np.newaxis] *
             np.linspace(0, nstep, nstep + 1)[np.newaxis, :])

    rp = 0.5 * (redge[:, 1:] + redge[:, :-1])
    dr = redge[:, 1:] - redge[:, :-1]
    fnv = fn(rp)

    r = r.reshape(r.shape + (1,))
    saxis = 1

    sig2 = sig * sig
    x = r * rp / (sig2)

    if 'je_fn' not in convolve2d_gauss.__dict__:
        t = 10 ** np.linspace(-8, 8, 1000)
        t = np.insert(t, 0, [0])
        je = special.ive(0, t)
        convolve2d_gauss.je_fn = UnivariateSpline(t, je, k=2, s=0)

    je = convolve2d_gauss.je_fn(x.flat).reshape(x.shape)
    #    je2 = special.ive(0,x)
    v = (rp * fnv / (sig2) * je * np.exp(x - (r * r + rp * rp) /
                                         (2 * sig2)) * dr)
    s = np.sum(v, axis=saxis)

    return s
Ejemplo n.º 8
0
def Fm(x, m, r1, r2, semi = True):
    ra = r1
    rb = r2
    if (r2 < r1):
       rb = r1
       ra = r2
    if m > 20 and semi:
       
       za = x * ra
       zb = x * rb
       if (za < 1e-5) and (zb < 1e-5): 
           e = -1 + m * math.log(ra/rb * (m + 1.0)/m) -0.5 *math.log((m+1.0)*m) - math.log(rb/2/(m + 1.0))
           return -math.exp(2*e)/4.0
           #return 0.0
       sqa1 = math.sqrt(m**2 + za**2)
       sqa2 = math.sqrt((m + 1)**2 + za**2)
       sqb1 = math.sqrt(m**2 + zb**2)
       sqb2 = math.sqrt((m + 1)**2 + zb**2)
       
       li1 = sqa1 + m * math.log(za/(m + sqa1)) - 0.5 * math.log(sqa1) 
       li2 = sqa2 + (m + 1) * math.log(za/(m + 1 + sqa2)) - 0.5 * math.log(sqa2) 
       lk1 = -sqb1 - m * math.log(zb/(m + sqb1)) - 0.5 * math.log(sqb1)
       lk2 = -sqb2 - (m + 1)* math.log(zb/(m + 1 + sqb2)) - 0.5 * math.log(sqb2)
       L =  2.0*(li1 + lk1)
       Li = 2.0*(li2 - li1)
       Lk = 2.0*(lk2 - lk1)
       return math.exp(L) * x * x * (math.exp(Li) - 1) * (math.exp(Lk) - 1)/4
       #return math.exp(L) * (math.exp(Li) - 1) * (math.exp(Lk) - 1)/4
       
    im1 = special.ive(m, x * ra)
    km1 = special.kve(m, x * rb)
    
    im2 = special.ive(m + 1, x * ra)
    km2 = special.kve(m + 1, x * rb)
    
    e = math.exp(x * (ra - rb))
    
    q1 = im1 * km1 * im1 * km1 
    q2 = im2 * km2 * im2 * km2 
    q3 = im1 * km2 * im1 * km2
    #q4 = q3
    q4 = im2 * km1 * im2 * km1
    #q = x * (im1 * km1 - im2 * km2) * e
    #print r1, r2, m, e, q
    return x * x * (im1 * im1 - im2 * im2) * (km2 * km2 - km1 * km1) * e * e
Ejemplo n.º 9
0
def make_Ive_array(kperp,nb,Tpar_Tperp):
    global ive_arr
    ive_arr = np.empty((2*nb+2),dtype=np.float64)
    b=0.5*kperp**2/Tpar_Tperp
    
    js=np.arange(0,2*nb+2)
    j_shift=js-nb-1
    for j in js:
        ive_arr[j] = ive(j_shift[j],b)
Ejemplo n.º 10
0
def convolve2d_gauss(fn,r,sig,rmax,nstep=200):
    """Evaluate the convolution f'(r) = f(r) * g(r) where f(r) is
    azimuthally symmetric function in two dimensions and g is a
    gaussian given by:

    g(r) = 1/(2*pi*s^2) Exp[-r^2/(2*s^2)]

    Parameters
    ----------

    fn : Input function that takes a single radial coordinate parameter.

    r :  Array of points at which the convolution is to be evaluated.

    sig : Width parameter of the gaussian.

    """
    r = np.array(r,ndmin=1,copy=True)
    sig = np.array(sig,ndmin=1,copy=True)

    rp = edge_to_center(np.linspace(0,rmax,nstep+1))
    dr = rmax/float(nstep)
    fnrp = fn(rp)

    if sig.shape[0] > 1:        
        rp = rp.reshape((1,1,nstep))
        fnrp = fnrp.reshape((1,1,nstep))
        r = r.reshape((1,r.shape[0],1))
        sig = sig.reshape(sig.shape + (1,1))
        saxis = 2
    else:
        rp = rp.reshape(1,nstep)
        fnrp = fnrp.reshape(1,nstep)
        r = r.reshape(r.shape + (1,))
        saxis = 1

    sig2 = sig*sig
    x = r*rp/(sig2)
    je = spfn.ive(0,x)

    s = np.sum(rp*fnrp/(sig2)*
               np.exp(np.log(je)+x-(r*r+rp*rp)/(2*sig2)),axis=saxis)*dr

    return s
Ejemplo n.º 11
0
  def _verifyPdfWithNumpy(self, vmf, atol=1e-4):
    """Verifies log_prob evaluations with numpy/scipy.

    Both uniform random points and sampled points are evaluated.

    Args:
      vmf: A `tfp.distributions.VonMisesFisher` instance.
      atol: Absolute difference tolerable.
    """
    dim = tf.compat.dimension_value(vmf.event_shape[-1])
    nsamples = 10
    # Sample some random points uniformly over the hypersphere using numpy.
    sample_shape = [nsamples] + tensorshape_util.as_list(
        vmf.batch_shape) + [dim]
    uniforms = np.random.randn(*sample_shape)
    uniforms /= np.linalg.norm(uniforms, axis=-1, keepdims=True)
    uniforms = uniforms.astype(dtype_util.as_numpy_dtype(vmf.dtype))
    # Concatenate in some sampled points from the distribution under test.
    vmf_samples = vmf.sample(
        sample_shape=[nsamples], seed=tfp_test_util.test_seed())
    samples = tf.concat([uniforms, vmf_samples], axis=0)
    samples = tf.debugging.check_numerics(samples, 'samples')
    samples = self.evaluate(samples)
    log_prob = vmf.log_prob(samples)
    log_prob = tf.debugging.check_numerics(log_prob, 'log_prob')
    conc = self.evaluate(vmf.concentration)
    mean_dir = self.evaluate(vmf.mean_direction)
    log_true_sphere_surface_area = (
        np.log(2) + (dim / 2) * np.log(np.pi) - sp_special.gammaln(dim / 2))
    expected = (
        conc * np.sum(samples * mean_dir, axis=-1) +
        np.where(conc > 0,
                 (dim / 2 - 1) * np.log(conc) -
                 (dim / 2) * np.log(2 * np.pi) -
                 np.log(sp_special.ive(dim / 2 - 1, conc)) -
                 np.abs(conc),
                 -log_true_sphere_surface_area))
    self.assertAllClose(expected, self.evaluate(log_prob),
                        atol=atol)
Ejemplo n.º 12
0
    def dKo(self, n, z):
        """odd second-kind radial Mathieu function derivative (DKo) 
        (analogous to K Bessel functions, called Gek in McLachlan p248), 
        for scalar or vector orders or argument

        n: order (scalar or vector)
        z: radial argument (scalar or vector)"""

        from scipy.special import kve, ive
        n, z, sqrtq, enz, epz, v1, v2, M, EV, OD = self._RadDerivFuncSetup(
            n, z)
        dy = np.empty((n.shape[0], z.shape[0]), dtype=complex)

        ord = self.ord[0:M + 2]
        I = ive(ord[0:M + 2, None], v1[None, :])[:, None, :]
        K = kve(ord[0:M + 2, None], v2[None, :])[:, None, :]
        dI = self._deriv(v1, I[0:M + 2, 0, :], 0)[:, None, :]
        dK = self._deriv(v2, K[0:M + 2, 0, :], 1)[:, None, :]
        j = (n[:] - 1) // 2

        dy[EV, :] = (sqrtq / self.B[0, j[EV], 0, :] *
                     np.sum(self.B[0:M, j[EV], 0, :] *
                            (epz * I[0:M, :, :] * dK[2:M + 2, :, :] -
                             enz * dI[0:M, :, :] * K[2:M + 2, :, :] -
                             (epz * I[2:M + 2, :, :] * dK[0:M, :, :] -
                              enz * dI[2:M + 2, :, :] * K[0:M, :, :])),
                            axis=0))

        dy[OD, :] = (sqrtq / self.A[0, j[OD], 1, :] * np.sum(
            self.A[0:M, j[OD], 1, :] *
            (epz * I[0:M, :, :] * dK[1:M + 1, :, :] - enz * dI[0:M, :, :] *
             K[1:M + 1, :, :] + epz * I[1:M + 1, :, :] * dK[0:M, :, :] -
             enz * dI[1:M + 1, :, :] * K[0:M, :, :]),
            axis=0))

        dy *= np.exp(np.abs(v1.real) - v2)[None, :]
        dy[n == 0, :] = np.NaN  # dKo_0() invalid
        return np.squeeze(dy)
Ejemplo n.º 13
0
    def _verifyPdfWithNumpy(self, vmf, atol=1e-4):
        """Verifies log_prob evaluations with numpy/scipy.

    Both uniform random points and sampled points are evaluated.

    Args:
      vmf: A `tfp.distributions.VonMisesFisher` instance.
      atol: Absolute difference tolerable.
    """
        dim = vmf.event_shape[-1].value
        nsamples = 10
        # Sample some random points uniformly over the hypersphere using numpy.
        sample_shape = [nsamples] + vmf.batch_shape.as_list() + [dim]
        uniforms = np.random.randn(*sample_shape)
        uniforms /= np.linalg.norm(uniforms, axis=-1, keepdims=True)
        uniforms = uniforms.astype(vmf.dtype.as_numpy_dtype)
        # Concatenate in some sampled points from the distribution under test.
        samples = tf.concat(
            [uniforms, vmf.sample(sample_shape=[nsamples])], axis=0)
        samples = tf.check_numerics(samples, 'samples')
        samples = self.evaluate(samples)
        log_prob = vmf.log_prob(samples)
        log_prob = tf.check_numerics(log_prob, 'log_prob')
        try:
            from scipy.special import gammaln  # pylint: disable=g-import-not-at-top
            from scipy.special import ive  # pylint: disable=g-import-not-at-top
        except ImportError:
            tf.logging.warn('Unable to use scipy in tests')
            return
        conc = self.evaluate(vmf.concentration)
        mean_dir = self.evaluate(vmf.mean_direction)
        log_true_sphere_surface_area = (np.log(2) + (dim / 2) * np.log(np.pi) -
                                        gammaln(dim / 2))
        expected = (conc * np.sum(samples * mean_dir, axis=-1) + np.where(
            conc > 0, (dim / 2 - 1) * np.log(conc) -
            (dim / 2) * np.log(2 * np.pi) - np.log(ive(dim / 2 - 1, conc)) -
            np.abs(conc), -log_true_sphere_surface_area))
        self.assertAllClose(expected, self.evaluate(log_prob), atol=atol)
Ejemplo n.º 14
0
def vmf_tic(X):
    X = np.array(X)
    ll = log_likelihood(X)

    if np.isnan(ll):
        return np.nan

    N, D = X.shape
    mu = fit_mean_direction(X)
    kappa = fit_concentration(X)

    total = np.zeros(D)
    hess_diagonal = np.zeros(D - 1)
    for i, x in enumerate(X):
        grad_i = log_vMF_gradient(mu, kappa, x)
        total += grad_i**2

        elementwise = x * mu
        cdots = np.cumsum(elementwise[::-1])[::-1]

        hess_diagonal += -cdots[:-1] * kappa
    total /= N
    hess_diagonal /= N

    v = (D / 2 - 1)
    num = ive(v + 1, kappa) * (ive(v - 1, kappa) + ive(v + 1, kappa)) - ive(
        v, kappa) * (ive(v, kappa) + ive(v + 2, kappa))  # noqa
    denom = 2 * ive(v, kappa)**2

    k_diag = num / denom

    fisher_diagonal = -np.concatenate([[k_diag], hess_diagonal])

    correction = np.sum(total / fisher_diagonal)

    return -(ll - correction)
Ejemplo n.º 15
0
def magnetic_field_vertical_magnetic_dipole(t,
                                            xy,
                                            sigma=1.0,
                                            mu=mu_0,
                                            moment=1.0):
    """Magnetic field due to step off vertical dipole at the surface

    Parameters
    ----------
    t : (n_t) numpy.ndarray
        times (s)
    xy : (n_locs, 2) numpy.ndarray
        surface field locations (m)
    sigma : float, optional
        conductivity
    mu : float, optional
        magnetic permeability
    moment : float, optional
        moment of the dipole

    Returns
    -------
    h : (n_t, n_locs, 3) numpy.ndarray
        The magnetic field at the observation locations and times.

    Notes
    -----
    Matches the negative of equation 4.69a of Ward and Hohmann 1988, for the vertical
    component (due to the difference in coordinate sign conventionn used here).

    .. math::
        h_z = -\\frac{m}{4 \\pi \\rho^2} \\left[
        \\left(\\frac{9}{2 \\theta^2 \\rho^2} - 1\\right)\\mathrm{erf}(\\theta \\rho)
        - \\frac{1}{\\sqrt{\\pi}}\\left(\\frac{9}{\\theta \\rho + 4 \\theta \\rho} \\right)
        e^{-\\theta^2\\rho^2}
        \\right]

    Also matches equation 4.72 for the horizontal components, which is again negative due
    to our coordinate convention.

    .. math::
        h_\\rho = \\frac{m \\theta^2}{2\\pi\\rho}
        e^{-\\theta^2\\rho^2/2}\\left[I_1\\left(\\frac{\\theta^2\\rho^2}{2}\\right)
         - I_2\\left(\\frac{\\theta^2\\rho^2}{2}\\right)\\right]

    Examples
    --------
    Reproducing part of Figure 4.4 and 4.5 from Ward and Hohmann 1988

    >>> import numpy as np
    >>> import matplotlib.pyplot as plt
    >>> from geoana.em.tdem import magnetic_field_vertical_magnetic_dipole

    Calculate the field at the time given, and 100 m along the x-axis,

    >>> times = np.logspace(-8, 0, 200)
    >>> xy = np.array([[100, 0, 0]])
    >>> h = magnetic_field_vertical_magnetic_dipole(times, xy, sigma=1E-2)

    Match the vertical magnetic field plot

    >>> plt.loglog(times*1E3, h[:,0, 2], c='C0', label='$h_z$')
    >>> plt.loglog(times*1E3, -h[:,0, 2], '--', c='C0')
    >>> plt.loglog(times*1E3, h[:,0, 0], c='C1', label='$h_x$')
    >>> plt.loglog(times*1E3, -h[:,0, 0], '--', c='C1')
    >>> plt.xlabel('time (ms)')
    >>> plt.ylabel('h (A/m)')
    >>> plt.legend()
    >>> plt.show()
    """
    r = np.linalg.norm(xy[:, :2], axis=-1)
    x = xy[:, 0]
    y = xy[:, 1]
    thr = theta(t, sigma, mu=mu)[:, None] * r  #will be positive...

    h_z = 1.0 / r**3 * ((9 / (2 * thr**2) - 1) * erf(thr) -
                        (9 / thr + 4 * thr) / np.sqrt(np.pi) * np.exp(-thr**2))
    # positive here because z+ up

    # iv(1, arg) - iv(2, arg)
    # ive(1, arg) * np.exp(abs(arg)) - ive(2, arg) * np.exp(abs(arg))
    # (ive(1, arg) - ive(2, arg))*np.exp(abs(arg))
    h_r = 2 * thr**2 / r**3 * (ive(1, thr**2 / 2) - ive(2, thr**2 / 2))
    # thetar is always positive so this above simplifies (more numerically stable)

    angle = np.arctan2(y, x)
    h_x = np.cos(angle) * h_r
    h_y = np.sin(angle) * h_r

    return moment / (4 * np.pi) * np.stack((h_x, h_y, h_z), axis=-1)
Ejemplo n.º 16
0
def halfspace(off,
              angle,
              zsrc,
              zrec,
              etaH,
              etaV,
              freqtime,
              ab,
              signal,
              solution='dhs'):
    """Return frequency- or time-space domain VTI half-space solution.

    Calculates the frequency- or time-space domain electromagnetic response for
    a half-space below air using the diffusive approximation, as given in
    [Slob_et_al_2010]_, where the electric source is located at [0, 0, zsrc],
    and the electric receiver at [xco, yco, zrec].

    It can also be used to calculate the fullspace solution or the separate
    fields: direct field, reflected field, and airwave; always using the
    diffusive approximation. See `solution`-parameter.

    This routine is not strictly part of `empymod` and not used by it.
    However, it can be useful to compare the code to this analytical solution.

    This function is called from one of the modelling routines in :mod:`model`.
    Consult these modelling routines for a description of the input and
    solution parameters.

    """
    xco = np.cos(angle) * off
    yco = np.sin(angle) * off
    res = np.real(1 / etaH[0, 0])
    aniso = 1 / np.sqrt(np.real(etaV[0, 0]) * res)

    # Define freq/time and dtype depending on signal.
    if signal is None:
        freq = freqtime
        dtype = complex
    else:
        time = freqtime
        if signal == -1:  # Calculate DC
            time = np.r_[time[:, 0], 1e4][:, None]
            freqtime = time
        dtype = float

    # Other defined parameters
    rh = np.sqrt(xco**2 + yco**2)  # Horizontal distance in space
    hp = np.abs(zrec + zsrc)  # Physical vertical distance
    hm = np.abs(zrec - zsrc)
    hsp = hp * aniso  # Scaled vertical distance
    hsm = hm * aniso
    rp = np.sqrt(xco**2 + yco**2 + hp**2)  # Physical distance
    rm = np.sqrt(xco**2 + yco**2 + hm**2)
    rsp = np.sqrt(xco**2 + yco**2 + hsp**2)  # Scaled distance
    rsm = np.sqrt(xco**2 + yco**2 + hsm**2)
    #
    tp = mu_0 * rp**2 / (res * 4)  # Diffusion time
    tm = mu_0 * rm**2 / (res * 4)
    tsp = mu_0 * rsp**2 / (res * aniso**2 * 4)  # Scaled diffusion time
    tsm = mu_0 * rsm**2 / (res * aniso**2 * 4)
    #
    if signal is None:
        s = 2j * np.pi * freq  # Laplace parameter

    # delta-fct delta_\alpha\beta
    if ab in [11, 22, 33]:
        delta = 1
    else:
        delta = 0

    # src-rec type
    if ab == 33:
        srcrec = 3
    elif ab in [13, 23, 31, 32]:
        srcrec = 2
    else:
        srcrec = 1

    # Define alpha/beta; swap if necessary
    x = xco
    y = yco
    if ab == 11:
        y = x
    elif ab in [22, 23, 32]:
        x = y
    elif ab == 21:
        x, y = y, x

    # Define rev for 3\alpha->\alpha3 reciprocity
    if ab in [13, 23]:
        rev = -1
    elif ab in [31, 32]:
        rev = 1

    # Exponential diffusion functions for m=0,1,2

    if signal is None:  # Frequency-domain
        f0p = np.exp(-2 * np.sqrt(s * tp))
        f0m = np.exp(-2 * np.sqrt(s * tm))
        fs0p = np.exp(-2 * np.sqrt(s * tsp))
        fs0m = np.exp(-2 * np.sqrt(s * tsm))

        f1p = np.sqrt(s) * f0p
        f1m = np.sqrt(s) * f0m
        fs1p = np.sqrt(s) * fs0p
        fs1m = np.sqrt(s) * fs0m

        f2p = s * f0p
        f2m = s * f0m
        fs2p = s * fs0p
        fs2m = s * fs0m

    elif np.abs(signal) == 1:  # Time-domain step response
        # Replace F(m) with F(m-2)
        f0p = erfc(np.sqrt(tp / time))
        f0m = erfc(np.sqrt(tm / time))
        fs0p = erfc(np.sqrt(tsp / time))
        fs0m = erfc(np.sqrt(tsm / time))

        f1p = np.exp(-tp / time) / np.sqrt(np.pi * time)
        f1m = np.exp(-tm / time) / np.sqrt(np.pi * time)
        fs1p = np.exp(-tsp / time) / np.sqrt(np.pi * time)
        fs1m = np.exp(-tsm / time) / np.sqrt(np.pi * time)

        f2p = f1p * np.sqrt(tp) / time
        f2m = f1m * np.sqrt(tm) / time
        fs2p = fs1p * np.sqrt(tsp) / time
        fs2m = fs1m * np.sqrt(tsm) / time

    else:  # Time-domain impulse response
        f0p = np.sqrt(tp / (np.pi * time**3)) * np.exp(-tp / time)
        f0m = np.sqrt(tm / (np.pi * time**3)) * np.exp(-tm / time)
        fs0p = np.sqrt(tsp / (np.pi * time**3)) * np.exp(-tsp / time)
        fs0m = np.sqrt(tsm / (np.pi * time**3)) * np.exp(-tsm / time)

        f1p = (tp / time - 0.5) / np.sqrt(tp) * f0p
        f1m = (tm / time - 0.5) / np.sqrt(tm) * f0m
        fs1p = (tsp / time - 0.5) / np.sqrt(tsp) * fs0p
        fs1m = (tsm / time - 0.5) / np.sqrt(tsm) * fs0m

        f2p = (tp / time - 1.5) / time * f0p
        f2m = (tm / time - 1.5) / time * f0m
        fs2p = (tsp / time - 1.5) / time * fs0p
        fs2m = (tsm / time - 1.5) / time * fs0m

    # Pre-allocate arrays
    gs0m = np.zeros(np.shape(x), dtype=dtype)
    gs0p = np.zeros(np.shape(x), dtype=dtype)
    gs1m = np.zeros(np.shape(x), dtype=dtype)
    gs1p = np.zeros(np.shape(x), dtype=dtype)
    gs2m = np.zeros(np.shape(x), dtype=dtype)
    gs2p = np.zeros(np.shape(x), dtype=dtype)
    g0p = np.zeros(np.shape(x), dtype=dtype)
    g1m = np.zeros(np.shape(x), dtype=dtype)
    g1p = np.zeros(np.shape(x), dtype=dtype)
    g2m = np.zeros(np.shape(x), dtype=dtype)
    g2p = np.zeros(np.shape(x), dtype=dtype)
    air = np.zeros(np.shape(f0p), dtype=dtype)

    if srcrec == 1:  # 1. {alpha, beta}
        # Get indices for singularities
        izr = rh == 0  # index where rh = 0
        iir = np.invert(izr)  # invert of izr
        izh = hm == 0  # index where hm = 0
        iih = np.invert(izh)  # invert of izh

        # fab
        fab = rh**2 * delta - x * y

        # TM-mode coefficients
        gs0p = res * aniso * (3 * x * y - rsp**2 * delta) / (4 * np.pi *
                                                             rsp**5)
        gs0m = res * aniso * (3 * x * y - rsm**2 * delta) / (4 * np.pi *
                                                             rsm**5)
        gs1p[iir] = (
            ((3 * x[iir] * y[iir] - rsp[iir]**2 * delta) / rsp[iir]**4 -
             (x[iir] * y[iir] - fab[iir]) / rh[iir]**4) * np.sqrt(mu_0 * res) /
            (4 * np.pi))
        gs1m[iir] = (
            ((3 * x[iir] * y[iir] - rsm[iir]**2 * delta) / rsm[iir]**4 -
             (x[iir] * y[iir] - fab[iir]) / rh[iir]**4) * np.sqrt(mu_0 * res) /
            (4 * np.pi))
        gs2p[iir] = ((mu_0 * x[iir] * y[iir]) /
                     (4 * np.pi * aniso * rsp[iir]) *
                     (1 / rsp[iir]**2 - 1 / rh[iir]**2))
        gs2m[iir] = ((mu_0 * x[iir] * y[iir]) /
                     (4 * np.pi * aniso * rsm[iir]) *
                     (1 / rsm[iir]**2 - 1 / rh[iir]**2))

        # TM-mode for numerical singularities rh=0 (hm!=0)
        gs1p[izr * iih] = -np.sqrt(mu_0 * res) * delta / (4 * np.pi * hsp**2)
        gs1m[izr * iih] = -np.sqrt(mu_0 * res) * delta / (4 * np.pi * hsm**2)
        gs2p[izr * iih] = -mu_0 * delta / (8 * np.pi * aniso * hsp)
        gs2m[izr * iih] = -mu_0 * delta / (8 * np.pi * aniso * hsm)

        # TE-mode coefficients
        g0p = res * (3 * fab - rp**2 * delta) / (2 * np.pi * rp**5)
        g1m[iir] = (np.sqrt(mu_0 * res) * (x[iir] * y[iir] - fab[iir]) /
                    (4 * np.pi * rh[iir]**4))
        g1p[iir] = (g1m[iir] + np.sqrt(mu_0 * res) *
                    (3 * fab[iir] - rp[iir]**2 * delta) /
                    (2 * np.pi * rp[iir]**4))
        g2p[iir] = mu_0 * fab[iir] / (4 * np.pi * rp[iir]) * (2 / rp[iir]**2 -
                                                              1 / rh[iir]**2)
        g2m[iir] = -mu_0 * fab[iir] / (4 * np.pi * rh[iir]**2 * rm[iir])

        # TE-mode for numerical singularities rh=0 (hm!=0)
        g1m[izr * iih] = np.zeros(np.shape(g1m[izr * iih]), dtype=dtype)
        g1p[izr * iih] = -np.sqrt(mu_0 * res) * delta / (2 * np.pi * hp**2)
        g2m[izr * iih] = mu_0 * delta / (8 * np.pi * hm)
        g2p[izr * iih] = mu_0 * delta / (8 * np.pi * hp)

        # Bessel functions for airwave
        def BI(gamH, hp, nr, xim):
            """Return BI_nr."""
            return np.exp(-np.real(gamH) * hp) * ive(nr, xim)

        def BK(xip, nr):
            """Return BK_nr."""
            return np.exp(-1j * np.imag(xip)) * kve(nr, xip)

        # Airwave calculation
        def airwave(s, hp, rp, res, fab, delta):
            """Return airwave."""
            # Parameters
            zeta = s * mu_0
            gamH = np.sqrt(zeta / res)
            xip = gamH * (rp + hp) / 2
            xim = gamH * (rp - hp) / 2

            # Bessel functions
            BI0 = BI(gamH, hp, 0, xim)
            BI1 = BI(gamH, hp, 1, xim)
            BI2 = BI(gamH, hp, 2, xim)
            BK0 = BK(xip, 0)
            BK1 = BK(xip, 1)

            # Calculation
            P1 = (s * mu_0)**(3 / 2) * fab * hp / (4 * np.sqrt(res))
            P2 = 4 * BI1 * BK0 - (3 * BI0 - 4 * np.sqrt(res) * BI1 /
                                  (np.sqrt(s * mu_0) * (rp + hp)) + BI2) * BK1
            P3 = 3 * fab / rp**2 - delta
            P4 = (s * mu_0 * hp * rp * (BI0 * BK0 - BI1 * BK1) +
                  np.sqrt(res * s * mu_0) * BI0 * BK1 * (rp + hp) +
                  np.sqrt(res * s * mu_0) * BI1 * BK0 * (rp - hp))

            return (P1 * P2 - P3 * P4) / (4 * np.pi * rp**3)

        # Airwave depending on signal
        if signal is None:  # Frequency-domain
            air = airwave(s, hp, rp, res, fab, delta)

        elif np.abs(signal) == 1:  # Time-domain step response
            # Solution for step-response air-wave is not analytical, but uses
            # the Gaver-Stehfest method.
            K = 16

            # Coefficients Dk
            fn = np.vectorize(np.math.factorial)

            def coeff_dk(k, K):
                """Return coefficients Dk for k, K."""
                n = np.arange(int((k + 1) / 2),
                              np.min([k, K / 2]) + .5,
                              1,
                              dtype=int)
                Dk = n**(K / 2) * fn(2 * n)
                Dk /= fn(n) * fn(n - 1) * fn(k - n) * fn(2 * n -
                                                         k) * fn(K / 2 - n)
                return Dk.sum() * (-1)**(k + K / 2)

            for k in range(1, K + 1):
                s = k * np.log(2) / time
                cair = airwave(s, hp, rp, res, fab, delta)
                air += coeff_dk(k, K) * cair.real / k

        else:  # Time-domain impulse response
            thp = mu_0 * hp**2 / (4 * res)
            trh = mu_0 * rh**2 / (8 * res)
            P1 = (mu_0**2 * hp * np.exp(-thp / time)) / (res * 32 * np.pi *
                                                         time**3)
            P2 = 2 * (delta - (x * y) / rh**2) * ive(1, trh / time)
            P3 = mu_0 / (2 * res * time) * (rh**2 * delta - x * y) - delta
            P4 = ive(0, trh / time) - ive(1, trh / time)

            air = P1 * (P2 - P3 * P4)

    elif srcrec == 2:  # 2. {3, alpha}, {alpha, 3}
        # TM-mode
        gs0m = 3 * x * res * aniso**3 * (zrec - zsrc) / (4 * np.pi * rsm**5)
        gs0p = rev * 3 * x * res * aniso**3 * hp / (4 * np.pi * rsp**5)
        gs1m = (np.sqrt(mu_0 * res) * 3 * aniso**2 * x * (zrec - zsrc) /
                (4 * np.pi * rsm**4))
        gs1p = rev * np.sqrt(
            mu_0 * res) * 3 * aniso**2 * x * hp / (4 * np.pi * rsp**4)
        gs2m = mu_0 * x * aniso * (zrec - zsrc) / (4 * np.pi * rsm**3)
        gs2p = rev * mu_0 * x * aniso * hp / (4 * np.pi * rsp**3)

    elif srcrec == 3:  # 3. {3, 3}
        # TM-mode
        gs0m = res * aniso**3 * (3 * hsm**2 - rsm**2) / (4 * np.pi * rsm**5)
        gs0p = -res * aniso**3 * (3 * hsp**2 - rsp**2) / (4 * np.pi * rsp**5)
        gs1m = np.sqrt(mu_0 * res) * aniso**2 * (3 * hsm**2 -
                                                 rsm**2) / (4 * np.pi * rsm**4)
        gs1p = -np.sqrt(mu_0 * res) * aniso**2 * (3 * hsp**2 - rsp**2) / (
            4 * np.pi * rsp**4)
        gs2m = mu_0 * aniso * (hsm**2 - rsm**2) / (4 * np.pi * rsm**3)
        gs2p = -mu_0 * aniso * (hsp**2 - rsp**2) / (4 * np.pi * rsp**3)

    # Direct field
    direct_TM = gs0m * fs0m + gs1m * fs1m + gs2m * fs2m
    direct_TE = g1m * f1m + g2m * f2m
    direct = direct_TM + direct_TE

    # Reflection
    reflect_TM = gs0p * fs0p + gs1p * fs1p + gs2p * fs2p
    reflect_TE = g0p * f0p + g1p * f1p + g2p * f2p
    reflect = reflect_TM + reflect_TE

    # If switch-on, subtract switch-on from DC value
    if signal == -1:
        direct_TM = direct_TM[-1] - direct_TM[:-1]
        direct_TE = direct_TE[-1] - direct_TE[:-1]
        direct = direct[-1] - direct[:-1]

        reflect_TM = reflect_TM[-1] - reflect_TM[:-1]
        reflect_TE = reflect_TE[-1] - reflect_TE[:-1]
        reflect = reflect[-1] - reflect[:-1]

        air = air[-1] - air[:-1]

    # Return, depending on 'solution'
    if solution == 'dfs':
        return direct
    elif solution == 'dsplit':
        return direct, reflect, air
    elif solution == 'dtetm':
        return direct_TE, direct_TM, reflect_TE, reflect_TM, air
    else:
        return direct + reflect + air
Ejemplo n.º 17
0
 def analytic_solution_helper(x, tau, x_0):
     sqrt_tau = np.sqrt(tau)
     result = float((1 - tau) * 1 / (x * np.sqrt(tau)) *
                    special.ive(1, 2 * x / x_0 * sqrt_tau) *
                    np.exp(-(1 + tau - 2 * sqrt_tau) * x / x_0))
     return result
Ejemplo n.º 18
0
def _vonmises_pdf(x, mu, kappa):
    """Calculate vonmises_pdf."""
    if kappa <= 0:
        raise ValueError("Argument 'kappa' must be positive.")
    pdf = 1 / (2 * np.pi * ive(0, kappa)) * np.exp(np.cos(x - mu) - 1)**kappa
    return pdf
Ejemplo n.º 19
0
 def BI(gamH, hp, nr, xim):
     r"""Return BI_nr."""
     return np.exp(-np.real(gamH) * hp) * special.ive(nr, xim)
Ejemplo n.º 20
0
def convolveMRA(field, sigma):
    if sigma == 0:
        return field.data
    n = int(len(field.dimensions[-1].data) / 2)
    kernel = ive(numpy.arange(-n, n), sigma)
    return convolve(field.data, kernel, mode='same')
Ejemplo n.º 21
0
 def VerifyBesselIvRatio(self, v, z, rtol):
     bessel_iv_ratio, v, z = self.evaluate(
         [tfp.math.bessel_iv_ratio(v, z), v, z])
     # Use ive to avoid nans.
     scipy_ratio = scipy_special.ive(v, z) / scipy_special.ive(v - 1., z)
     self.assertAllClose(bessel_iv_ratio, scipy_ratio, rtol=rtol)
    def compute_params(self):
        """ Initialize  """
        check = 1
        inc = 0.00000001
        c_atzero = check + 1
        r0 = self.rmin()
        r_min = self.rmin()
        r1 = self.r_1()
        V = 1
        nv = self.N / V

        e = 0
        f = 0
        """ Iterate until the condition is satisfied """
        while (check > 0.0001):
            e = e + 1
            f = f + 1
            check, P, c_atzero = self.PSD(r0, r1)
            grad_1 = nv * self.p_0 * ((6.28 * r0)**(0.5 * self.d)) * (
                (self.d / r0) * sc.jve((0.5 * self.d), r0) + sc.ive(
                    (0.5 * self.d) - 1, r0) - sc.jve((0.5 * self.d) + 1, r0))
            grad_2 = nv * (1 - self.p_0) * ((6.28 * r1)**(0.5 * self.d)) * (
                (self.d / r1) * sc.jve((0.5 * self.d), r1) + sc.ive(
                    (0.5 * self.d) - 1, r1) - sc.jve((0.5 * self.d) + 1, r1))

            grad_norm = (check / r_min) + (r0 * grad_1 / r_min)

            r0 = r0 + inc * grad_norm
            r1 = r1 + inc * (grad_2 * r0 / r_min)

            if self.verbose == 1:
                if f == 1000:
                    print('iter =', e, '  check=', check)
                    f = 0

        r0 = r0 - inc * grad_1
        r1 = r1 - inc * grad_2

        check, P, c_atzero = self.PSD(r0, r1)
        """ Summary and figures """
        if self.summary == 1:

            print('---------------------------------------------------')
            print('N = ', self.N)
            print('d = ', self.d)
            print('r0 = ', r0)
            print('r1 = ', r1)
            print('p0 = ', self.p_0)
            print('delta = ', r1 - r0)
            print('rmin_step =', r_min)
            print('gain = ', r0 / r_min)
            print('---------------------------------------------------')

            plt.figure()
            plt.plot(P, label='PSD')
            ze = np.zeros((self.bins, 1))
            plt.plot(ze, ':r')
            plt.title('PSD : N=' + str(self.N) + '  d=' + str(self.d))
            plt.legend()
            #plt.show()

        return P, r0, r1, self.p_0, r_min
Ejemplo n.º 23
0
def MRicdf(Ic, Is, interpmethod='cubic'):
    """
    Compute an interpolation function to give the inverse CDF of the
    modified Rician with a given Ic and Is.  

    Arguments:
    Ic: float, parameter for M-R
    Is: float > 0, parameter for M-R

    Optional argument:
    interpmethod: keyword passed as 'kind' to interpolate.interp1d

    Returns: 
    interpolation function f for the inverse CDF of the M-R

    """

    if Is <= 0 or Ic < 0:
        raise ValueError(
            "Cannot compute modified Rician CDF with Is<=0 or Ic<0.")

    # Compute mean and variance of modified Rician, compute CDF by
    # going 15 sigma to either side (but starting no lower than zero).
    # Use 1000 points, or about 30 points/sigma.

    mu = Ic + Is
    sig = np.sqrt(Is**2 + 2 * Ic * Is)
    I1 = max(0, mu - 15 * sig)
    I2 = mu + 15 * sig
    I = np.linspace(I1, I2, 1000)

    # Grid spacing.  Set I to be offset by dI/2 to give the
    # trapezoidal rule by direct summation.

    dI = I[1] - I[0]
    I += dI / 2

    # Modified Rician PDF, and CDF by direct summation of intensities
    # centered on the bins to be integrated.  Enforce normalization at
    # the end since our integration scheme is off by a part in 1e-6 or
    # something.

    #p_I = 1./Is*np.exp(-(Ic + I)/Is)*special.iv(0, 2*np.sqrt(I*Ic)/Is)
    p_I = 1. / Is * np.exp(
        (2 * np.sqrt(I * Ic) -
         (Ic + I)) / Is) * special.ive(0, 2 * np.sqrt(I * Ic) / Is)

    cdf = np.cumsum(p_I) * dI
    cdf /= cdf[-1]

    # The integral is defined with respect to the bin edges.

    I = np.asarray([0] + list(I + dI / 2))
    cdf = np.asarray([0] + list(cdf))

    # The interpolation scheme doesn't want duplicate values.  Pick
    # the unique ones, and then return a function to compute the
    # inverse of the CDF.

    i = np.unique(cdf, return_index=True)[1]
    return interpolate.interp1d(cdf[i], I[i], kind=interpmethod)
Ejemplo n.º 24
0
    def Mtil(m, epr, mur, bet, nu, b):
        def produto(A, B):
            C = _np.zeros((A.shape[0], B.shape[1], A.shape[2]), dtype=complex)
            for i in range(A.shape[0]):
                for j in range(B.shape[1]):
                    for k in range(A.shape[1]):
                        C[i, j, :] = C[i, j, :] + A[i, k, :] * B[k, j, :]
            return C

        for i in range(
                len(b)):  # lembrando que length(b) = número de camadas - 1
            x = nu[i + 1, :] * b[i]
            y = nu[i, :] * b[i]
            Mt = _np.zeros((4, 4, w.shape[0]), dtype=complex)

            if i < len(b) - 1:
                D = _np.zeros((4, 4, nu.shape[1]), dtype=complex)
                z = nu[i + 1, :] * b[i + 1]
                if not any(z.real < 0):
                    ind = (z.real < 60)

                    A = _scyspe.iv(m, z[ind])
                    B = _scyspe.kv(m, z[ind])
                    C = _scyspe.iv(m, x[ind])
                    E = _scyspe.kv(m, x[ind])

                    D[0, 0, :] = 1
                    D[1, 1, ind] = -B * C / (A * E)
                    D[1, 1, ~ind] = -_np.exp(-2 * (z[~ind] - x[~ind]))
                    D[2, 2, :] = 1
                    D[3, 3, ind] = -B * C / (A * E)
                    D[3, 3, ~ind] = -_np.exp(-2 * (z[~ind] - x[~ind]))

            Mt[0, 0, :] = -nu[i + 1, :]**2 * b[i] / epr[i + 1, :] * (
                epr[i + 1, :] / nu[i + 1, :] *
                (-_scyspe.kve(m - 1, x) / _scyspe.kve(m, x) - m / x) -
                epr[i, :] / nu[i, :] *
                (_scyspe.ive(m - 1, y) / _scyspe.ive(m, y) - m / y))
            Mt[0, 1, :] = -nu[i + 1, :]**2 * b[i] / epr[i + 1, :] * (
                epr[i + 1, :] / nu[i + 1, :] *
                (-_scyspe.kve(m - 1, x) / _scyspe.kve(m, x) - m / x) -
                epr[i, :] / nu[i, :] *
                (-_scyspe.kve(m - 1, y) / _scyspe.kve(m, y) - m / y))
            Mt[1, 0, :] = -nu[i + 1, :]**2 * b[i] / epr[i + 1, :] * (
                epr[i + 1, :] / nu[i + 1, :] *
                (_scyspe.ive(m - 1, x) / _scyspe.ive(m, x) - m / x) -
                epr[i, :] / nu[i, :] *
                (_scyspe.ive(m - 1, y) / _scyspe.ive(m, y) - m / y))
            Mt[1, 1, :] = -nu[i + 1, :]**2 * b[i] / epr[i + 1, :] * (
                epr[i + 1, :] / nu[i + 1, :] *
                (_scyspe.ive(m - 1, x) / _scyspe.ive(m, x) - m / x) -
                epr[i, :] / nu[i, :] *
                (-_scyspe.kve(m - 1, y) / _scyspe.kve(m, y) - m / y))

            Mt[0, 2, :] = (nu[i + 1, :]**2 / nu[i, :]**2 -
                           1) * m / (bet * epr[i + 1, :])
            Mt[0, 3, :] = Mt[0, 2, :]
            Mt[1, 2, :] = Mt[0, 2, :]
            Mt[1, 3, :] = Mt[0, 2, :]
            Mt[2, 2, :] = -nu[i + 1, :]**2 * b[i] / mur[i + 1, :] * (
                mur[i + 1, :] / nu[i + 1, :] *
                (-_scyspe.kve(m - 1, x) / _scyspe.kve(m, x) - m / x) -
                mur[i, :] / nu[i, :] *
                (_scyspe.ive(m - 1, y) / _scyspe.ive(m, y) - m / y))
            Mt[2, 3, :] = -nu[i + 1, :]**2 * b[i] / mur[i + 1, :] * (
                mur[i + 1, :] / nu[i + 1, :] *
                (-_scyspe.kve(m - 1, x) / _scyspe.kve(m, x) - m / x) -
                mur[i, :] / nu[i, :] *
                (-_scyspe.kve(m - 1, y) / _scyspe.kve(m, y) - m / y))
            Mt[3, 2, :] = -nu[i + 1, :]**2 * b[i] / mur[i + 1, :] * (
                mur[i + 1, :] / nu[i + 1, :] *
                (_scyspe.ive(m - 1, x) / _scyspe.ive(m, x) - m / x) -
                mur[i, :] / nu[i, :] *
                (_scyspe.ive(m - 1, y) / _scyspe.ive(m, y) - m / y))
            Mt[3, 3, :] = -nu[i + 1, :]**2 * b[i] / mur[i + 1, :] * (
                mur[i + 1, :] / nu[i + 1, :] *
                (_scyspe.ive(m - 1, x) / _scyspe.ive(m, x) - m / x) -
                mur[i, :] / nu[i, :] *
                (-_scyspe.kve(m - 1, y) / _scyspe.kve(m, y) - m / y))
            Mt[2, 0, :] = (nu[i + 1, :]**2 / nu[i, :]**2 -
                           1) * m / (bet * mur[i + 1, :])
            Mt[2, 1, :] = Mt[2, 0, :]
            Mt[3, 0, :] = Mt[2, 0, :]
            Mt[3, 1, :] = Mt[2, 0, :]

            if len(b) == 1:
                M = Mt
            else:
                if (i == 0):
                    M = produto(D, Mt)
                elif i < len(b) - 1:
                    M = produto(D, produto(Mt, M))
                else:
                    M = produto(Mt, M)
        return M
Ejemplo n.º 25
0
def pol(args, p, k, omega):
    logging.basicConfig(level=args.loglevel or logging.INFO)
    logger = logging.getLogger(__name__)

    theta = p['theta'][0] * np.pi / 180.
    logger.debug("omega guess = %e+%ei \n", omega.real, omega.imag)

    # epsilon is renormalized: epsilon = epsilon*(v_A^2/c^2*omega^2)
    epsilon = np.zeros((3, 3), dtype=complex)
    epsilon += (p['delta'][0] * omega)**2 * np.identity(3)
    """ Iterate over species """
    for m in range(0, int(p['Nsp'][0])):
        beta_perp = p['beta_perp'][m]
        beta_para = p['beta_para'][m]
        beta_ratio = beta_perp / beta_para
        dens = p['dens'][m]
        mu = p['mu'][m]
        q = p['q'][m]
        kappa = int(p['kappa'][m])  # right now only integer kappa is supported
        ''' chiX shortcuts for long terms '''
        chi = dens**1.5 * q**2 * np.sqrt(mu / beta_para) / (k * np.cos(theta))
        chi0 = (beta_ratio - 1.) * mu * dens * q**2
        ''' use kappa dispersion relation '''
        if (kappa < p['kappa_limit'][0]):
            ''' first add non-iterative term '''
            epsilon[0, 0] += chi0
            epsilon[1, 1] += chi0
            epsilon[2, 2] += chi0 * np.tan(theta)**2
            epsilon[2,2] += 2.*omega**2*(2.*kappa-1.)/(2.*kappa-3.)*dens**2\
              *q**2/beta_para/(k*np.cos(theta))**2
            epsilon[0, 2] += -chi0 * np.tan(theta)  # typo?

            N = int(p['N'][0])
            lab = 0
            epsi = np.zeros((3, 3), dtype=complex)
            while True:
                add_eps = np.zeros((3, 3), dtype=complex)
                for n in range(-N, N + 1):
                    # this piece is to avoid unnessary function evaluation
                    if (lab and abs(n) <= N - 1):
                        pass
                    else:
                        eta = beta_ratio * omega - (
                            beta_ratio - 1.) * n * mu * q  # shortcut
                        zh    = np.sqrt((2.*kappa+2.)/(2.*kappa-3.))*(omega-n*q*mu)/\
                                (np.sqrt(beta_para*mu)*k*np.cos(theta))*np.sqrt(dens)
                        jh = k * np.sin(theta) * np.sqrt(
                            (2. * kappa - 3.) * beta_perp / 2. / mu / dens) / q
                        intxx = complex_quadrature(intgrand, zh, jh, kappa, n,
                                                   0)
                        intyy = complex_quadrature(intgrand, zh, jh, kappa, n,
                                                   1)
                        intxy = complex_quadrature(intgrand, zh, jh, kappa, n,
                                                   2)

                        add_eps[0,0] += 4.*np.sqrt(2.)*mu**1.5*dens**2.5*q**4*(kappa-0.5)*((kappa+1.)/(2.*kappa-3.))**1.5\
                          /(beta_perp*(k*np.sin(theta))**2)/(np.sqrt(beta_para)*k*np.cos(theta))*n**2*eta*intxx
                        add_eps[1, 1] += 2. * np.sqrt(2.) * chi * (
                            kappa - 0.5) / np.sqrt(2. * kappa - 3.) * (
                                kappa + 1.)**1.5 * eta * intyy
                        add_eps[2,2] += 4.*np.sqrt(2.)/np.sqrt(mu)*dens**2.5*q**2*(kappa-0.5)*((kappa+1.)/(2.*kappa-3.0))**1.5\
                          /beta_perp/np.sqrt(beta_para)/(k*np.cos(theta))**3*eta*(omega-n*mu*q)**2*intxx
                        add_eps[0,1] += 4j*mu*dens**2*q**3/np.sqrt(beta_perp*beta_para)/(k**2*np.cos(theta)*np.sin(theta))*\
                          (kappa-0.5)/(2.*kappa-3.)*(kappa+1.)**1.5*n*eta*intxy
                        add_eps[0,2] += 4.*np.sqrt(2.)*np.sqrt(mu)*dens**2.5*q**3*(kappa-0.5)*((kappa+1)/(2.*kappa-3.))**1.5/\
                          beta_perp/(k*np.sin(theta))/np.sqrt(beta_para)/(k*np.cos(theta))**2*n*eta*(omega-n*mu*q)*intxx
                        add_eps[1,2] += -4j*dens**2*q**2*(kappa-0.5)/(2.*kappa-3.)*(kappa+1.)**1.5/np.sqrt(beta_perp*beta_para)\
                          /(k*np.cos(theta))**2*eta*(omega-n*mu*q)*intxy

                # check if we should increase N, and copy add_eps value to epsi
                lab, var = check_eps(epsi, add_eps, p['eps_error'][0], lab)
                if (var):
                    logger.debug("sp[%d], n=%d satisfies constraint!\n", m, N)
                    break
                epsi += add_eps
                N += 1
                logger.debug("sp[%d], Increase N to =%d!\n", m, N)
            epsilon += epsi

        else:
            '''use bi-maxwellian dispersion'''
            Lam = (k * np.sin(theta))**2 * beta_perp / (2. * q**2 * mu * dens)
            # add non-iterative term
            epsilon[0, 0] += chi0
            epsilon[1, 1] += chi0

            N = int(p['N'][0])
            lab = 0
            epsi = np.zeros((3, 3), dtype=complex)
            while (True):
                add_eps = np.zeros((3, 3), dtype=complex)
                for n in range(-N, N + 1):
                    # this piece is to avoid unnessary function evaluation
                    if (lab and abs(n) <= N - 1):
                        pass
                    else:
                        eta = beta_ratio * omega - (beta_ratio -
                                                    1.) * n * mu * q
                        zeta = (omega - n * mu * q) * np.sqrt(dens) / (
                            np.sqrt(beta_para * mu) * k * np.cos(theta))
                        add_eps[0, 0] += chi * n**2 * sp.ive(
                            n, Lam) / Lam * eta * f.Z(zeta)
                        add_eps[0, 1] += 1j * chi * n * (
                            f.dIne(n, Lam) - sp.ive(n, Lam)) * eta * f.Z(zeta)
                        add_eps[0,2] += -mu*dens**2*q**3/beta_perp/(k**2*np.sin(theta)*np.cos(theta))*eta*\
                            n*sp.ive(n,Lam)*f.dp(zeta,0)
                        add_eps[1,
                                1] += chi * (n**2 * sp.ive(n, Lam) / Lam -
                                             2. * Lam *
                                             (f.dIne(n, Lam) - sp.ive(n, Lam))
                                             ) * eta * f.Z(zeta)
                        add_eps[1, 2] += 1j / 2. * dens * q * np.tan(
                            theta) * eta * (f.dIne(n, Lam) -
                                            sp.ive(n, Lam)) * f.dp(zeta, 0)
                        add_eps[2,2] += -dens**2*q**2*(omega-n*mu*q)/beta_perp/(k*np.cos(theta))**2*eta*\
                           sp.ive(n,Lam)*f.dp(zeta,0)
                # check if we should increase N
                lab, var = check_eps(epsi, add_eps, p['eps_error'][0], lab)
                if (var):
                    logger.debug("sp[%d], n=%d satisfies constraint!\n", m, N)
                    break
                N += 1
                epsi += add_eps
                logger.debug("sp[%d], Increase N to =%d!\n", m, N)
            epsilon += epsi
    epsilon[1, 0] = -epsilon[0, 1]
    epsilon[2, 0] = epsilon[0, 2]
    epsilon[2, 1] = -epsilon[1, 2]
    epsilon[0, 0] += -(k * np.cos(theta))**2
    epsilon[1, 1] += -k**2
    epsilon[2, 2] += -(k * np.sin(theta))**2
    epsilon[0, 2] += k**2 * np.sin(theta) * np.cos(theta)
    epsilon[2, 0] += k**2 * np.sin(theta) * np.cos(theta)
    ''' calculate determinant '''
    disp_det = LA.det(epsilon) / omega**p['exp'][0]

    # calculate polarization
    val = np.ones(3, dtype=complex)  # eigenvalue
    vec = np.ones((3, 3), dtype=complex)  # eigenvectors
    val, vec = LA.eig(epsilon)
    if (abs(omega.real) > 1e-5):
        pol = 1j * vec[1] / vec[0] * omega.real / abs(omega.real)
    else:
        pol = 1j * vec[1] / vec[0]
    return val, pol
Ejemplo n.º 26
0
def logive(nu, kappa):
    return np.log(ive(nu, kappa))
Ejemplo n.º 27
0
def inference_model_grad(xin, config):

    # Load parameters
    n_data = config['N_data']
    n_pred = config['N_pred']
    c_data = config['c_data']
    s_data = config['s_data']
    c_2data = config['c_2data']
    s_2data = config['s_2data']
    mat_kin = config['Kinv']  # not ideal, but this way it's all consistent.
    idx_psi_p = config['idx_psi_p']
    idx_mf_k1 = config['idx_mf_k1']
    idx_mf_m1 = config['idx_mf_m1']
    k1 = config['k1']
    k2 = config['k2']

    n_totp = n_data + n_pred

    # Variable unpacking
    psi_p = xin[idx_psi_p]
    mf_k1 = np.exp(xin[idx_mf_k1])
    mf_m1 = xin[idx_mf_m1]

    # Variable reshaping
    psi_p = psi_p.reshape(n_pred, 1)
    mf_k1 = mf_k1.reshape(n_totp, 1)
    mf_m1 = mf_m1.reshape(n_totp, 1)
    k1 = k1.reshape(1, 1)
    k2 = k2.reshape(1, 1)

    # assemble prediction set statistics
    s_psi_p = np.sin(psi_p)
    c_psi_p = np.cos(psi_p)
    s_2psi_p = np.sin(2. * psi_p)
    c_2psi_p = np.cos(2. * psi_p)

    c_psi = np.vstack((c_psi_p, c_data))
    s_psi = np.vstack((s_psi_p, s_data))
    c_2psi = np.vstack((c_2psi_p, c_2data))
    s_2psi = np.vstack((s_2psi_p, s_2data))

    # Getting mean field moments
    div_ive_1_0 = ss.ive(1, mf_k1) / ss.ive(0, mf_k1)
    div_ive_2_0 = ss.ive(2, mf_k1) / ss.ive(0, mf_k1)
    div_ive_3_0 = ss.ive(3, mf_k1) / ss.ive(0, mf_k1)

    c_x = div_ive_1_0 * np.cos(mf_m1)
    s_x = div_ive_1_0 * np.sin(mf_m1)
    c_2x = div_ive_2_0 * np.cos(2. * mf_m1)
    s_2x = div_ive_2_0 * np.sin(2. * mf_m1)

    cc_x = 0.5 * (1 + c_2x)
    ss_x = 0.5 * (1 - c_2x)
    cs_x = 0.5 * s_2x

    # Building inverse sections
    mat_kin_cc = mat_kin[0:n_totp, 0:n_totp]
    mat_kin_ss = mat_kin[n_totp:, n_totp:]
    mat_kin_cs = mat_kin[0:n_totp, n_totp:]

    diag_mat_kin_cc = np.diag(mat_kin[0:n_totp, 0:n_totp]).reshape(n_totp, 1)
    diag_mat_kin_ss = np.diag(mat_kin[n_totp:, n_totp:]).reshape(n_totp, 1)
    diag_mat_kin_cs = np.diag(mat_kin[0:n_totp, n_totp:]).reshape(n_totp, 1)

    np.fill_diagonal(mat_kin_cc, 0.)
    np.fill_diagonal(mat_kin_ss, 0.)
    np.fill_diagonal(mat_kin_cs, 0.)

    # Gradient assembly point
    # ----------------------------------------------------
    # Prior
    dpri_psi_p = 0.
    dpri_c_x = - (np.dot(mat_kin_cc, c_x) + np.dot(mat_kin_cs, s_x))
    dpri_s_x = - (np.dot(mat_kin_ss, s_x) + np.dot(mat_kin_cs.T, c_x))
    dpri_cc_x = - 0.5 * diag_mat_kin_cc
    dpri_ss_x = - 0.5 * diag_mat_kin_ss
    dpri_cs_x = - diag_mat_kin_cs

    # Likelihood
    ds_psi_psi_p = + np.cos(psi_p)
    dc_psi_psi_p = - np.sin(psi_p)
    ds_2psi_psi_p = + 2. * np.cos(2. * psi_p)
    dc_2psi_psi_p = - 2. * np.sin(2. * psi_p)

    dlik_s_psi = k1 * s_x[0:n_pred]
    dlik_c_psi = k1 * c_x[0:n_pred]
    dlik_s_2psi = k2 * s_2x[0:n_pred]
    dlik_c_2psi = k2 * c_2x[0:n_pred]

    dlik_psi_p = (dlik_s_psi * ds_psi_psi_p + dlik_c_psi * dc_psi_psi_p +
                  dlik_s_2psi * ds_2psi_psi_p + dlik_c_2psi * dc_2psi_psi_p)

    dlik_c_x = +k1 * c_psi
    dlik_s_x = +k1 * s_psi
    dlik_cc_x = +k2 * c_2psi
    dlik_ss_x = -k2 * c_2psi
    dlik_cs_x = +2.0 * k2 * s_2psi

    # Mean field gradients (along with entropy)
    dc_x_mf_k1 = np.cos(mf_m1) * (0.5 * (1. + div_ive_2_0) - div_ive_1_0 ** 2)
    ds_x_mf_k1 = np.sin(mf_m1) * (0.5 * (1. + div_ive_2_0) - div_ive_1_0 ** 2)
    dcc_x_mf_k1 = +0.5 * np.cos(2. * mf_m1) * (0.5 * (div_ive_1_0 + div_ive_3_0) - div_ive_1_0 * div_ive_2_0)
    dss_x_mf_k1 = -0.5 * np.cos(2. * mf_m1) * (0.5 * (div_ive_1_0 + div_ive_3_0) - div_ive_1_0 * div_ive_2_0)
    dcs_x_mf_k1 = +0.5 * np.sin(2. * mf_m1) * (0.5 * (div_ive_1_0 + div_ive_3_0) - div_ive_1_0 * div_ive_2_0)

    dent_mf_k1 = - 0.5 * mf_k1 * (1. + div_ive_2_0) + mf_k1 * div_ive_1_0 ** 2

    dc_x_mf_m1 = - np.sin(mf_m1) * div_ive_1_0
    ds_x_mf_m1 = + np.cos(mf_m1) * div_ive_1_0
    dcc_x_mf_m1 = - np.sin(2. * mf_m1) * div_ive_2_0
    dss_x_mf_m1 = + np.sin(2. * mf_m1) * div_ive_2_0
    dcs_x_mf_m1 = + np.cos(2. * mf_m1) * div_ive_2_0

    dent_mf_m1 = 0.

    dmf_k1 = (dpri_c_x + dlik_c_x) * dc_x_mf_k1 + (dpri_s_x + dlik_s_x) * ds_x_mf_k1 + \
             (dpri_cc_x + dlik_cc_x) * dcc_x_mf_k1 + (dpri_ss_x + dlik_ss_x) * dss_x_mf_k1 + \
             (dpri_cs_x + dlik_cs_x) * dcs_x_mf_k1 + dent_mf_k1

    dmf_m1 = (dpri_c_x + dlik_c_x) * dc_x_mf_m1 + (dpri_s_x + dlik_s_x) * ds_x_mf_m1 + \
             (dpri_cc_x + dlik_cc_x) * dcc_x_mf_m1 + (dpri_ss_x + dlik_ss_x) * dss_x_mf_m1 + \
             (dpri_cs_x + dlik_cs_x) * dcs_x_mf_m1 + dent_mf_m1

    # Final gradient assembly
    dpsi_p = dlik_psi_p + dpri_psi_p

    # Positivy transformation
    dlog_mf_k1 = dmf_k1 * mf_k1

    grad = np.vstack((dpsi_p, dlog_mf_k1, dmf_m1))

    return - grad.flatten()
Ejemplo n.º 28
0
def inference_model_obj(xin, config):

    # Load parameters
    n_data = config['N_data']
    n_pred = config['N_pred']
    c_data = config['c_data']
    s_data = config['s_data']
    c_2data = config['c_2data']
    s_2data = config['s_2data']
    mat_kin = config['Kinv']  # not ideal, but this way it's all consistent.
    idx_psi_p = config['idx_psi_p']
    idx_mf_k1 = config['idx_mf_k1']
    idx_mf_m1 = config['idx_mf_m1']
    k1 = config['k1']
    k2 = config['k2']

    n_totp = n_data + n_pred

    # Variable unpacking
    psi_p = xin[idx_psi_p]
    mf_k1 = np.exp(xin[idx_mf_k1])
    mf_m1 = xin[idx_mf_m1]

    # Variable reshaping
    psi_p = psi_p.reshape(n_pred, 1)
    mf_k1 = mf_k1.reshape(n_totp, 1)
    mf_m1 = mf_m1.reshape(n_totp, 1)
    k1 = k1.reshape(1, 1)
    k2 = k2.reshape(1, 1)

    # assemble prediction set statistics
    s_psi_p = np.sin(psi_p)
    c_psi_p = np.cos(psi_p)
    s_2psi_p = np.sin(2. * psi_p)
    c_2psi_p = np.cos(2. * psi_p)

    c_psi = np.vstack((c_psi_p, c_data))
    s_psi = np.vstack((s_psi_p, s_data))
    c_2psi = np.vstack((c_2psi_p, c_2data))
    s_2psi = np.vstack((s_2psi_p, s_2data))

    # Getting mean field moments
    div_ive_1_0 = ss.ive(1, mf_k1) / ss.ive(0, mf_k1)
    div_ive_2_0 = ss.ive(2, mf_k1) / ss.ive(0, mf_k1)

    c_x = div_ive_1_0 * np.cos(mf_m1)
    s_x = div_ive_1_0 * np.sin(mf_m1)
    c_2x = div_ive_2_0 * np.cos(2. * mf_m1)
    s_2x = div_ive_2_0 * np.sin(2. * mf_m1)

    cc_x = 0.5 * (1 + c_2x)
    ss_x = 0.5 * (1 - c_2x)
    cs_x = 0.5 * s_2x

    # Building inverse sections
    mat_kin_cc = mat_kin[0:n_totp, 0:n_totp]
    mat_kin_ss = mat_kin[n_totp:, n_totp:]
    mat_kin_cs = mat_kin[0:n_totp, n_totp:]

    diag_mat_kin_cc = np.diag(mat_kin[0:n_totp, 0:n_totp]).reshape(n_totp, 1)
    diag_mat_kin_ss = np.diag(mat_kin[n_totp:, n_totp:]).reshape(n_totp, 1)
    diag_mat_kin_cs = np.diag(mat_kin[0:n_totp, n_totp:]).reshape(n_totp, 1)

    np.fill_diagonal(mat_kin_cc, 0.)
    np.fill_diagonal(mat_kin_ss, 0.)
    np.fill_diagonal(mat_kin_cs, 0.)

    # Free energy assembly point
    # ----------------------------------------------------

    prior = - (la.qform(c_x, mat_kin_cs, s_x) + np.dot(diag_mat_kin_cs.T, cs_x) +
               0.5 * (la.qform(c_x, mat_kin_cc, c_x) + np.dot(diag_mat_kin_cc.T, cc_x) +
                      la.qform(s_x, mat_kin_ss, s_x) + np.dot(diag_mat_kin_ss.T, ss_x)))

    likelihood = k1 * (np.dot(c_psi.T, c_x) + np.dot(s_psi.T, s_x)) - n_totp * (np.log(ss.ive(0, k1)) + k1) +\
                 k2 * (np.dot(c_2psi.T, cc_x - ss_x) + np.dot(s_2psi.T, 2 * cs_x)) - n_totp * (np.log(ss.ive(0, k2)) + k2)

    entropy = np.sum(np.log(ss.ive(0, mf_k1)) + mf_k1 - mf_k1 * ss.ive(1, mf_k1) / ss.ive(0, mf_k1))

    energy = likelihood + prior + entropy

    return - energy.flatten()
Ejemplo n.º 29
0
 def compute_log_partition(self, az, bz, y):
     b = np.absolute(bz)
     I0 = ive(0, b * y)
     logZ = np.sum(-0.5 * az * (y**2) +
                   np.log(2 * np.pi * y * ive(0, b * y)) + b * y)
     return logZ
Ejemplo n.º 30
0
def vonmises_coefficient(k,m):
    return ive(m,k)/ive(0,k)
Ejemplo n.º 31
0
def convolveMRA(field, sigma):
    if sigma==0:
        return field.data
    n = int(len(field.dimensions[-1].data)/2)
    kernel = ive(numpy.arange(-n, n), sigma)
    return convolve(field.data, kernel, mode='same')
Ejemplo n.º 32
0
def dIne(n,a):
  return 0.5*(sp.ive(n-1,a)+sp.ive(n+1,a))
Ejemplo n.º 33
0
 def VerifyBesselIve(self, v, z, rtol, atol=1e-7):
     bessel_ive, v, z = self.evaluate([tfp.math.bessel_ive(v, z), v, z])
     scipy_ive = scipy_special.ive(v, z)
     self.assertAllClose(bessel_ive, scipy_ive, rtol=rtol, atol=atol)
Ejemplo n.º 34
0
def dive(n,a,i):
  a = float(a)
  # No perpendicular component
  if a ==0:
    if   i == 1:
      fz = 0.5*(sp.ive(n-1,a)+sp.ive(n+1,a))-sp.ive(n,a)
    elif i == 2:
      fz = 0.25*sp.ive(n-2,a)-sp.ive(n-1,a)+1.5*sp.ive(n,a)\
           -sp.ive(n+1,a)+0.25*sp.ive(n+2,a)
    else:
      sys.exit("Error:i should be 1 or 2 for dive function!")
   
  # with perpendicular component
  else:
    if   i == 1:
      fz = (n/a-1)*sp.ive(n,a)+sp.ive(n+1,a)
    elif i == 2:
      fz = ((n**2-n)/a**2-2*n/a+1.)*sp.ive(n,a)+\
           ((2*n+1.0)/a-2)*sp.ive(n+1,a)+sp.ive(n+2,a)
    else:
      sys.exit("Error:i should be 1 or 2 for dive function!")
  return fz
Ejemplo n.º 35
0
def k2w_es3d(
    kxs,
    kzs,
    species,
    params,
    isMag=None,
    J=8,
    N=10,
    check_convergence=True,
    convergence_thresh=0.975,
    sort="real",
    dry_run=False,
):
    """
    Compute electrostatic dispersion relation for a magnetized Vlasov-Poisson
    system assuming the background magnetic field along `z` and the wavevector
    `k` can have components along `x` and `z`, i.e., the perpendicular and
    parallel directions.
  
    The basic algorithm follows [1]. The Z function is approximated by a J-pole
    Pade expansion and the bi-Maxwellian distribution is approximated by a
    truncated summation of Bessel functions. This way, a linear system is
    generated that can be solved for complex frequencies as eigenvalues of the
    equivalent matrix.

    [1]:https://iopscience.iop.org/article/10.1088/1009-0630/18/2/01/pdf
  
    Args:
        kxs (np.ndarray): Wavevector component values along `x`.
        kzs (np.ndarray): Wavevector component values along `z`.
        species (np.ndarray): A list of parameters of each plasma species.
          `species[s]` are the parameters of the `s`th species, including
          `q, m, n, v0x, v0z, p0x, p0z`.
        params (dict): A dictionary of relevant parameters. Here, the used
          ones are `epsilon0` and `Bz`.
        isMag (list or None): A list of booleans to indicate wether each species
            is magnetized. If not set, all species are assumed to be magnetized.
        J (int): Order of Pade approximation. One of (`8`, `12`).
        N (int): Highest order of cylctron harmonic to include in the Bessel
          expansion of the bi-Maxwellian distribution. If `check_convergence`
          is set to True, `N` will be increased until the expansion coefficients
          add up to greater than a threshold value set by `convergence_thresh`.
        check_convergence (bool): See option `N`. Default is True.
        convergence_thresh (float): See option `N`. Default is 0.975.
        sort (str): Order for sorting computed frequencies. Default is "real".
        sort (str): `'real'` or `'imag'` or `'none'`. Order to sort results.
  
    Returns:
        ws (np.ndarray or list): Computed frequencies in a list. `ws[ik]` is the
          solution for the `ik`th wavevector. The result is packed as a
          `np.ndarray` if the `N` values used for all `k` are the same.
    """
    q, m, n, vx, vz, px, pz = np.rollaxis(np.array(species), axis=1)
    eps0 = params['epsilon0']
    Bz = params['Bz']

    S = len(q)  # number of species
    lamDz = np.sqrt(eps0 * pz / (n * q)**2)
    vtz = np.sqrt(2. * pz / n / m)
    vtx = np.sqrt(2. * px / n / m)
    wc = q * Bz / m

    if isMag is None:
        isMag = [True] * S
    assert (len(isMag) == S)

    bz, cz = bzs[J], czs[J]

    Tz_Tx = (vtz / vtx)**2
    rc = vtx / np.sqrt(2) / np.abs(wc)

    ks = np.sqrt(kzs**2 + kxs**2)
    nk = len(ks)
    ws = []
    Ns = np.zeros((nk, ), dtype=np.int32)

    if check_convergence:
        if np.any(isMag):
            for ik in range(nk):
                Nmax = N
                kz = kzs[ik]
                kp = kxs[ik]
                kp_rc2m = ((kp * rc[isMag])**2).max()
                found = False
                while (not found):
                    bessSum = ive(range(-Nmax, Nmax + 1), kp_rc2m).sum()
                    if bessSum < convergence_thresh:
                        Nmax = Nmax + 1
                    else:
                        found = True
                        if ik == len(ks) - 1:
                            logging.debug(
                                "(kp*rc)^2 {}, N {}, bessSum {}".format(
                                    kp_rc2m, Nmax, bessSum))
                Ns[ik] = Nmax
    logging.debug("Ns {}".format(Ns))
    print('Ns', Ns)
    if dry_run:
        return

    for ik, k in enumerate(ks):
        kz = kzs[ik]
        kp = kxs[ik]

        N4k = Ns[ik]  # the number of terms to keep for k
        SNJ = S * (2 * N4k + 1) * J
        M = np.zeros((SNJ, SNJ), dtype=np.complex128)
        B = np.zeros([SNJ], dtype=np.complex128)
        C = np.zeros([SNJ], dtype=np.complex128)
        m = 0
        for s in range(S):
            if isMag[s]:
                for n in range(-N4k, N4k + 1):
                    bessel = ive(n,
                                 (kp * rc[s])**2)  # modified Bessel function
                    for j in range(J):
                        B[m] = bessel * bz[j] \
                            * (cz[j] * kz * vtz[s] + n * wc[s] * Tz_Tx[s]) \
                            / (lamDz[s] * k)**2
                        C[m] = kz * vz[s] + kp * vx[s] + n * wc[s] \
                             + cz[j] * kz * vtz[s]
                        m += 1
            else:
                bessel = 1. / (2. * N4k + 1.)
                for n in range(-N4k, N4k + 1):
                    for j in range(J):
                        B[m] = bessel * bz[j] * (cz[j] * k * vtz[s]) \
                             / (lamDz[s] * k)**2
                        C[m] = kz * vz[s] + kp * vx[s] + cz[j] * k * vtz[s]
                        m += 1

        for m in range(SNJ):
            M[m, :] = -B[m]
            M[m, m] += C[m]

        w = scipy.linalg.eigvals(M)

        sort_idx = slice(None)
        if sort in ["imag"]:
            sort_idx = np.argsort(w.imag + 1j * w.real)
        elif sort in ["real"]:
            sort_idx = np.argsort(w)
        elif sort != 'none':
            raise ValueError('`sort` value {} not recognized'.format(sort))
        ws.append(w[sort_idx])

    if Ns.min() == Ns.max():
        # if different k has different N, the size of ws are different
        return np.array(ws)
    else:
        return ws
Ejemplo n.º 36
0
 def U(self, r):
     C = np.sqrt(2.0 * np.pi) / self.r_0 / 2.0
     x = r**2 / 4.0 / self.r_0**2
     # ive is bessel function of
     # imaginary argument * decaying exponent
     return special.ive(0, x) * C
def cp_log(p, kappa):
    p = float(p)
    cp = (p / 2 - 1) * np.log(kappa)
    cp += -(p / 2) * np.log(2 * pi) - np.log(ive(p / 2 - 1, kappa)) - kappa
    return cp
Ejemplo n.º 38
0
 def log_norm(cls, kappa, D):
     kappa = np.clip(kappa, 1e-10, np.inf)
     return (
         (D / 2) * np.log(2 * np.pi) + np.log(ive(D / 2 - 1, kappa))
         + np.abs(kappa) - (D / 2 - 1) * np.log(kappa)
     )
Ejemplo n.º 39
0
 def BI(gamH, hp, nr, xim):
     """Return BI_nr."""
     return np.exp(-np.real(gamH) * hp) * ive(nr, xim)
Ejemplo n.º 40
0
 def ratio(self, l):
     """Compute the ratio I_{l+1/2}(alpha) / I_{l-1/2}(alpha)"""
     return ive(l + 0.5, self.alpha) / ive(l - 0.5, self.alpha)
Ejemplo n.º 41
0
    def Mtil(m, epr, mur, bet, nu, b):
        def produto(A,B):
            C = _np.zeros((A.shape[0],B.shape[1],A.shape[2]),dtype=complex)
            for i in range(A.shape[0]):
                for j in range(B.shape[1]):
                    for k in range(A.shape[1]):
                        C[i,j,:] = C[i,j,:] + A[i,k,:]*B[k,j,:]
            return C

        for i in range(len(b)): # lembrando que length(b) = número de camadas - 1
            x = nu[i+1,:] * b[i]
            y = nu[i  ,:] * b[i]
            Mt = _np.zeros((4,4,w.shape[0]),dtype=complex)

            if i<len(b)-1:
                D = _np.zeros((4,4,nu.shape[1]),dtype=complex)
                z = nu[i+1,:]*b[i+1]
                if not any(z.real<0):
                    ind = (z.real<60)

                    A = _scyspe.iv(m,z[ind])
                    B = _scyspe.kv(m,z[ind])
                    C = _scyspe.iv(m,x[ind])
                    E = _scyspe.kv(m,x[ind])

                    D[0,0,:]    =  1
                    D[1,1,ind]  = - B*C/(A*E)
                    D[1,1,~ind] = - _np.exp(-2*(z[~ind]-x[~ind]))
                    D[2,2,:]    =  1
                    D[3,3,ind]  = - B*C/(A*E)
                    D[3,3,~ind] = - _np.exp(-2*(z[~ind]-x[~ind]))

            Mt[0,0,:] = -nu[i+1,:]**2*b[i]/epr[i+1,:]*(
                    epr[i+1,:]/nu[i+1,:]*(-_scyspe.kve(m-1,x)/_scyspe.kve(m,x) - m/x)
                    - epr[i,:]/nu[i,:]  *( _scyspe.ive(m-1,y)/_scyspe.ive(m,y) - m/y))
            Mt[0,1,:] = -nu[i+1,:]**2*b[i]/epr[i+1,:]*(
                    epr[i+1,:]/nu[i+1,:]*(-_scyspe.kve(m-1,x)/_scyspe.kve(m,x) - m/x)
                    - epr[i,:]/nu[i,:]  *(-_scyspe.kve(m-1,y)/_scyspe.kve(m,y) - m/y))
            Mt[1,0,:] = -nu[i+1,:]**2*b[i]/epr[i+1,:]*(
                    epr[i+1,:]/nu[i+1,:]*( _scyspe.ive(m-1,x)/_scyspe.ive(m,x) - m/x)
                    - epr[i,:]/nu[i,:]  *( _scyspe.ive(m-1,y)/_scyspe.ive(m,y) - m/y))
            Mt[1,1,:] = -nu[i+1,:]**2*b[i]/epr[i+1,:]*(
                    epr[i+1,:]/nu[i+1,:]*( _scyspe.ive(m-1,x)/_scyspe.ive(m,x) - m/x)
                    - epr[i,:]/nu[i,:]  *(-_scyspe.kve(m-1,y)/_scyspe.kve(m,y) - m/y))

            Mt[0,2,:] = (nu[i+1,:]**2/nu[i,:]**2 - 1)*m/(bet*epr[i+1,:])
            Mt[0,3,:] = Mt[0,2,:]
            Mt[1,2,:] = Mt[0,2,:]
            Mt[1,3,:] = Mt[0,2,:]
            Mt[2,2,:] = -nu[i+1,:]**2*b[i]/mur[i+1,:]*(
                    mur[i+1,:]/nu[i+1,:]*(-_scyspe.kve(m-1,x)/_scyspe.kve(m,x) - m/x)
                    - mur[i,:]/nu[i,:]  *( _scyspe.ive(m-1,y)/_scyspe.ive(m,y) - m/y))
            Mt[2,3,:] = -nu[i+1,:]**2*b[i]/mur[i+1,:]*(
                    mur[i+1,:]/nu[i+1,:]*(-_scyspe.kve(m-1,x)/_scyspe.kve(m,x) - m/x)
                    - mur[i,:]/nu[i,:]  *(-_scyspe.kve(m-1,y)/_scyspe.kve(m,y) - m/y))
            Mt[3,2,:] = -nu[i+1,:]**2*b[i]/mur[i+1,:]*(
                    mur[i+1,:]/nu[i+1,:]*( _scyspe.ive(m-1,x)/_scyspe.ive(m,x) - m/x)
                    - mur[i,:]/nu[i,:]  *( _scyspe.ive(m-1,y)/_scyspe.ive(m,y) - m/y))
            Mt[3,3,:] = -nu[i+1,:]**2*b[i]/mur[i+1,:]*(
                    mur[i+1,:]/nu[i+1,:]*( _scyspe.ive(m-1,x)/_scyspe.ive(m,x) - m/x)
                    - mur[i,:]/nu[i,:]  *(-_scyspe.kve(m-1,y)/_scyspe.kve(m,y) - m/y))
            Mt[2,0,:] = (nu[i+1,:]**2/nu[i,:]**2 - 1)*m/(bet*mur[i+1,:])
            Mt[2,1,:] = Mt[2,0,:]
            Mt[3,0,:] = Mt[2,0,:]
            Mt[3,1,:] = Mt[2,0,:]

            if len(b) == 1:
                M = Mt
            else:
                if (i ==0):
                    M = produto(D,Mt)
                elif i < len(b)-1:
                    M = produto(D,produto(Mt,M))
                else:
                    M = produto(Mt,M)
        return M
Ejemplo n.º 42
0
 def f_scaled(xi_b, xi_y):
     b = sz_eff * xi_b
     y = b / az + xi_y / np.sqrt(az)
     coef = 2 * np.pi / np.sqrt(u_eff)
     bz = complex2array(np.array(b))
     return coef * relu(b) * relu(y) * ive(0, b * y) * f(bz, y)
Ejemplo n.º 43
0
 def U(self, r):
     C = np.sqrt(2.0 * np.pi) / self.r_0 / 2.0;
     x = r**2 / 4.0 / self.r_0**2
     # ive is bessel function of
     # imaginary argument * decaying exponent
     return special.ive(0, x) * C 
Ejemplo n.º 44
0
def magnetic_field_time_deriv_magnetic_dipole(t,
                                              xy,
                                              sigma=1.0,
                                              mu=mu_0,
                                              moment=1.0):
    """Magnetic field time derivative due to step off vertical dipole at the surface

    Parameters
    ----------
    t : (n_t) numpy.ndarray
        times (s)
    xy : (n_locs, 2) numpy.ndarray
        surface field locations (m)
    sigma : float, optional
        conductivity
    mu : float, optional
        magnetic permeability
    moment : float, optional
        moment of the dipole

    Returns
    -------
    dh_dt : (n_t, n_locs, 3) numpy.ndarray
        The magnetic field at the observation locations and times.

    Notes
    -----
    Matches the negative of equation 4.70 of Ward and Hohmann 1988, for the vertical
    component (due to the difference in coordinate sign conventionn used here).

    .. math::
        \\frac{\\partial h_z}{\\partial t} = \\frac{m}{2 \\pi \\mu \\sigma \\rho^5}\\left[
        9\\mathrm{erf}(\\theta \\rho)
        - \\frac{2\\theta\\rho}{\\sqrt{\\pi}}\\left(
        9 + 6\\theta^2\\rho^2 + 4\\theta^4\\rho^4\\right)
        e^{-\\theta^2\\rho^2}
        \\right]

    Also matches equation 4.74 for the horizontal components

    .. math::
        \\frac{\\partial h_\\rho}{\\partial t} = -\\frac{m \\theta^2}{2 \\pi \\rho t}e^{-\\theta^2\\rho^2/2} \\left[
        (1 +\\theta^2 \\rho^2) I_0 \\left(
        \\frac{\\theta^2\\rho^2}{2}
        \\right) - \\left(
        2 + \\theta^2\\rho^2 + \\frac{4}{\\theta^2\\rho^2}\\right)I_1\\left(\\frac{\\theta^2\\rho^2}{2}\\right)
        \\right]

    Examples
    --------
    Reproducing the time derivate parts of Figure 4.4 and 4.5 from Ward and Hohmann 1988

    >>> import numpy as np
    >>> import matplotlib.pyplot as plt
    >>> from geoana.em.tdem import magnetic_field_time_deriv_magnetic_dipole

    Calculate the field at the time given, 100 m along the x-axis,

    >>> times = np.logspace(-6, 0, 200)
    >>> xy = np.array([[100, 0, 0]])
    >>> dh_dt = magnetic_field_time_deriv_magnetic_dipole(times, xy, sigma=1E-2)

    Match the vertical magnetic field plot

    >>> plt.loglog(times*1E3, dh_dt[:,0, 2], c='C0', label=r'$\\frac{\\partial h_z}{\\partial t}$')
    >>> plt.loglog(times*1E3, -dh_dt[:,0, 2], '--', c='C0')
    >>> plt.loglog(times*1E3, dh_dt[:,0, 0], c='C1', label=r'$\\frac{\\partial h_x}{\\partial t}$')
    >>> plt.loglog(times*1E3, -dh_dt[:,0, 0], '--', c='C1')
    >>> plt.xlabel('time (ms)')
    >>> plt.ylabel(r'$\\frac{\\partial h}{\\partial t}$ (A/(m s))')
    >>> plt.legend()
    >>> plt.show()
    """
    r = np.linalg.norm(xy[:, :2], axis=-1)
    x = xy[:, 0]
    y = xy[:, 1]
    tr = theta(t, sigma, mu)[:, None] * r

    dhz_dt = 1 / (r**3 * t[:, None]) * (
        9 / (2 * tr**2) * erf(tr) -
        (4 * tr**3 + 6 * tr + 9 / tr) / np.sqrt(np.pi) * np.exp(-tr**2))

    # iv(k, v) = ive(k, v) * exp(abs(arg))
    dhr_dt = -2 * tr**2 / (r**3 * t[:, None]) * (
        (1 + tr**2) * ive(0, tr**2 / 2) -
        (2 + tr**2 + 4 / tr**2) * ive(1, tr**2 / 2))
    angle = np.arctan2(y, x)
    dhx_dt = np.cos(angle) * dhr_dt
    dhy_dt = np.sin(angle) * dhr_dt
    return moment / (4 * np.pi) * np.stack((dhx_dt, dhy_dt, dhz_dt), axis=-1)