Example #1
0
def calculate_E(B, J, qn, DX=dx):
    '''Calculates the value of the electric field based on source term and magnetic field contributions, assuming constant
    electron temperature across simulation grid. This is done via a reworking of Ampere's Law that assumes quasineutrality,
    and removes the requirement to calculate the electron current. Based on equation 10 of Buchner (2003, p. 140).
    INPUT:
        B   -- Magnetic field array. Displaced from E-field array by half a spatial step.
        J   -- Ion current density. Source term, based on particle velocities
        qn  -- Charge density. Source term, based on particle positions
    OUTPUT:
        E_out -- Updated electric field array
    '''
    curlB = get_curl_B(B, DX=DX) / mu0

    Ve = np.zeros((J.shape[0], 3))
    Ve[:, 0] = (J[:, 0] - curlB[:, 0]) / qn
    Ve[:, 1] = (J[:, 1] - curlB[:, 1]) / qn
    Ve[:, 2] = (J[:, 2] - curlB[:, 2]) / qn

    Te = get_electron_temp(qn)

    del_p = get_grad_P(qn, Te)

    B_center = interpolate_to_center_cspline3D(B, DX=DX)

    VexB = cross_product(Ve, B_center)

    E = np.zeros((J.shape[0], 3))
    E[:, 0] = -VexB[:, 0] - del_p / qn
    E[:, 1] = -VexB[:, 1]
    E[:, 2] = -VexB[:, 2]

    E[0] = E[J.shape[0] - 3]
    E[J.shape[0] - 2] = E[1]
    E[J.shape[0] - 1] = E[2]
    return E, Ve, Te
Example #2
0
def calculate_E_old(B, J, qn, DX=dx):
    '''Calculates the value of the electric field based on source term and magnetic field contributions, assuming constant
    electron temperature across simulation grid. This is done via a reworking of Ampere's Law that assumes quasineutrality,
    and removes the requirement to calculate the electron current. Based on equation 10 of Buchner (2003, p. 140).

    INPUT:
        B   -- Magnetic field array. Displaced from E-field array by half a spatial step.
        J   -- Ion current density. Source term, based on particle velocities
        qn  -- Charge density. Source term, based on particle positions

    OUTPUT:
        E_out -- Updated electric field array
    '''
    Te       = get_electron_temp(qn)

    B_center = interpolate_to_center_cspline3D(B, DX=DX)
    JxB      = cross_product(J, B_center)    
    curlB    = get_curl_B(B, DX=DX)
    BdB      = cross_product(B_center, curlB) / mu0
    del_p    = get_grad_P(qn, Te)

    E_out       = np.zeros((J.shape[0], 3))                 
    E_out[:, 0] = (- JxB[:, 0] - BdB[:, 0] - del_p ) / qn
    E_out[:, 1] = (- JxB[:, 1] - BdB[:, 1]         ) / qn
    E_out[:, 2] = (- JxB[:, 2] - BdB[:, 2]         ) / qn

    E_out[0]                = E_out[J.shape[0] - 3]
    E_out[J.shape[0] - 2]   = E_out[1]
    E_out[J.shape[0] - 1]   = E_out[2]                                  # This doesn't really get used, but might as well
    return E_out
