def _run_solve(self): """Function run on every step to perform the required steps to solve Poisson's equation.""" if not mwxrun.initialized: return # get rho from WarpX self.rho_data = mwxrun.get_gathered_rho_grid()[:,:,0] # run superLU solver to get phi self.solve() # write phi to WarpX mwxrun.set_phi_grid(self.phi)
def get_grid_quantities(self): """Function to return ion and electron density at the electron positions. Will also return the electron temperature if needed to calculate the Coulomb logarithm.""" self.ion_density_grid = mwxrun.get_gathered_rho_grid(self.field.name) if mwxrun.geom_str == 'Z': self.ion_density_grid = self.ion_density_grid[:, 0] / self.field.sq elif mwxrun.geom_str == 'XZ': self.ion_density_grid = self.ion_density_grid[:, :, 0] / self.field.sq if self.log_lambda is None: raise NotImplementedError( "Calculation of the Coulomb logarithm is not yet supported.") # Instantiate a particle processor for the electron species used # to get the electron density and temperature on grid if the # Coulomb logarithm needs to be calculated. Note that the # temperature is given in eV. '''
def _get_rho_ions(self): rho_data = mwxrun.get_gathered_rho_grid('he_ions', False) if mwxrun.me == 0: self.rho_array += (np.mean(rho_data[:, :, 0], axis=0) / constants.q_e / self.DIAG_STEPS)
def fields_diag(self): """Function to process (get, plot and save) field quantities. This function is called on every step, but only executes if check_timestep() evaluated to True. """ if (self.post_processing and (mwxrun.get_it() == mwxrun.simulation.max_steps)): self.do_post_processing() if not self.check_timestep(): return logger.info("Analyzing fields...") self.it = mwxrun.get_it() if self.process_phi: data = mwxrun.get_gathered_phi_grid(include_ghosts=False) self.process_field(data=data, titlestr='Electrostatic potential', plottype='phi', draw_image=True, default_ticks=True, draw_contourlines=False) # Optionally generate barrier index plot if requested if self.plot and (self.barrier_slices is not None): self.plot_barrier_slices(data, self.barrier_slices) if self.process_E: raise NotImplementedError( "E-field processing not yet implemented.") self.process_field(data=None, titlestr='Electric field strength', plottype='E', draw_image=True, default_ticks=True, draw_contourlines=False) if self.process_rho: # assume that rho_fp still holds the net charge density data = mwxrun.get_gathered_rho_grid(include_ghosts=False) * 1e-6 if mwxrun.dim == 1: data = data[:, 0] elif mwxrun.dim == 2: data = data[:, :, 0] self.process_field(data=data, titlestr='Net charge density', plottype='rho', draw_image=True, default_ticks=True, draw_contourlines=False) # deposit the charge density for each species for species in self.species_list: data = (mwxrun.get_gathered_rho_grid(species_name=species.name, include_ghosts=False) / species.sq * 1e-6) if mwxrun.dim == 1: data = data[:, 0] elif mwxrun.dim == 2: data = data[:, :, 0] self.process_field(data=data, titlestr=f'{species.name} particle density', plottype='n', draw_image=True, default_ticks=True, draw_contourlines=False) logger.info("Finished analyzing fields")
def test_two_embedded_cylinders_scraping(): name = "two_embedded_cylinders_scraping" # Include a random run number to allow parallel runs to not collide. Using # python randint prevents collisions due to numpy rseed below testing_util.initialize_testingdir(name) # Initialize each run with consistent, randomly-chosen, rseed. Use a random # seed instead for initial dataframe generation. # np.random.seed() np.random.seed(42147820) # Specific numbers match older run for consistency D_CA = 0.025 # m run = diode_setup.DiodeRun_V1( GEOM_STR='XZ', #V_ANODE_CATHODE=VOLTAGE, D_CA=D_CA, NX=64, NZ=64, DT=1e-10, TOTAL_TIMESTEPS=15, DIAG_STEPS=15, FIELD_DIAG_DATA_LIST=['phi'], # FIELD_DIAG_PLOT=True, INERT_GAS_TYPE='positron') # Only the functions we change from defaults are listed here run.setup_run(init_conductors=False, init_scraper=False, init_electrons=True, init_inert_gas=True, init_solver=False, init_injectors=False, init_field_diag=True, init_simcontrol=True, init_simulation=False) # Install the embedded boundaries cylinder1 = assemblies.InfCylinderY(center_x=-0.25 * D_CA, center_z=0.5 * D_CA, radius=0.1 * D_CA, V=-0.5, T=300, WF=4.7, name="Cylinder1") cylinder2 = assemblies.InfCylinderY(center_x=0.25 * D_CA, center_z=0.5 * D_CA, radius=0.1 * D_CA, V=0.2, T=300, WF=4.7, name="Cylinder2") # Initialize solver run.init_solver() run.init_conductors() run.electrons.save_particles_at_eb = 1 run.ions.save_particles_at_eb = 1 # Inject particles in the simulation volemitter = emission.ZSinDistributionVolumeEmitter( T=3000, zmin=0, zmax=run.D_CA, ) emission.PlasmaInjector( emitter=volemitter, species1=run.electrons, species2=run.ions, npart=4000, plasma_density=1e14, ) # Initialize the simulation run.init_simulation() run.init_warpx() # Run the main WARP loop while run.control.check_criteria(): mwxrun.simulation.step() ####################################################################### # Check flux on each cylinder # ####################################################################### cylinder1.init_scrapedparticles(cylinder1.fields) cylinder1.record_scrapedparticles() cyl1_scraped = cylinder1.get_scrapedparticles() cylinder2.init_scrapedparticles(cylinder2.fields) cylinder2.record_scrapedparticles() cyl2_scraped = cylinder2.get_scrapedparticles() assert np.allclose(cyl1_scraped['n'], np.array([2, 0])) assert np.allclose(cyl2_scraped['n'], np.array([1, 2])) ####################################################################### # Check rho results against reference data # ####################################################################### rho = mwxrun.get_gathered_rho_grid(include_ghosts=False)[:, :, 0] # np.save('two_embedded_cylinders_rho.npy', rho) ref_rho = np.load( os.path.join(testing_util.test_dir, 'embedded_boundary', 'two_embedded_cylinders_rho.npy')) assert np.allclose(rho, ref_rho)