def __init__(self): self.q1_start = 0 self.q2_start = 0 self.q1_end = 1 self.q2_end = 1 self.N_q1 = 1024 self.N_q2 = 1024 self.dq1 = (self.q1_end - self.q1_start) / self.N_q1 self.dq2 = (self.q2_end - self.q2_start) / self.N_q2 self.N_ghost = self.N_g = np.random.randint(3, 5) self.q1_center, self.q2_center = \ calculate_q_center(self.q1_start, self.q2_start, self.N_q1, self.N_q2, self.N_ghost, self.dq1, self.dq2 ) self.params = type('obj', (object, ), {'eps':1}) self.cell_centered_EM_fields = af.constant(0, 6, 1, self.q1_center.shape[2], self.q1_center.shape[3], dtype=af.Dtype.f64 ) self._comm = PETSc.COMM_WORLD.tompi4py() self.performance_test_flag = False
def __init__(self, physical_system, rho_hat_initial): """ Constructor for the fields_solver object, which takes in the physical system object and the FT of the initial charge density as the input. Parameters: ----------- physical_system: The defined physical system object which holds all the simulation information rho_hat_initial: af.Array The FT of the initial charge density array that's passed to an electrostatic solver for initialization """ self.N_q1 = physical_system.N_q1 self.N_q2 = physical_system.N_q2 self.dq1 = physical_system.dq1 self.dq2 = physical_system.dq2 self.params = physical_system.params self.initialize = physical_system.initial_conditions self.q1_center, self.q2_center = \ calculate_q_center(physical_system.q1_start, physical_system.q2_start, self.N_q1, self.N_q2, 0, self.dq1, self.dq2 ) self.k_q1, self.k_q2 = calculate_k(self.N_q1, self.N_q2, physical_system.dq1, physical_system.dq2) self._initialize(rho_hat_initial)
def __init__(self): self.physical_system = type('obj', (object, ), {'moments': moments}) self.p1_start = [-10] self.p2_start = [-10] self.p3_start = [-10] self.N_p1 = 32 self.N_p2 = 32 self.N_p3 = 32 self.dp1 = (-2 * self.p1_start[0]) / self.N_p1 self.dp2 = (-2 * self.p2_start[0]) / self.N_p2 self.dp3 = (-2 * self.p3_start[0]) / self.N_p3 self.q1_start = 0 self.q2_start = 0 self.q1_end = 1 self.q2_end = 1 self.N_q1 = 16 self.N_q2 = 16 self.dq1 = (self.q1_end - self.q1_start) / self.N_q1 self.dq2 = (self.q2_end - self.q2_start) / self.N_q2 self.q1_center, self.q2_center = \ calculate_q_center(self.q1_start, self.q2_start, self.N_q1, self.N_q2, 0, self.dq1, self.dq2 ) self.p1_center, self.p2_center, self.p3_center = \ calculate_p_center(self.p1_start, self.p2_start, self.p3_start, self.N_p1, self.N_p2, self.N_p3, [self.dp1], [self.dp2], [self.dp3] ) rho = (1 + 0.01 * af.sin(2 * np.pi * self.q1_center + 4 * np.pi * self.q2_center)) T = (1 + 0.01 * af.cos(2 * np.pi * self.q1_center + 4 * np.pi * self.q2_center)) p1_b = 0.01 * af.exp(-10 * self.q1_center**2 - 10 * self.q2_center**2) p2_b = 0.01 * af.exp(-10 * self.q1_center**2 - 10 * self.q2_center**2) p3_b = 0.01 * af.exp(-10 * self.q1_center**2 - 10 * self.q2_center**2) self.f = maxwell_boltzmann(rho, T, p1_b, p2_b, p3_b, self.p1_center, self.p2_center, self.p3_center)
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 __init__(self, physical_system): """ Constructor for the linear_solver object. It takes the physical system object as an argument and uses it in intialization and evolution of the system in consideration. Parameters ---------- physical_system: The defined physical system object which holds all the simulation information such as the initial conditions, and the domain info is passed as an argument in defining an instance of the linear_solver. This system is then evolved, and monitored using the various methods under the linear_solver class. """ self.physical_system = physical_system # Storing Domain Information: self.q1_start, self.q1_end = physical_system.q1_start,\ physical_system.q1_end self.q2_start, self.q2_end = physical_system.q2_start,\ physical_system.q2_end self.p1_start, self.p1_end = physical_system.p1_start,\ physical_system.p1_end self.p2_start, self.p2_end = physical_system.p2_start,\ physical_system.p2_end self.p3_start, self.p3_end = physical_system.p3_start,\ physical_system.p3_end # Getting Domain Resolution self.N_q1, self.dq1 = physical_system.N_q1, physical_system.dq1 self.N_q2, self.dq2 = physical_system.N_q2, physical_system.dq2 self.N_p1, self.dp1 = physical_system.N_p1, physical_system.dp1 self.N_p2, self.dp2 = physical_system.N_p2, physical_system.dp2 self.N_p3, self.dp3 = physical_system.N_p3, physical_system.dp3 # Getting number of species: N_s = self.N_species = len(physical_system.params.mass) if(type(physical_system.params.mass) == list): # Having a temporary copy of the lists to copy to af.Array: list_mass = physical_system.params.mass.copy() list_charge = physical_system.params.charge.copy() # Initializing af.Arrays for mass and charge: # Having the mass and charge along axis 1: self.physical_system.params.mass = af.constant(0, 1, N_s, dtype = af.Dtype.f64) self.physical_system.params.charge = af.constant(0, 1, N_s, dtype = af.Dtype.f64) for i in range(N_s): self.physical_system.params.mass[0, i] = list_mass[i] self.physical_system.params.charge[0, i] = list_charge[i] # Initializing variable to hold time elapsed: self.time_elapsed = 0 # Checking that periodic B.C's are utilized: if( physical_system.boundary_conditions.in_q1_left != 'periodic' and physical_system.boundary_conditions.in_q1_right != 'periodic' and physical_system.boundary_conditions.in_q2_bottom != 'periodic' and physical_system.boundary_conditions.in_q2_top != 'periodic' ): raise Exception('Only systems with periodic boundary conditions \ can be solved using the linear solver' ) # Initializing DAs which will be used in file-writing: # This is done so that the output format used by the linear solver matches # with the output format of the nonlinear solver: self._da_dump_f = PETSc.DMDA().create([self.N_q1, self.N_q2], dof=( self.N_species * self.N_p1 * self.N_p2 * self.N_p3 ) ) # Getting the number of definitions in moments: attributes = [a for a in dir(self.physical_system.moments) if not a.startswith('_')] # Removing utility functions: if('integral_over_v' in attributes): attributes.remove('integral_over_v') self._da_dump_moments = PETSc.DMDA().create([self.N_q1, self.N_q2], dof = self.N_species * len(attributes) ) # Printing backend details: PETSc.Sys.Print('\nBackend Details for Linear Solver:') PETSc.Sys.Print(indent('On Node: '+ socket.gethostname())) PETSc.Sys.Print(indent('Device Details:')) PETSc.Sys.Print(indent(af.info_str(), 2)) PETSc.Sys.Print(indent('Device Bandwidth = ' + str(bandwidth_test(100)) + ' GB / sec')) PETSc.Sys.Print() # Creating PETSc Vecs which are used in dumping to file: self._glob_f = self._da_dump_f.createGlobalVec() self._glob_f_array = self._glob_f.getArray() self._glob_moments = self._da_dump_moments.createGlobalVec() self._glob_moments_array = self._glob_moments.getArray() # Setting names for the objects which will then be # used as the key identifiers for the HDF5 files: PETSc.Object.setName(self._glob_f, 'distribution_function') PETSc.Object.setName(self._glob_moments, 'moments') # Intializing position, velocity and wave number arrays: self.q1_center, self.q2_center = \ calculate_q_center(self.q1_start, self.q2_start, self.N_q1, self.N_q2, 0, self.dq1, self.dq2 ) self.p1_center, self.p2_center, self.p3_center = \ calculate_p_center(self.p1_start, self.p2_start, self.p3_start, self.N_p1, self.N_p2, self.N_p3, self.dp1, self.dp2, self.dp3, ) # Converting dp1, dp2, dp3 to af.Array: self.dp1 = af.moddims(af.to_array(self.dp1), 1, self.N_species) self.dp2 = af.moddims(af.to_array(self.dp2), 1, self.N_species) self.dp3 = af.moddims(af.to_array(self.dp3), 1, self.N_species) self.k_q1, self.k_q2 = calculate_k(self.N_q1, self.N_q2, self.physical_system.dq1, self.physical_system.dq2 ) # Assigning the function objects to methods of the solver: self._A_q = self.physical_system.A_q self._A_p = self.physical_system.A_p self._source = self.physical_system.source # Initializing f, f_hat and the other EM field quantities: self._initialize(physical_system.params)