Example #3
0
def calculate_E(B, Ji, q_dens, E, Ve, Te, temp3D, temp3D2, temp1D, qq=0):
    '''Calculates the value of the electric field based on source term and magnetic field contributions, assuming constant
    electron temperature across simulation grid. This is done via a reworking of Ampere's Law that assumes quasineutrality,
    and removes the requirement to calculate the electron current. Based on equation 10 of Buchner (2003, p. 140).
    
    INPUT:
        B   -- Magnetic field array. Displaced from E-field array by half a spatial step.
        Ji  -- Ion current density. Source term, based on particle velocities
        qn  -- Charge density. Source term, based on particle positions
        
    OUTPUT:
        E   -- Updated electric field array
        Ve  -- Electron velocity moment
        Te  -- Electron temperature
    
    arr3D, arr1D are tertiary arrays used for intermediary computations
    '''    
    curl_B_term(B, temp3D)                                   # temp3D is now curl B term

    Ve[:, 0] = (Ji[:, 0] - temp3D[:, 0]) / q_dens
    Ve[:, 1] = (Ji[:, 1] - temp3D[:, 1]) / q_dens
    Ve[:, 2] = (Ji[:, 2] - temp3D[:, 2]) / q_dens

    get_electron_temp(q_dens, Te)

    get_grad_P(q_dens, Te, temp1D, temp3D2[:, 0])            # temp1D is now del_p term, temp3D2 slice used for computation

    aux.interpolate_to_center_cspline3D(B, temp3D2)          # temp3d2 is now B_center

    aux.cross_product(Ve, temp3D2, temp3D)                   # temp3D is now Ve x B term

    E[:, 0]  = - temp3D[:, 0] - temp1D[:] / q_dens[:]
    E[:, 1]  = - temp3D[:, 1]
    E[:, 2]  = - temp3D[:, 2]

    E[0]                = E[Ji.shape[0] - 3]
    E[Ji.shape[0] - 2]  = E[1]
    E[Ji.shape[0] - 1]  = E[2]
    return 
Example #4
0
def test_interp_cross_manual():
    '''
    Test order of cross product with interpolation, separate from hall term calculation (double check)
    '''
    grids  = [16, 32, 64, 128, 256, 512, 1024]
    errors = np.zeros(len(grids))
    
    #NX   = 32      #const.NX
    xmin = 0.0     #const.xmin
    xmax = 2*np.pi #const.xmax
    k    = 1.0
    marker_size = 20
    
    for NX, ii in zip(grids, list(range(len(grids)))):
        dx   = xmax / NX
        #x    = np.arange(xmin, xmax, dx/100.)

        # Physical location of nodes
        E_nodes = (np.arange(NX + 3) - 0.5) * dx
        B_nodes = (np.arange(NX + 3) - 1.0) * dx
        
        ## TEST INPUT FIELDS ##
        A  = np.ones((NX + 3, 3))
        Ax = np.sin(1.0*E_nodes*k)
        Ay = np.sin(2.0*E_nodes*k)
        Az = np.sin(3.0*E_nodes*k)
        
        B  = np.ones((NX + 3, 3))
        Bx = np.cos(1.0*B_nodes*k)
        By = np.cos(2.0*B_nodes*k)
        Bz = np.cos(3.0*B_nodes*k)
        
        Be  = np.ones((NX + 3, 3))
        Bxe = np.cos(1.0*E_nodes*k)
        Bye = np.cos(2.0*E_nodes*k)
        Bze = np.cos(3.0*E_nodes*k)
        
        A[:, 0] = Ax ; B[:, 0] = Bx ; Be[:, 0] = Bxe
        A[:, 1] = Ay ; B[:, 1] = By ; Be[:, 1] = Bye
        A[:, 2] = Az ; B[:, 2] = Bz ; Be[:, 2] = Bze
        
        B_inter      = aux.interpolate_to_center_cspline3D(B)
        
        ## RESULTS (AxB) ##
        anal_result       = np.ones((NX + 3, 3))
        anal_result[:, 0] = Ay*Bze - Az*Bye
        anal_result[:, 1] = Az*Bxe - Ax*Bze
        anal_result[:, 2] = Ax*Bye - Ay*Bxe
        
        test_result  = aux.cross_product(A, Be)
        inter_result = aux.cross_product(A, B_inter)

        error_x    = abs(anal_result[:, 0] - inter_result[:, 0]).max()
        error_y    = abs(anal_result[:, 1] - inter_result[:, 1]).max()
        error_z    = abs(anal_result[:, 2] - inter_result[:, 2]).max()
        
        errors[ii] = np.max([error_x, error_y, error_z])
        
    for ii in range(len(grids) - 1):
        order = np.log(errors[ii] / errors[ii + 1]) / np.log(2)
        print(order)


    # OUTPUTS (Plots the highest grid-resolution version)
    plot = False
    if plot == True:
        plt.figure()
        plt.scatter(E_nodes, anal_result[:, 0], s=marker_size, c='k', marker='o')
        plt.scatter(E_nodes, anal_result[:, 1], s=marker_size, c='k', marker='o')
        plt.scatter(E_nodes, anal_result[:, 2], s=marker_size, c='k', marker='o')
    
        plt.scatter(E_nodes, test_result[:, 0], s=marker_size, c='r', marker='x')
        plt.scatter(E_nodes, test_result[:, 1], s=marker_size, c='r', marker='x')
        plt.scatter(E_nodes, test_result[:, 2], s=marker_size, c='r', marker='x')
    
        plt.scatter(E_nodes, inter_result[:, 0], s=marker_size, c='b', marker='x')
        plt.scatter(E_nodes, inter_result[:, 1], s=marker_size, c='b', marker='x')
        plt.scatter(E_nodes, inter_result[:, 2], s=marker_size, c='b', marker='x')
    
        for kk in range(NX + 3):
            plt.axvline(E_nodes[kk], linestyle='--', c='r', alpha=0.2)
            plt.axvline(B_nodes[kk], linestyle='--', c='b', alpha=0.2)
            
            plt.axvline(xmin, linestyle='-', c='k', alpha=0.2)
            plt.axvline(xmax, linestyle='-', c='k', alpha=0.2)
        
        plt.xlim(xmin - 1.5*dx, xmax + 2*dx)
        plt.legend()
    return
