예제 #1
0
파일: flutils.py 프로젝트: mkozturk/rapt
def fl_error(tpos, field, Bm):
    """
    Return the max and mean relative error of calculated dipole field line 
    points, compared to the analytic result. For debugging.

    Parameters
    ----------
    tpos : array-like
        4-element array of time and position.
    field: Field object
        The field object under which the integral is evaluated.
    Bm : float
        Mirror field value (T).
    
    Returns
    -------
    e_max : float
        The maximum error
    e_avg : float
        Th average error
    """
    fl = Fieldline(tpos, field, Bmax=Bm)
    fl.trace()
    r0 = np.sqrt(np.dot(tpos[1:], tpos[1:]))
    e_max = 0
    e_avg = 0
    for p in fl.curve:
        r = np.sqrt(np.dot(p[1:], p[1:]))
        l = np.arcsin(p[3] / r)
        e = abs(1 - r / (r0 * np.cos(l)**2))
        if e > e_max:
            e_max = e
        e_avg += e
    e_avg /= (len(fl.curve) - 1)
    return (e_max, e_avg)
예제 #2
0
파일: flutils.py 프로젝트: mkozturk/rapt
def fl_error(tpos, field, Bm):
    """
    Return the max and mean relative error of calculated dipole field line 
    points, compared to the analytic result. For debugging.

    Parameters
    ----------
    tpos : array-like
        4-element array of time and position.
    field: Field object
        The field object under which the integral is evaluated.
    Bm : float
        Mirror field value (T).
    
    Returns
    -------
    e_max : float
        The maximum error
    e_avg : float
        Th average error
    """
    fl = Fieldline(tpos, field, Bmax=Bm)
    fl.trace()
    r0 = np.sqrt(np.dot(tpos[1:],tpos[1:]))
    e_max = 0
    e_avg = 0
    for p in fl.curve:
        r = np.sqrt(np.dot(p[1:],p[1:]))
        l = np.arcsin(p[3]/r)
        e = abs(1 - r/(r0*np.cos(l)**2))
        if e > e_max:
            e_max = e
        e_avg += e
    e_avg /= (len(fl.curve)-1)
    return (e_max, e_avg)
예제 #3
0
파일: flutils.py 프로젝트: mkozturk/rapt
def criticalpoints(tpos, field, Bm):
    """
    Return a list of critical points where the field strength is a maximum or a minimum along the field line.
    
    Parameters
    ----------
    tpos : array-like
        Starting position and time for the field line.
    field : Field
        The field object that provides electric and magnetic field vectors and 
        related quantities.
    Bm : float
        The mirror field strength in Tesla (defines the endpoints of the field line).
    
    Returns
    -------
    array
        Array of (s, B, B'') triplets for each critical point, where s is the
        location along the field line (with respect to the initial position),
        B is the field strength at s, and B'' is the second derivative along
        the field line.
    
    """
    fl = Fieldline(tpos, field, Bmax = Bm)
    fl.trace()
    s = fl.gets()
    b = fl.getB()
    n = len(b)
    slist = []
    # first, make a list of approximate locations of minima or maxima.
    for i in range(1,n-1):
        if (b[i]-b[i-1])*(b[i+1]-b[i]) <= 0:
            slist.append(s[i])
    # Create an interpolated function B(s)
    B = interp1d(s, b, kind='cubic', assume_sorted=True)
    # Find the optimal point for each value in slist
    res = []    
    for s0 in slist:
        m = minimize(B, s0)
        sm = m.x[0]
        B2s = derivative(B, sm, dx=0.1*(s[1]-s[0]), n=2)
        res.append((sm, float(B(sm)), B2s))
    return res
예제 #4
0
파일: flutils.py 프로젝트: mkozturk/rapt
def criticalpoints(tpos, field, Bm):
    """
    Return a list of critical points where the field strength is a maximum or a minimum along the field line.
    
    Parameters
    ----------
    tpos : array-like
        Starting position and time for the field line.
    field : Field
        The field object that provides electric and magnetic field vectors and 
        related quantities.
    Bm : float
        The mirror field strength in Tesla (defines the endpoints of the field line).
    
    Returns
    -------
    array
        Array of (s, B, B'') triplets for each critical point, where s is the
        location along the field line (with respect to the initial position),
        B is the field strength at s, and B'' is the second derivative along
        the field line.
    
    """
    fl = Fieldline(tpos, field, Bmax=Bm)
    fl.trace()
    s = fl.gets()
    b = fl.getB()
    n = len(b)
    slist = []
    # first, make a list of approximate locations of minima or maxima.
    for i in range(1, n - 1):
        if (b[i] - b[i - 1]) * (b[i + 1] - b[i]) <= 0:
            slist.append(s[i])
    # Create an interpolated function B(s)
    B = interp1d(s, b, kind='cubic', assume_sorted=True)
    # Find the optimal point for each value in slist
    res = []
    for s0 in slist:
        m = minimize(B, s0)
        sm = m.x[0]
        B2s = derivative(B, sm, dx=0.1 * (s[1] - s[0]), n=2)
        res.append((sm, float(B(sm)), B2s))
    return res
