def fvm_timestep_RK2(self, dt): f_initial = self.f self.f = self.f + df_dt_fvm(self.f, self, True) * (dt / 2) self._communicate_f() self._apply_bcs_f() if (self.physical_system.params.charge_electron != 0 and self.physical_system.params.fields_solver == 'fdtd'): # Will return a flattened array containing the values of # J1,2,3 in 2D space: self.J1 = self.physical_system.params.charge_electron \ * self.compute_moments('mom_p1_bulk') # (i + 1/2, j + 1/2) self.J2 = self.physical_system.params.charge_electron \ * self.compute_moments('mom_p2_bulk') # (i + 1/2, j + 1/2) self.J3 = self.physical_system.params.charge_electron \ * self.compute_moments('mom_p3_bulk') # (i + 1/2, j + 1/2) # Obtaining the values for current density on the Yee-Grid: self.J1 = 0.5 * (self.J1 + af.shift(self.J1, 0, 0, 1)) # (i + 1/2, j) self.J2 = 0.5 * (self.J2 + af.shift(self.J2, 0, 1, 0)) # (i, j + 1/2) self.J3 = 0.25 * ( self.J3 + af.shift(self.J3, 0, 1, 0) + +af.shift(self.J3, 0, 0, 1) + af.shift(self.J3, 0, 1, 1)) # (i, j) # Here: # cell_centered_EM_fields[:3] is at n # cell_centered_EM_fields[3:] is at n+1/2 # cell_centered_EM_fields_at_n_plus_half[3:] is at n-1/2 self.cell_centered_EM_fields_at_n[:3] = self.cell_centered_EM_fields[: 3] self.cell_centered_EM_fields_at_n[3:] = \ 0.5 * ( self.cell_centered_EM_fields_at_n_plus_half[3:] + self.cell_centered_EM_fields[3:] ) self.cell_centered_EM_fields_at_n_plus_half[ 3:] = self.cell_centered_EM_fields[3:] fdtd(self, dt) fdtd_grid_to_ck_grid(self) # Here # cell_centered_EM_fields[:3] is at n+1 # cell_centered_EM_fields[3:] is at n+3/2 self.cell_centered_EM_fields_at_n_plus_half[:3] = \ 0.5 * ( self.cell_centered_EM_fields_at_n_plus_half[:3] + self.cell_centered_EM_fields[:3] ) self.f = f_initial + df_dt_fvm(self.f, self, False) * dt af.eval(self.f) return
def fdtd_evolve_B(self, dt): """ Evolves magnetic fields from B^{n + 1/2} --> B^{n + 3/2} Parameters ---------- dt : double Time-step size to evolve the system """ if (self.performance_test_flag == True): tic = af.time() dq1 = self.dq1 dq2 = self.dq2 E1 = self.yee_grid_EM_fields[0] # (i, j + 1/2) E2 = self.yee_grid_EM_fields[1] # (i + 1/2, j) E3 = self.yee_grid_EM_fields[2] # (i + 1/2, j + 1/2) E1_minus_q2 = af.shift(E1, 0, 0, 0, 1) E2_minus_q1 = af.shift(E2, 0, 0, 1, 0) E3_minus_q1 = af.shift(E3, 0, 0, 1, 0) E3_minus_q2 = af.shift(E3, 0, 0, 0, 1) # dB/dt = -(∇ x E) # dB1/dt = - dE3/dq2 # dB2/dt = + dE3/dq1 # dB3/dt = - (dE2/dq1 - dE1/dq2) # curlE_x = dE3/dq2 curlE_1 = (E3 - E3_minus_q2) / dq2 # (i + 1/2, j) # curlE_y = -dE3/dq1 curlE_2 = -(E3 - E3_minus_q1) / dq1 # (i, j + 1/2) # curlE_z = (dE2/dq1 - dE1/dq2) curlE_3 = (E2 - E2_minus_q1) / dq1 - (E1 - E1_minus_q2) / dq2 # (i, j) # B1 --> (i + 1/2, j) self.yee_grid_EM_fields[3] += -dt * curlE_1 # B2 --> (i, j + 1/2) self.yee_grid_EM_fields[4] += -dt * curlE_2 # B3 --> (i, j) self.yee_grid_EM_fields[5] += -dt * curlE_3 af.eval(self.yee_grid_EM_fields) if (self.performance_test_flag == True): af.sync() toc = af.time() self.time_fieldsolver += toc - tic return
def _gradUpdate(): u_hat_af = af.to_array(u_hat) if len(x.shape) == 2: DTu_hat = self._indexLastAxis(u_hat_af, 0) - af.shift(self._indexLastAxis(u_hat_af, 0), -1, 0) + \ self._indexLastAxis(u_hat_af, 1) - af.shift(self._indexLastAxis(u_hat_af, 1), 0, -1) elif len(x.shape) == 3: DTu_hat = self._indexLastAxis(u_hat_af, 0) - af.shift(self._indexLastAxis(u_hat_af, 0), -1, 0, 0) + \ self._indexLastAxis(u_hat_af, 1) - af.shift(self._indexLastAxis(u_hat_af, 1), 0, -1, 0) + \ self._indexLastAxis(u_hat_af, 2) - af.shift(self._indexLastAxis(u_hat_af, 2), 0, 0, -1) grad_u_hat = x - np.array(self.parameter * DTu_hat) return grad_u_hat
def compute_divB(self): B1 = self.yee_grid_EM_fields[3] # (i + 1/2, j) B2 = self.yee_grid_EM_fields[4] # (i, j + 1/2) B1_minus_q1 = af.shift(B1, 0, 0, 1) # (i - 1/2, j) B2_minus_q2 = af.shift(B2, 0, 0, 0, 1) # (i, j - 1/2) divB = (B1 - B1_minus_q1)/self.dq1 + (B2 - B2_minus_q2)/self.dq2 # (i, j) return(divB)
def current_values_to_yee_grid(self): # Obtaining the values for current density on the Yee-Grid: self.J1 = 0.5 * (self.J1 + af.shift(self.J1, 0, 0, 0, 1) ) # (i + 1/2, j) self.J2 = 0.5 * (self.J2 + af.shift(self.J2, 0, 0, 1, 0) ) # (i, j + 1/2) self.J3 = 0.25 * (self.J3 + af.shift(self.J3, 0, 0, 1, 0) + af.shift( self.J3, 0, 0, 0, 1) + af.shift(self.J3, 0, 0, 1, 1)) # (i, j) return
def compute_divE(self): communicate.communicate_fields(self, True) E1 = self.yee_grid_EM_fields[0] # (i, j + 1/2) E2 = self.yee_grid_EM_fields[1] # (i + 1/2, j) E1_plus_q1 = af.shift(E1, 0, 0, -1) # (i + 1, j + 1/2) E2_plus_q2 = af.shift(E2, 0, 0, 0, -1) # (i + 1/2, j + 1) divE = (E1_plus_q1 - E1)/self.dq1 + (E2_plus_q2 - E2)/self.dq2 # (i + 1/2, j + 1/2) return(divE)
def initialize_f(q1, q2, v1, v2, v3, params): m = params.mass k = params.boltzmann_constant n_b = params.density_background T_b = params.temperature_background v1_bulk_b = params.v1_bulk_background eigval, eigvecs = solve_linear_modes(params) pert_n = eigvecs[0, 1] pert_real_n = pert_n.real pert_imag_n = pert_n.imag pert_v1 = eigvecs[1, 1] pert_real_v1 = pert_v1.real pert_imag_v1 = pert_v1.imag pert_T = eigvecs[2, 1] pert_real_T = pert_T.real pert_imag_T = pert_T.imag k_q1 = params.k_q1 amp = params.amplitude # Introducing the perturbation amounts: # Plugging in the value from the Eigenvectors: # Calculating the perturbed density: n = n_b + amp * ( pert_real_n * af.cos(k_q1 * q1) - pert_imag_n * af.sin(k_q1 * q1) ) # Calculating the perturbed bulk velocities: v1_bulk = v1_bulk_b + amp * ( pert_real_v1 * af.cos(k_q1 * q1) - pert_imag_v1 * af.sin(k_q1 * q1) ) # Calculating the perturbed temperature: T = T_b + amp * ( pert_real_T * af.cos(k_q1 * q1) - pert_imag_T * af.sin(k_q1 * q1) ) f0 = n * (m / (2 * np.pi * k * T))**(1 / 2) \ * af.exp(-m * (v1 - v1_bulk)**2 / (2 * k * T)) \ dq1 = af.sum(q1[0, 0, 1, 0] - q1[0, 0, 0, 0]) f = f0 - 0.5 * params.tau(0, 0, 0, 0, 0) * (af.shift(f0, -1) - af.shift(f0, 1)) / dq1 af.eval(f) return (f)
def lax_friedrichs_flux(u, gv): ''' ''' u = af.reorder(af.moddims(u, params.N_LGL**2, 10, 10), 2, 1, 0) diff_u_boundary = af.np_to_af_array(np.zeros([10, 10, params.N_LGL**2])) u_xi_minus1_boundary_right = u[:, :, :params.N_LGL] u_xi_minus1_boundary_left = af.shift(u[:, :, -params.N_LGL:], d0=0, d1=1) u[:, :, :params.N_LGL] = (u_xi_minus1_boundary_right + u_xi_minus1_boundary_left) / 2 diff_u_boundary[:, :, :params.N_LGL] = (u_xi_minus1_boundary_right - u_xi_minus1_boundary_left) u_xi_1_boundary_left = u[:, :, -params.N_LGL:] u_xi_1_boundary_right = af.shift(u[:, :, :params.N_LGL], d0=0, d1=-1) u[:, :, :params.N_LGL] = (u_xi_minus1_boundary_left + u_xi_minus1_boundary_right) / 2 diff_u_boundary[:, :, -params.N_LGL:] = (u_xi_minus1_boundary_right - u_xi_minus1_boundary_left) u_eta_minus1_boundary_down = af.shift(u[:, :, params.N_LGL - 1:params.N_LGL**2:params.N_LGL], d0=-1) u_eta_minus1_boundary_up = u[:, :, 0:-params.N_LGL + 1:params.N_LGL] u[:, :, 0:-params.N_LGL + 1:params.N_LGL] = (u_eta_minus1_boundary_down\ + u_eta_minus1_boundary_up) / 2 diff_u_boundary[:, :, 0:-params.N_LGL + 1:params.N_LGL] = (u_eta_minus1_boundary_up\ -u_eta_minus1_boundary_down) u_eta_1_boundary_down = u[:, :, params.N_LGL - 1:params.N_LGL**2:params.N_LGL] u_eta_1_boundary_up = af.shift(u[:, :, 0:-params.N_LGL + 1:params.N_LGL], d0=1) u[:, :, params.N_LGL - 1:params.N_LGL ** 2:params.N_LGL] = (u_eta_1_boundary_up\ +u_eta_1_boundary_down) / 2 diff_u_boundary[:, :, params.N_LGL - 1:params.N_LGL ** 2:params.N_LGL] = (u_eta_1_boundary_up\ -u_eta_1_boundary_down) u = af.moddims(af.reorder(u, 2, 1, 0), params.N_LGL**2, 100) diff_u_boundary = af.moddims(af.reorder(diff_u_boundary, 2, 1, 0), params.N_LGL**2, 100) F_xi_e_ij = F_xi(u, gv) - params.c_x * diff_u_boundary F_eta_e_ij = F_eta(u, gv) - params.c_y * diff_u_boundary return F_xi_e_ij, F_eta_e_ij
def test_surface_term(): ''' A test function to test the surface_term function in the wave_equation module using analytical Lax-Friedrichs flux. ''' threshold = 1e-13 params.c = 1 params.N_LGL = 8 params.N_quad = 10 params.N_Elements = 10 wave = 'gaussian' gv = global_variables.advection_variables(params.N_LGL, params.N_quad,\ params.x_nodes, params.N_Elements,\ params.c, params.total_time, wave,\ params.c_x, params.c_y, params.courant,\ params.mesh_file, params.total_time_2d) analytical_f_i = (gv.u_init[-1, :]) analytical_f_i_minus1 = (af.shift(gv.u_init[-1, :], 0, 1)) L_p_1 = af.constant(0, params.N_LGL, dtype=af.Dtype.f64) L_p_1[params.N_LGL - 1] = 1 L_p_minus1 = af.constant(0, params.N_LGL, dtype=af.Dtype.f64) L_p_minus1[0] = 1 analytical_surface_term = af.blas.matmul(L_p_1, analytical_f_i)\ - af.blas.matmul(L_p_minus1, analytical_f_i_minus1) numerical_surface_term = (wave_equation.surface_term(gv.u_init[:, :], gv)) assert af.max(af.abs(analytical_surface_term - numerical_surface_term)) \ < threshold return analytical_surface_term
def test_surface_term(): ''' A test function to test the surface_term function in the wave_equation module using analytical Lax-Friedrichs flux. ''' threshold = 1e-13 params.c = 1 change_parameters(8, 10, 8, 'gaussian') analytical_f_i = (params.u[-1, :, 0]) analytical_f_i_minus1 = (af.shift(params.u[-1, :, 0], 0, 1)) L_p_1 = af.constant(0, params.N_LGL, dtype=af.Dtype.f64) L_p_1[params.N_LGL - 1] = 1 L_p_minus1 = af.constant(0, params.N_LGL, dtype=af.Dtype.f64) L_p_minus1[0] = 1 analytical_surface_term = af.blas.matmul(L_p_1, analytical_f_i)\ - af.blas.matmul(L_p_minus1, analytical_f_i_minus1) numerical_surface_term = (wave_equation.surface_term(params.u[:, :, 0])) assert af.max(af.abs(analytical_surface_term - numerical_surface_term)) \ < threshold return analytical_surface_term
def upwind_flux(u_n): ''' Finds the upwind flux of all the element edges present inside a domain. Parameters ---------- u_n : arrayfire.Array [N_LGL N_Elements M 1] Amplitude of the wave at the mapped LGL nodes of each element. This code will work for :math:`M` multiple ``u_n``. Returns ------- flux_x : arrayfire.Array [1 N_Elements 1 1] Contains the value of the flux at the boundary elements. Periodic boundary conditions are used. ''' right_state = af.shift(u_n[0, :], 0, -1) left_state = u_n[-1, :] if params.c > 0: return flux_x(left_state) if params.c == 0: return flux_x((left_state + right_state) / 2) if params.c < 0: return flux_x(right_state) return
def upwind_flux_maxwell_eq(u_n): ''' Finds the upwind flux of all the element edges present inside a domain for Mode :math:`1` of Maxwell's equations. Please refer to `maxwell_equation_pbc_1d.pdf`_ for the derivation of the modes. .. _maxwell_equation_pbc_1d.pdf: `https://goo.gl/8FS4mv` Parameters ---------- u_n : arrayfire.Array [N_LGL N_Elements M 1] Amplitude of the wave at the mapped LGL nodes of each element. This code will work for :math:`M` multiple ``u_n``. Returns ------- flux_x : arrayfire.Array [1 N_Elements 1 1] Contains the value of the flux at the boundary elements. Periodic boundary conditions are used. ''' right_state = af.shift(u_n[0, :], 0, -1) flux = right_state.copy() flux[:, :, 0] = -right_state[:, :, 1] flux[:, :, 1] = -right_state[:, :, 0] return flux
def lax_friedrichs_flux(u_n): ''' Calculates the lax-friedrichs_flux :math:`f_i` using. :math:`f_i = \\frac{F(u^{i + 1}_0) + F(u^i_{N_{LGL} - 1})}{2} - \\frac {\Delta x}{2\Delta t} (u^{i + 1}_0 - u^i_{N_{LGL} - 1})` The algorithm used is explained in this `document`_ .. _document: `https://goo.gl/sNsXXK` Parameters ---------- u_n : arrayfire.Array [N_LGL N_Elements M 1] Amplitude of the wave at the mapped LGL nodes of each element. This code will work for :math:`M` multiple ``u_n``. Returns ------- boundary_flux : arrayfire.Array [1 N_Elements 1 1] Contains the value of the flux at the boundary elements. Periodic boundary conditions are used. ''' u_iplus1_0 = af.shift(u_n[0, :], 0, -1) u_i_N_LGL = u_n[-1, :] flux_iplus1_0 = flux_x(u_iplus1_0) flux_i_N_LGL = flux_x(u_i_N_LGL) boundary_flux = (flux_iplus1_0 + flux_i_N_LGL) / 2 \ - params.c_lax * (u_iplus1_0 - u_i_N_LGL) / 2 return boundary_flux
def test_check_maxwells_constraints(): params = params_check_maxwells_contraints system = physical_system(domain, boundary_conditions, params, initialize_check_maxwells_contraints, advection_terms, collision_operator.BGK, moments ) dq1 = (domain.q1_end - domain.q1_start) / domain.N_q1 dq2 = (domain.q2_end - domain.q2_start) / domain.N_q2 q1, q2 = calculate_q_center(domain.q1_start, domain.q2_start, domain.N_q1, domain.N_q2, domain.N_ghost, dq1, dq2 ) rho = ( params.pert_real * af.cos( params.k_q1 * q1 + params.k_q2 * q2 ) - params.pert_imag * af.sin( params.k_q1 * q1 + params.k_q2 * q2 ) ) obj = fields_solver(system, rho, False ) # Checking for ∇.E = rho / epsilon rho_left_bot = 0.25 * ( rho + af.shift(rho, 0, 0, 0, 1) + af.shift(rho, 0, 0, 1, 0) + af.shift(rho, 0, 0, 1, 1) ) N_g = obj.N_g assert(af.mean(af.abs(obj.compute_divB()[:, :, N_g:-N_g, N_g:-N_g]))<1e-14) divE = obj.compute_divE() rho_b = af.mean(rho_left_bot) # background assert(af.mean(af.abs(divE - rho_left_bot + rho_b)[:, :, N_g:-N_g, N_g:-N_g])<1e-6)
def simple_data(verbose=False): display_func = _util.display_func(verbose) print_func = _util.print_func(verbose) display_func(af.constant(100, 3,3, dtype=af.Dtype.f32)) display_func(af.constant(25, 3,3, dtype=af.Dtype.c32)) display_func(af.constant(2**50, 3,3, dtype=af.Dtype.s64)) display_func(af.constant(2+3j, 3,3)) display_func(af.constant(3+5j, 3,3, dtype=af.Dtype.c32)) display_func(af.range(3, 3)) display_func(af.iota(3, 3, tile_dims=(2,2))) display_func(af.identity(3, 3, 1, 2, af.Dtype.b8)) display_func(af.identity(3, 3, dtype=af.Dtype.c32)) a = af.randu(3, 4) b = af.diag(a, extract=True) c = af.diag(a, 1, extract=True) display_func(a) display_func(b) display_func(c) display_func(af.diag(b, extract = False)) display_func(af.diag(c, 1, extract = False)) display_func(af.join(0, a, a)) display_func(af.join(1, a, a, a)) display_func(af.tile(a, 2, 2)) display_func(af.reorder(a, 1, 0)) display_func(af.shift(a, -1, 1)) display_func(af.moddims(a, 6, 2)) display_func(af.flat(a)) display_func(af.flip(a, 0)) display_func(af.flip(a, 1)) display_func(af.lower(a, False)) display_func(af.lower(a, True)) display_func(af.upper(a, False)) display_func(af.upper(a, True)) a = af.randu(5,5) display_func(af.transpose(a)) af.transpose_inplace(a) display_func(a) display_func(af.select(a > 0.3, a, -0.3)) af.replace(a, a > 0.3, -0.3) display_func(a)
def simple_data(verbose=False): display_func = _util.display_func(verbose) display_func(af.constant(100, 3, 3, dtype=af.Dtype.f32)) display_func(af.constant(25, 3, 3, dtype=af.Dtype.c32)) display_func(af.constant(2**50, 3, 3, dtype=af.Dtype.s64)) display_func(af.constant(2+3j, 3, 3)) display_func(af.constant(3+5j, 3, 3, dtype=af.Dtype.c32)) display_func(af.range(3, 3)) display_func(af.iota(3, 3, tile_dims=(2, 2))) display_func(af.identity(3, 3, 1, 2, af.Dtype.b8)) display_func(af.identity(3, 3, dtype=af.Dtype.c32)) a = af.randu(3, 4) b = af.diag(a, extract=True) c = af.diag(a, 1, extract=True) display_func(a) display_func(b) display_func(c) display_func(af.diag(b, extract=False)) display_func(af.diag(c, 1, extract=False)) display_func(af.join(0, a, a)) display_func(af.join(1, a, a, a)) display_func(af.tile(a, 2, 2)) display_func(af.reorder(a, 1, 0)) display_func(af.shift(a, -1, 1)) display_func(af.moddims(a, 6, 2)) display_func(af.flat(a)) display_func(af.flip(a, 0)) display_func(af.flip(a, 1)) display_func(af.lower(a, False)) display_func(af.lower(a, True)) display_func(af.upper(a, False)) display_func(af.upper(a, True)) a = af.randu(5, 5) display_func(af.transpose(a)) af.transpose_inplace(a) display_func(a) display_func(af.select(a > 0.3, a, -0.3)) af.replace(a, a > 0.3, -0.3) display_func(a) display_func(af.pad(a, (1, 1, 0, 0), (2, 2, 0, 0)))
def get_theta_bottom(q1, q2): x, y = get_cartesian_coords(q1, q2) # Extract x and y along bottom edge bottom_edge = 0 x = x[0, 0, :, bottom_edge] y = y[0, 0, :, bottom_edge] y_1 = af.shift(y, 0, 0, 1, 0) x_1 = af.shift(x, 0, 0, 1, 0) print("bot x shape : ", x.dims()) print("bot x1 shape : ", x_1.dims()) slope = af.atan((y_1 - y) / (x_1 - x)) #print("bot slope : ", slope) return (slope)
def get_theta_top(q1, q2): x, y = get_cartesian_coords(q1, q2) # Extract x and y along top edge top_edge = -1 x = x[0, 0, :, top_edge] y = y[0, 0, :, top_edge] y_1 = af.shift(y, 0, 0, 1, 0) x_1 = af.shift(x, 0, 0, 1, 0) print("top x shape : ", x.dims()) print("top x1 shape : ", x_1.dims()) slope = af.atan((y_1 - y) / (x_1 - x)) #print("top slope : ", slope) return (slope)
def get_theta_left(q1, q2): x, y = get_cartesian_coords(q1, q2) # Extract x and y along left edge left_edge = 0 x = x[0, 0, left_edge, :] y = y[0, 0, left_edge, :] y_1 = af.shift(y, 0, 0, 0, 1) x_1 = af.shift(x, 0, 0, 0, 1) #print("x shape : ", x.dims()) #print("x1 shape : ", x_1.dims()) slope = af.atan((y_1 - y) / (x_1 - x)) #print("slope : ", slope) return (slope)
def get_theta_right(q1, q2): x, y = get_cartesian_coords(q1, q2) # Extract x and y along right edge right_edge = -1 x = x[0, 0, right_edge, :] y = y[0, 0, right_edge, :] y_1 = af.shift(y, 0, 0, 0, 1) x_1 = af.shift(x, 0, 0, 0, 1) print("right x shape : ", x.dims()) print("right x1 shape : ", x_1.dims()) slope = af.atan((y_1 - y) / (x_1 - x)) #print("right slope : ", slope) return (slope)
def constrainPupil(self, pupil, pupil_mask=None, flag_smooth_phase=True): #makes sure pupil amplitude is between 0 and 1. #if pupil mask is passed in, amplitude will become the mask pupil_abs = np.abs(pupil) pupil_phase = af.shift(af.arg(pupil), pupil.shape[0] // 2, pupil.shape[1] // 2) #smoothen phase pupil_phase = af.convolve2(pupil_phase, self.gaussian_kernel) if pupil_mask is None: pupil_abs[pupil_abs > 1.0] = 1.0 pupil_abs[pupil_abs < 0] = 0.0 else: pupil_abs[:] = np.abs(pupil_mask) pupil = pupil_abs * np.exp( 1.0j * af.shift(pupil_phase, -1 * int(pupil.shape[0] // 2), -1 * int(pupil.shape[1] // 2))) return pupil
def roll(a, shift, axis=None): shape = a.shape if(axis is None): axis = 0 a = a.flatten() axis = pu.c2f(a.shape, axis) if axis == 0: s = arrayfire.shift(a.d_array, shift, 0, 0, 0) elif axis == 1: s = arrayfire.shift(a.d_array, 0, shift, 0, 0) elif axis == 2: s = arrayfire.shift(a.d_array, 0, 0, shift, 0) elif axis == 3: s = arrayfire.shift(a.d_array, 0, 0, 0, shift) else: raise NotImplementedError return afnumpy.ndarray(shape, dtype=a.dtype, af_array=s)
def roll(a, shift, axis=None): shape = a.shape if (axis is None): axis = 0 a = a.flatten() axis = pu.c2f(a.shape, axis) if axis == 0: s = arrayfire.shift(a.d_array, shift, 0, 0, 0) elif axis == 1: s = arrayfire.shift(a.d_array, 0, shift, 0, 0) elif axis == 2: s = arrayfire.shift(a.d_array, 0, 0, shift, 0) elif axis == 3: s = arrayfire.shift(a.d_array, 0, 0, 0, shift) else: raise NotImplementedError return afnumpy.ndarray(a.shape, dtype=a.dtype, af_array=s).reshape(shape)
def cell_centered_grid_to_yee_grid(self): E1 = self.cell_centered_EM_fields[0] E2 = self.cell_centered_EM_fields[1] E3 = self.cell_centered_EM_fields[2] B1 = self.cell_centered_EM_fields[3] B2 = self.cell_centered_EM_fields[4] B3 = self.cell_centered_EM_fields[5] self.yee_grid_EM_fields[0] = 0.5 * (E1 + af.shift(E1, 0, 0, 0, 1) ) # (i+1/2, j) self.yee_grid_EM_fields[1] = 0.5 * (E2 + af.shift(E2, 0, 0, 1, 0) ) # (i, j+1/2) self.yee_grid_EM_fields[2] = 0.25 * ( E3 + af.shift(E3, 0, 0, 1, 0) + af.shift(E3, 0, 0, 0, 1) + af.shift(E3, 0, 0, 1, 1)) # (i, j) self.yee_grid_EM_fields[3] = 0.5 * (B1 + af.shift(B1, 0, 0, 1, 0) ) # (i, j+1/2) self.yee_grid_EM_fields[4] = 0.5 * (B2 + af.shift(B2, 0, 0, 0, 1) ) # (i+1/2, j) self.yee_grid_EM_fields[5] = B3 # (i+1/2, j+1/2) af.eval(self.yee_grid_EM_fields) return
def fdtd_grid_to_ck_grid(self): E1_yee = self.yee_grid_EM_fields[0] E2_yee = self.yee_grid_EM_fields[1] E3_yee = self.yee_grid_EM_fields[2] B1_yee = self.yee_grid_EM_fields[3] B2_yee = self.yee_grid_EM_fields[4] B3_yee = self.yee_grid_EM_fields[5] # Interpolating at the (i + 1/2, j + 1/2) point of the grid to use for the # nonlinear solver: self.cell_centered_EM_fields[0] = 0.5 * (E1_yee + af.shift(E1_yee, 0, 0, -1)) self.cell_centered_EM_fields[1] = 0.5 * (E2_yee + af.shift(E2_yee, 0, -1, 0)) self.cell_centered_EM_fields[2] = 0.25 * ( E3_yee + af.shift(E3_yee, 0, 0, -1) + af.shift(E3_yee, 0, -1, 0) + af.shift(E3_yee, 0, -1, -1)) self.cell_centered_EM_fields[3] = 0.5 * (B1_yee + af.shift(B1_yee, 0, -1, 0)) self.cell_centered_EM_fields[4] = 0.5 * (B2_yee + af.shift(B2_yee, 0, 0, -1)) self.cell_centered_EM_fields[5] = B3_yee af.eval(self.cell_centered_EM_fields) return
def yee_grid_to_cell_centered_grid(self, fields_to_transform = None): """ Making use of the optional fields_to_transform option, one can convert the magnetic fields or the electric fields alone. The default option is to convert both when the option is passed as None """ E1_yee = self.yee_grid_EM_fields[0] # (i, j + 1/2) E2_yee = self.yee_grid_EM_fields[1] # (i + 1/2, j) E3_yee = self.yee_grid_EM_fields[2] # (i + 1/2, j + 1/2) B1_yee = self.yee_grid_EM_fields[3] # (i + 1/2, j) B2_yee = self.yee_grid_EM_fields[4] # (i, j + 1/2) B3_yee = self.yee_grid_EM_fields[5] # (i, j) # Interpolating at the (i + 1/2, j + 1/2) point of the grid: if(fields_to_transform == 'E' or fields_to_transform == None): self.cell_centered_EM_fields[0] = 0.5 * (E1_yee + af.shift(E1_yee, 0, 0, -1, 0)) self.cell_centered_EM_fields[1] = 0.5 * (E2_yee + af.shift(E2_yee, 0, 0, 0, -1)) self.cell_centered_EM_fields[2] = E3_yee if(fields_to_transform == 'B' or fields_to_transform == None): self.cell_centered_EM_fields[3] = 0.5 * (B1_yee + af.shift(B1_yee, 0, 0, 0, -1)) self.cell_centered_EM_fields[4] = 0.5 * (B2_yee + af.shift(B2_yee, 0, 0, -1, 0)) self.cell_centered_EM_fields[5] = 0.25 * ( B3_yee + af.shift(B3_yee, 0, 0, 0, -1) + af.shift(B3_yee, 0, 0, -1, 0) + af.shift(B3_yee, 0, 0, -1, -1) ) return
def yee_grid_to_cell_centered_grid(self): E1_yee = self.yee_grid_EM_fields[0] # (i + 1/2, j) E2_yee = self.yee_grid_EM_fields[1] # (i, j + 1/2) E3_yee = self.yee_grid_EM_fields[2] # (i, j) B1_yee = self.yee_grid_EM_fields[3] # (i, j + 1/2) B2_yee = self.yee_grid_EM_fields[4] # (i + 1/2, j) B3_yee = self.yee_grid_EM_fields[5] # (i + 1/2, j + 1/2) # Interpolating at the (i + 1/2, j + 1/2) point of the grid: self.cell_centered_EM_fields[0] = 0.5 * (E1_yee + af.shift(E1_yee, 0, 0, 0, -1)) self.cell_centered_EM_fields[1] = 0.5 * (E2_yee + af.shift(E2_yee, 0, 0, -1, 0)) self.cell_centered_EM_fields[2] = 0.25 * ( E3_yee + af.shift(E3_yee, 0, 0, 0, -1) + af.shift(E3_yee, 0, 0, -1, 0) + af.shift(E3_yee, 0, 0, -1, -1)) self.cell_centered_EM_fields[3] = 0.5 * (B1_yee + af.shift(B1_yee, 0, 0, -1, 0)) self.cell_centered_EM_fields[4] = 0.5 * (B2_yee + af.shift(B2_yee, 0, 0, 0, -1)) self.cell_centered_EM_fields[5] = B3_yee af.eval(self.cell_centered_EM_fields) return
def cell_centered_grid_to_yee_grid(self, fields_to_transform = None): """ Making use of the fields_to_transform option, one can convert the magnetic fields or the electric fields alone. The default option is to convert both when the option is passed as None """ E1 = self.cell_centered_EM_fields[0] E2 = self.cell_centered_EM_fields[1] E3 = self.cell_centered_EM_fields[2] B1 = self.cell_centered_EM_fields[3] B2 = self.cell_centered_EM_fields[4] B3 = self.cell_centered_EM_fields[5] if(fields_to_transform == 'E' or fields_to_transform == None): self.yee_grid_EM_fields[0] = 0.5 * (E1 + af.shift(E1, 0, 0, 1, 0)) # (i, j+1/2) self.yee_grid_EM_fields[1] = 0.5 * (E2 + af.shift(E2, 0, 0, 0, 1)) # (i+1/2, j) self.yee_grid_EM_fields[2] = E3 # (i+1/2, j+1/2) if(fields_to_transform == 'B' or fields_to_transform == None): self.yee_grid_EM_fields[3] = 0.5 * (B1 + af.shift(B1, 0, 0, 0, 1)) # (i+1/2, j) self.yee_grid_EM_fields[4] = 0.5 * (B2 + af.shift(B2, 0, 0, 1, 0)) # (i, j+1/2) self.yee_grid_EM_fields[5] = 0.25 * ( B3 + af.shift(B3, 0, 0, 1, 0) + af.shift(B3, 0, 0, 0, 1) + af.shift(B3, 0, 0, 1, 1) ) # (i, j) return
def surface_term(u_n): ''' Calculates the surface term, :math:`L_p(1) f_i - L_p(-1) f_{i - 1}` using the lax_friedrichs_flux function and lagrange_basis_value from params module. Parameters ---------- u_n : arrayfire.Array [N_LGL N_Elements M 1] Amplitude of the wave at the mapped LGL nodes of each element. This code will work for multiple :math:`M` ``u_n`` Returns ------- surface_term : arrayfire.Array [N_LGL N_Elements M 1] The surface term represented in the form of an array, :math:`L_p (1) f_i - L_p (-1) f_{i - 1}`, where p varies from zero to :math:`N_{LGL}` and i from zero to :math:`N_{Elements}`. p varies along the rows and i along columns. **See:** `PDF`_ describing the algorithm to obtain the surface term. .. _PDF: https://goo.gl/Nhhgzx ''' shape_u_n = utils.shape(u_n) L_p_minus1 = af.tile(params.lagrange_basis_value[:, 0], d0=1, d1=1, d2=shape_u_n[2]) L_p_1 = af.tile(params.lagrange_basis_value[:, -1], d0=1, d1=1, d2=shape_u_n[2]) #[NOTE]: Uncomment to use lax friedrichs flux #f_i = lax_friedrichs_flux(u_n) #[NOTE]: Uncomment to use upwind flux for uncoupled advection equations f_i = upwind_flux(u_n) #[NOTE]: Uncomment to use upwind flux for Maxwell's equations #f_i = upwind_flux_maxwell_eq(u_n) f_iminus1 = af.shift(f_i, 0, 1) surface_term = utils.matmul_3D(L_p_1, f_i) \ - utils.matmul_3D(L_p_minus1, f_iminus1) return surface_term
def slope_minmod(input_array, axis): if (axis == 0): f_i_plus_one = af.shift(input_array, -1) f_i_minus_one = af.shift(input_array, 1) elif (axis == 1): f_i_plus_one = af.shift(input_array, 0, -1) f_i_minus_one = af.shift(input_array, 0, 1) elif (axis == 2): f_i_plus_one = af.shift(input_array, 0, 0, -1) f_i_minus_one = af.shift(input_array, 0, 0, 1) forward_diff = (f_i_plus_one - input_array) backward_diff = (input_array - f_i_minus_one) central_diff = backward_diff + forward_diff slope_lim_theta = 2 left = slope_lim_theta * backward_diff center = 0.5 * central_diff right = slope_lim_theta * forward_diff return (minmod(left, center, right))
def fdtd_evolve_E(self, dt): if (self.performance_test_flag == True): tic = af.time() dq1 = self.dq1 dq2 = self.dq2 B1 = self.yee_grid_EM_fields[3] B2 = self.yee_grid_EM_fields[4] B3 = self.yee_grid_EM_fields[5] # dE1/dt = + dB3/dq2 # dE2/dt = - dB3/dq1 # dE3/dt = dB2/dq1 - dB1/dq2 B1_shifted_q2 = af.shift(B1, 0, 0, 0, 1) B2_shifted_q1 = af.shift(B2, 0, 0, 1, 0) B3_shifted_q1 = af.shift(B3, 0, 0, 1, 0) B3_shifted_q2 = af.shift(B3, 0, 0, 0, 1) self.yee_grid_EM_fields[0] += (dt / dq2) * (B3 - B3_shifted_q2) - self.J1 * dt self.yee_grid_EM_fields[1] += -(dt / dq1) * (B3 - B3_shifted_q1) - self.J2 * dt self.yee_grid_EM_fields[2] += (dt / dq1) * (B2 - B2_shifted_q1) \ - (dt / dq2) * (B1 - B1_shifted_q2) \ - dt * self.J3 af.eval(self.yee_grid_EM_fields) if (self.performance_test_flag == True): af.sync() toc = af.time() self.time_fieldsolver += toc - tic return
def initialize_electric_fields(self): if('initialize_E' in dir(self.initialize)): E1 = self.initialize.initialize_E(self.q1_left_center, self.q2_left_center, self.params )[0] E2 = self.initialize.initialize_E(self.q1_center_bot, self.q2_center_bot, self.params )[1] E3 = self.initialize.initialize_E(self.q1_center, self.q2_center, self.params )[2] elif('initialize_A_phi' in dir(self.initialize)): A1 = self.initialize.initialize_A_phi(self.q1_center_bot, self.q2_center_bot, self.params )[0] A2 = self.initialize.initialize_A_phi(self.q1_left_center, self.q2_left_center, self.params )[1] A3 = self.initialize.initialize_A_phi(self.q1_left_bot, self.q2_left_bot, self.params )[2] phi = self.initialize.initialize_A_phi(self.q1_center, self.q2_center, self.params )[3] dA3_dq2 = (af.shift(A3, 0, 0, 0, -1) - A3) / self.dq2 dA3_dq1 = (af.shift(A3, 0, 0, -1, 0) - A3) / self.dq1 dA2_dq1 = (af.shift(A2, 0, 0, -1, 0) - A2) / self.dq1 dA1_dq2 = (af.shift(A1, 0, 0, 0, -1) - A1) / self.dq2 dphi_dq1 = -(af.shift(phi, 0, 0, 1, 0) - phi) / self.dq1 dphi_dq2 = -(af.shift(phi, 0, 0, 0, 1) - phi) / self.dq2 E1 = dA3_dq2 - dphi_dq1 E2 = -dA3_dq1 - dphi_dq2 E3 = dA2_dq1 - dA1_dq2 else: raise NotImplementedError('Initialization method for electric fields not valid/found') self.yee_grid_EM_fields[:3] = af.join(0, E1, E2, E3) af.eval(self.yee_grid_EM_fields) return
a = af.randu(3, 4) b = af.diag(a, extract=True) c = af.diag(a, 1, extract=True) af.display(a) af.display(b) af.display(c) af.display(af.diag(b, extract = False)) af.display(af.diag(c, 1, extract = False)) af.display(af.tile(a, 2, 2)) af.display(af.reorder(a, 1, 0)) af.display(af.shift(a, -1, 1)) af.display(af.moddims(a, 6, 2)) af.display(af.flat(a)) af.display(af.flip(a, 0)) af.display(af.flip(a, 1)) af.display(af.lower(a, False)) af.display(af.lower(a, True)) af.display(af.upper(a, False)) af.display(af.upper(a, True))
a = af.randu(3, 4) b = af.diag(a, extract=True) c = af.diag(a, 1, extract=True) af.print_array(a) af.print_array(b) af.print_array(c) af.print_array(af.diag(b, extract = False)) af.print_array(af.diag(c, 1, extract = False)) af.print_array(af.tile(a, 2, 2)) af.print_array(af.reorder(a, 1, 0)) af.print_array(af.shift(a, -1, 1)) af.print_array(af.moddims(a, 6, 2)) af.print_array(af.flat(a)) af.print_array(af.flip(a, 0)) af.print_array(af.flip(a, 1)) af.print_array(af.lower(a, False)) af.print_array(af.lower(a, True)) af.print_array(af.upper(a, False)) af.print_array(af.upper(a, True))