Example #5
0
def test_cspline_interpolation():
    '''
    Tests E-field update, hall term (B x curl(B)) only by selection of inputs
    '''
    grids = [8, 16, 32]
    errors = np.zeros(len(grids))
    
    for NX, ii in zip(grids, list(range(len(grids)))):
        #NX   = 32      #const.NX
        xmin = 0.0     #const.xmin
        xmax = 2*np.pi #const.xmax
        
        dx   = xmax / NX
        x    = np.arange(xmin - 1.5*dx, xmax + 2*dx, dx/100.)
        k    = 1.0
        marker_size = 20
        
        # Physical location of nodes
        E_nodes = (np.arange(NX + 3) - 0.5) * dx
        B_nodes = (np.arange(NX + 3) - 1.0) * dx
    
        Bxc        = np.cos(1.0*k*x)
        Byc        = np.cos(2.0*k*x)
        Bzc        = np.cos(3.0*k*x)
        
        Bx         = np.cos(1.0*k*B_nodes)
        By         = np.cos(2.0*k*B_nodes)
        Bz         = np.cos(3.0*k*B_nodes)
        
        Bxe        = np.cos(1.0*k*E_nodes)
        Bye        = np.cos(2.0*k*E_nodes)
        Bze        = np.cos(3.0*k*E_nodes)  
        
        B_input       = np.zeros((NX + 3, 3))
        B_input[:, 0] = Bx
        B_input[:, 1] = By
        B_input[:, 2] = Bz
    
        ## TEST INTERPOLATION ##
        B_center = aux.interpolate_to_center_cspline3D(B_input, DX=dx)
    
        error_x    = abs(B_center[:, 0] - Bxe).max()
        error_y    = abs(B_center[:, 1] - Bye).max()
        error_z    = abs(B_center[:, 2] - Bze).max()
        
        errors[ii] = np.max([error_x, error_y, error_z])
        
    for ii in range(len(grids) - 1):
        order = np.log(errors[ii] / errors[ii + 1]) / np.log(2)
        print(order)

    plot = True
    if plot == True:
        plt.figure()
        plt.scatter(B_nodes, B_input[:, 0], s=marker_size, c='b', marker='x')
        plt.scatter(B_nodes, B_input[:, 1], s=marker_size, c='b', marker='x')
        plt.scatter(B_nodes, B_input[:, 2], s=marker_size, c='b', marker='x')
        
        plt.scatter(E_nodes, Bxe, s=marker_size, c='k', marker='o')
        plt.scatter(E_nodes, Bye, s=marker_size, c='k', marker='o')
        plt.scatter(E_nodes, Bze, s=marker_size, c='k', marker='o')
        
        plt.scatter(E_nodes, B_center[:, 0], s=marker_size, c='r', marker='x')
        plt.scatter(E_nodes, B_center[:, 1], s=marker_size, c='r', marker='x')
        plt.scatter(E_nodes, B_center[:, 2], s=marker_size, c='r', marker='x')
        
        plt.plot(x, Bxc, linestyle=':', c='k')
        plt.plot(x, Byc, linestyle=':', c='k')
        plt.plot(x, Bzc, linestyle=':', c='k')
        
        for kk in range(NX + 3):
            plt.axvline(E_nodes[kk], linestyle='--', c='r', alpha=0.2)
            plt.axvline(B_nodes[kk], linestyle='--', c='b', alpha=0.2)
            
        plt.axvline(xmin, linestyle='-', c='k', alpha=0.2)
        plt.axvline(xmax, linestyle='-', c='k', alpha=0.2)
    
        plt.xlim(xmin - 1.5*dx, xmax + 2*dx)
        plt.legend()
    return