예제 #5
0
파일: flutils.py 프로젝트: mkozturk/rapt
def eye(tpos, field, Bm, usedipole=False):
    """
    Return the I integral (second invariant) value.
    
    Parameters
    ----------
    tpos : array-like
        4-element vector of time (s) and starting position of the field line
        (meters).
    Bm : float
        Mirror field value in Tesla.
    field: Field object
        The field object under which the integral is evaluated.
    
    Returns
    -------
    float
        The second invariant I, evaluated over the field line passing through
        the starting point at the given time.
        
    Other Parameters
    ----------------
    usedipole : bool, optional
        If True, uses the formula for dipole, without following a field line.
    """
    eqpa_threshold = 70 # Below this value, use Simpson's rule. Otherwise use interpolation.
    
    # Return a more accurate form for I if field is a dipole.    
    if usedipole:
        R0 = np.sqrt(np.dot(tpos[1:3],tpos[1:3]))
        return dipoleI(R0,Bm)
    
    # Follow a field line from the starting point up to Bm.
    # The trace will slightly overshoot the mirror point.
    fl = Fieldline(tpos, field, Bmax = Bm)
    fl.trace()
    s = fl.gets()
    b = fl.getB()
    n = len(b)

    Bmin = np.min(b)   
    
    if Bmin > Bm:
        return 0
    if abs(Bmin-Bm)/Bm < 1e-12:  # equatorial particle
        return 0
    # Determine the indices of points that satisfy B<Bm
    inside = np.where(b<Bm)[0]
    # Discard points so that only one point lies beyond the mirror locations.
    b = np.delete(b, list(range(0,inside[0]-1)) + list(range(inside[-1]+2, n)))
    s = np.delete(s, list(range(0,inside[0]-1)) + list(range(inside[-1]+2, n)))
    assert b[0]>Bm and b[1]<Bm and b[-2]<Bm and b[-1]>Bm

    eqpa = np.arcsin(np.sqrt(Bmin/Bm)) * 180 / np.pi   # equatorial pitch angle (estimated)
    if eqpa < eqpa_threshold: # use Simpson's rule to evaluate the integral
        # Determine the lower (antiparallel direction) mirror point location
        sm1 = (Bm-b[0]) * (s[1]-s[0]) / (b[1]-b[0]) + s[0]
        # Determine the upper (parallel direction) mirror point location
        sm2 = (Bm-b[-2]) * (s[-1]-s[-2]) / (b[-1]-b[-2]) + s[-2]
                    
        s[0], s[-1] = sm1, sm2
        b[0], b[-1] = Bm, Bm

        #Evaluate all but the end intervals with Simpson's rule
        bi = np.sqrt(1-b[1:-1]/Bm)
        eye = simps(bi,s[1:-1])
        # Add the end intervals with special formula
        d = s[-1]-s[-2]
        eye += (2/3)*d*np.sqrt((Bm-b[-2])/Bm)
        d = s[1]-s[0]
        eye += (2/3)*d*np.sqrt((Bm-b[1])/Bm)

    else:  # use interpolation and adaptive quadrature for integration
        # Generate an interpolating function for B(s)
        B = interp1d(s, b, kind='quadratic', assume_sorted=True)
        # Determine the lower (antiparallel direction) mirror point location
        # with root finding.
        sm1 = brentq(lambda x: B(x)-Bm, s[0],s[1])
          
        # Determine the upper (parallel direction) mirror point location
        if B(s[-2])==Bm:
            sm2 = s[-2]
        else:  
            sm2 = brentq(lambda x: B(x)-Bm, s[-2],s[-1])        
        eye = quad(lambda x: np.sqrt(1-B(x)/Bm), sm1, sm2, epsrel=1e-4)[0]

    return eye