Example #6
0
def test_E_hall():
    '''
    Tests E-field update, hall term (B x curl(B)) only by selection of inputs
    '''
# =============================================================================
#     grids = [32, 64, 128, 256, 512, 1024, 2048]
#     err_curl   = np.zeros(len(grids))
#     err_interp = np.zeros(len(grids))
#     err_hall   = np.zeros(len(grids))
# =============================================================================
    
    #for NX, ii in zip(grids, range(len(grids))):
    NX   = 32      #const.NX
    xmin = 0.0     #const.xmin
    xmax = 2*np.pi #const.xmax
    
    dx   = xmax / NX
    k    = 1.0
    marker_size = 70
    
    E_nodes = (np.arange(NX + 3) - 0.5) * dx                    # Physical location of nodes
    B_nodes = (np.arange(NX + 3) - 1.0) * dx
    
    ## INPUTS ##
    Bx         =           np.sin(1.0*k*B_nodes)
    By         =           np.sin(2.0*k*B_nodes)
    Bz         =           np.sin(3.0*k*B_nodes)
    
    Bxe        =           np.sin(1.0*k*E_nodes)
    Bye        =           np.sin(2.0*k*E_nodes)
    Bze        =           np.sin(3.0*k*E_nodes)
    
    dBy        = 2.0 * k * np.cos(2.0*k*E_nodes)
    dBz        = 3.0 * k * np.cos(3.0*k*E_nodes)
    
    B_input       = np.zeros((NX + 3, 3))
    B_input[:, 0] = Bx
    B_input[:, 1] = By
    B_input[:, 2] = Bz

    Be_input       = np.zeros((NX + 3, 3))
    Be_input[:, 0] = Bxe
    Be_input[:, 1] = Bye
    Be_input[:, 2] = Bze
    B_center       = aux.interpolate_to_center_cspline3D(B_input, DX=dx)
    
    
    ## TEST CURL B (AGAIN JUST TO BE SURE)
    curl_B_FD   = fields.get_curl_B(B_input, DX=dx)
    curl_B_anal = np.zeros((NX + 3, 3))
    curl_B_anal[:, 1] = -dBz
    curl_B_anal[:, 2] =  dBy


    ## ELECTRIC FIELD CALCULATION ## 
    E_FD         =   fields.calculate_E(       B_input, np.zeros((NX + 3, 3)), np.ones(NX + 3), DX=dx)
    E_FD2        =   fields.calculate_E_w_exel(B_input, np.zeros((NX + 3, 3)), np.ones(NX + 3), DX=dx)
    
    E_anal       = np.zeros((NX + 3, 3))
    E_anal[:, 0] = - (Bye * dBy + Bze * dBz)
    E_anal[:, 1] = Bxe * dBy
    E_anal[:, 2] = Bxe * dBz
    E_anal      /= const.mu0
        

# =============================================================================
#         ## Calculate errors ##
#         err_curl[ii]   = np.abs(curl_B_FD[1: -2, :] - curl_B_anal[1: -2, :]).max()
#         err_interp[ii] = np.abs(B_center[1: -2, :]  - Be_input[1: -2, :]   ).max()
#         err_hall[ii]   = np.abs(E_FD[1: -2, :]  - E_anal[1: -2, :]   ).max()
#     
#     for ii in range(len(grids) - 1):
#         order_curl   = np.log(err_curl[ii]   / err_curl[ii + 1]  ) / np.log(2)
#         order_interp = np.log(err_interp[ii] / err_interp[ii + 1]) / np.log(2)
#         order_hall   = np.log(err_hall[ii]   / err_hall[ii + 1]  ) / np.log(2)
#         
#         print ''
#         print 'Grid reduction: {} -> {}'.format(grids[ii], grids[ii + 1])
#         print 'Curl order: {}, \nC-spline Interpolation order: {}'.format(order_curl, order_interp)
#         print 'E-field Hall order: {}'.format(order_hall)
# =============================================================================
        
        
    plot = True
    if plot == True:
# =============================================================================
#         # Plot curl test
#         plt.figure()
#         plt.scatter(E_nodes, curl_B_anal[:, 1], s=marker_size, c='k')
#         plt.scatter(E_nodes, curl_B_anal[:, 2], s=marker_size, c='k')
#         plt.scatter(E_nodes, curl_B_FD[:, 1], s=marker_size, marker='x')
#         plt.scatter(E_nodes, curl_B_FD[:, 2], s=marker_size, marker='x')
#         
#         # Plot center-interpolated B test
#         plt.figure()
#         plt.scatter(B_nodes, B_input[:, 0], s=marker_size, c='b')
#         plt.scatter(B_nodes, B_input[:, 1], s=marker_size, c='b')
#         plt.scatter(B_nodes, B_input[:, 2], s=marker_size, c='b')
#         plt.scatter(E_nodes, B_center[:, 0], s=marker_size, c='r')
#         plt.scatter(E_nodes, B_center[:, 1], s=marker_size, c='r')
#         plt.scatter(E_nodes, B_center[:, 2], s=marker_size, c='r')
# =============================================================================
            
        # Plot E-field test solutions
        plt.scatter(E_nodes, E_anal[:, 0], s=marker_size, marker='o', c='k')
        plt.scatter(E_nodes, E_anal[:, 1], s=marker_size, marker='o', c='k')
        plt.scatter(E_nodes, E_anal[:, 2], s=marker_size, marker='o', c='k')
        
        plt.scatter(E_nodes, E_FD[:, 0],  s=marker_size, c='b', marker='+')
        plt.scatter(E_nodes, E_FD[:, 1],  s=marker_size, c='b', marker='+')
        plt.scatter(E_nodes, E_FD[:, 2],  s=marker_size, c='b', marker='+')
        
        plt.scatter(E_nodes, E_FD2[:, 0], s=marker_size, c='r', marker='x')
        plt.scatter(E_nodes, E_FD2[:, 1], s=marker_size, c='r', marker='x')
        plt.scatter(E_nodes, E_FD2[:, 2], s=marker_size, c='r', marker='x')
        
        for kk in range(NX + 3):
            plt.axvline(E_nodes[kk], linestyle='--', c='r', alpha=0.2)
            plt.axvline(B_nodes[kk], linestyle='--', c='b', alpha=0.2)
            
            plt.axvline(xmin, linestyle='-', c='k', alpha=0.2)
            plt.axvline(xmax, linestyle='-', c='k', alpha=0.2)
        
        plt.xlim(xmin - 1.5*dx, xmax + 2*dx)
    return