예제 #6
0
파일: flutils.py 프로젝트: mkozturk/rapt
def halfbouncepath(tpos,field,Bm):
    """Return the half-bounce path length S_b.
    
    Parameters
    ----------
    tpos : array-like
        4-element array of time and position.
    field: Field object
        The field object under which the integral is evaluated.
    Bm : float
        Mirror field value (T).

    Returns
    -------
    float
        The half-bounce path length (m) : The total helical distance traveled by a 
        particle around the guiding line passing through the given location and
        mirroring at B=Bm.
    """
    # Follow a field line from the starting point up to Bm.
    # The trace will slightly overshoot the mirror points.
    fl = Fieldline(tpos, field, Bmax = Bm)
    fl.trace()
    
    s = fl.gets()
    b = fl.getB()
    n = len(b)
    # Determine the indices of points that satisfy B<Bm
    inside = np.where(b<=Bm)[0]
    # there are 0 or 1 such points, we have an equatorial particle.
    # Discard points so that only one point lies beyond each mirror location.
    # i1,i2 are the indices of points to keep. 
    if len(inside) == 0:
        i1 = int((n-3)/2)
        i2 = int((n+1)/2)
    else:
        i1,i2 = inside[0]-1,inside[-1]+1
    b = np.delete(b, list(range(0,i1)) + list(range(i2+1, n)))
    s = np.delete(s, list(range(0,i1)) + list(range(i2+1, n)))
    n = len(b)
    
    if n == 3: # Equatorial particle
        # Evaluate Sb = pi * sqrt(2Bm/B2s)
        # where B2s is the second derivative at the minimum.
        # Estimate it using Lagrange polynomials of degree 2.
        s1, s2, s3 = s[0], s[1], s[2]
        B1, B2, B3 = b[0], b[1], b[2]
        s12 = s1-s2
        s23 = s2-s3
        s13 = s1-s3
        B2s = 2*(B1*s23 - B2*s13 + B3*s12) / (s12*s13*s23)
        res = np.pi * np.sqrt(2*Bm/B2s)
    else:
        # Get an interpolating function for B(s)
        B = interp1d(s, b, kind='quadratic', assume_sorted=True)
        # Determine the lower (antiparallel direction) mirror point location
        # with root finding.
        sm1 = brentq(lambda x: B(x)-Bm, s[0],s[1])
        # Determine the upper (parallel direction) mirror point location
        sm2 = brentq(lambda x: B(x)-Bm, s[-2],s[-1])        
        res = quad(lambda x: 1/np.sqrt(1-B(x)/Bm), sm1, sm2, epsrel=1e-4)[0]
        
    return res
예제 #7
0
파일: flutils.py 프로젝트: mkozturk/rapt
def eye(tpos, field, Bm, usedipole=False):
    """
    Return the I integral (second invariant) value.
    
    Parameters
    ----------
    tpos : array-like
        4-element vector of time (s) and starting position of the field line
        (meters).
    Bm : float
        Mirror field value in Tesla.
    field: Field object
        The field object under which the integral is evaluated.
    
    Returns
    -------
    float
        The second invariant I, evaluated over the field line passing through
        the starting point at the given time.
        
    Other Parameters
    ----------------
    usedipole : bool, optional
        If True, uses the formula for dipole, without following a field line.
    """
    eqpa_threshold = 70  # Below this value, use Simpson's rule. Otherwise use interpolation.

    # Return a more accurate form for I if field is a dipole.
    if usedipole:
        R0 = np.sqrt(np.dot(tpos[1:3], tpos[1:3]))
        return dipoleI(R0, Bm)

    # Follow a field line from the starting point up to Bm.
    # The trace will slightly overshoot the mirror point.
    fl = Fieldline(tpos, field, Bmax=Bm)
    fl.trace()
    s = fl.gets()
    b = fl.getB()
    n = len(b)

    Bmin = np.min(b)

    if Bmin > Bm:
        return 0
    if abs(Bmin - Bm) / Bm < 1e-12:  # equatorial particle
        return 0
    # Determine the indices of points that satisfy B<Bm
    inside = np.where(b < Bm)[0]
    # Discard points so that only one point lies beyond the mirror locations.
    b = np.delete(
        b,
        list(range(0, inside[0] - 1)) + list(range(inside[-1] + 2, n)))
    s = np.delete(
        s,
        list(range(0, inside[0] - 1)) + list(range(inside[-1] + 2, n)))
    assert b[0] > Bm and b[1] < Bm and b[-2] < Bm and b[-1] > Bm

    eqpa = np.arcsin(np.sqrt(
        Bmin / Bm)) * 180 / np.pi  # equatorial pitch angle (estimated)
    if eqpa < eqpa_threshold:  # use Simpson's rule to evaluate the integral
        # Determine the lower (antiparallel direction) mirror point location
        sm1 = (Bm - b[0]) * (s[1] - s[0]) / (b[1] - b[0]) + s[0]
        # Determine the upper (parallel direction) mirror point location
        sm2 = (Bm - b[-2]) * (s[-1] - s[-2]) / (b[-1] - b[-2]) + s[-2]

        s[0], s[-1] = sm1, sm2
        b[0], b[-1] = Bm, Bm

        #Evaluate all but the end intervals with Simpson's rule
        bi = np.sqrt(1 - b[1:-1] / Bm)
        eye = simps(bi, s[1:-1])
        # Add the end intervals with special formula
        d = s[-1] - s[-2]
        eye += (2 / 3) * d * np.sqrt((Bm - b[-2]) / Bm)
        d = s[1] - s[0]
        eye += (2 / 3) * d * np.sqrt((Bm - b[1]) / Bm)

    else:  # use interpolation and adaptive quadrature for integration
        # Generate an interpolating function for B(s)
        B = interp1d(s, b, kind='quadratic', assume_sorted=True)
        # Determine the lower (antiparallel direction) mirror point location
        # with root finding.
        sm1 = brentq(lambda x: B(x) - Bm, s[0], s[1])

        # Determine the upper (parallel direction) mirror point location
        if B(s[-2]) == Bm:
            sm2 = s[-2]
        else:
            sm2 = brentq(lambda x: B(x) - Bm, s[-2], s[-1])
        eye = quad(lambda x: np.sqrt(1 - B(x) / Bm), sm1, sm2, epsrel=1e-4)[0]

    return eye
예제 #8
0
파일: flutils.py 프로젝트: mkozturk/rapt
def halfbouncepath(tpos, field, Bm):
    """Return the half-bounce path length S_b.
    
    Parameters
    ----------
    tpos : array-like
        4-element array of time and position.
    field: Field object
        The field object under which the integral is evaluated.
    Bm : float
        Mirror field value (T).

    Returns
    -------
    float
        The half-bounce path length (m) : The total helical distance traveled by a 
        particle around the guiding line passing through the given location and
        mirroring at B=Bm.
    """
    # Follow a field line from the starting point up to Bm.
    # The trace will slightly overshoot the mirror points.
    fl = Fieldline(tpos, field, Bmax=Bm)
    fl.trace()

    s = fl.gets()
    b = fl.getB()
    n = len(b)
    # Determine the indices of points that satisfy B<Bm
    inside = np.where(b <= Bm)[0]
    # there are 0 or 1 such points, we have an equatorial particle.
    # Discard points so that only one point lies beyond each mirror location.
    # i1,i2 are the indices of points to keep.
    if len(inside) == 0:
        i1 = int((n - 3) / 2)
        i2 = int((n + 1) / 2)
    else:
        i1, i2 = inside[0] - 1, inside[-1] + 1
    b = np.delete(b, list(range(0, i1)) + list(range(i2 + 1, n)))
    s = np.delete(s, list(range(0, i1)) + list(range(i2 + 1, n)))
    n = len(b)

    if n == 3:  # Equatorial particle
        # Evaluate Sb = pi * sqrt(2Bm/B2s)
        # where B2s is the second derivative at the minimum.
        # Estimate it using Lagrange polynomials of degree 2.
        s1, s2, s3 = s[0], s[1], s[2]
        B1, B2, B3 = b[0], b[1], b[2]
        s12 = s1 - s2
        s23 = s2 - s3
        s13 = s1 - s3
        B2s = 2 * (B1 * s23 - B2 * s13 + B3 * s12) / (s12 * s13 * s23)
        res = np.pi * np.sqrt(2 * Bm / B2s)
    else:
        # Get an interpolating function for B(s)
        B = interp1d(s, b, kind='quadratic', assume_sorted=True)
        # Determine the lower (antiparallel direction) mirror point location
        # with root finding.
        sm1 = brentq(lambda x: B(x) - Bm, s[0], s[1])
        # Determine the upper (parallel direction) mirror point location
        sm2 = brentq(lambda x: B(x) - Bm, s[-2], s[-1])
        res = quad(lambda x: 1 / np.sqrt(1 - B(x) / Bm), sm1, sm2,
                   epsrel=1e-4)[0]

    return res