def test_efield_vs_gauss_law(): from hedge.mesh.generator import \ make_box_mesh, \ make_cylinder_mesh from math import sqrt, pi from pytools.arithmetic_container import \ ArithmeticList, join_fields from random import seed from pytools.stopwatch import Job from pyrticle.units import SIUnitsWithNaturalConstants units = SIUnitsWithNaturalConstants() seed(0) nparticles = 10000 beam_radius = 2.5 * units.MM emittance = 5 * units.MM * units.MRAD final_time = 0.1 * units.M / units.VACUUM_LIGHT_SPEED() field_dump_interval = 1 tube_length = 20 * units.MM # discretization setup ---------------------------------------------------- from pyrticle.geometry import make_cylinder_with_fine_core mesh = make_cylinder_with_fine_core( r=10 * beam_radius, inner_r=1 * beam_radius, min_z=0, max_z=tube_length, max_volume_inner=10 * units.MM**3, max_volume_outer=100 * units.MM**3, radial_subdiv=10, ) from hedge.backends import guess_run_context rcon = guess_run_context([]) discr = rcon.make_discretization(mesh, order=3) from hedge.models.em import MaxwellOperator max_op = MaxwellOperator(epsilon=units.EPSILON0, mu=units.MU0, flux_type=1) from hedge.models.nd_calculus import DivergenceOperator div_op = DivergenceOperator(discr.dimensions) # particles setup --------------------------------------------------------- from pyrticle.cloud import PicMethod from pyrticle.deposition.shape import ShapeFunctionDepositor from pyrticle.pusher import MonomialParticlePusher method = PicMethod(discr, units, ShapeFunctionDepositor(), MonomialParticlePusher(), 3, 3) # particle ic --------------------------------------------------------- cloud_charge = -1e-9 * units.C electrons_per_particle = abs(cloud_charge / nparticles / units.EL_CHARGE) el_energy = 10 * units.EL_REST_ENERGY() el_lorentz_gamma = el_energy / units.EL_REST_ENERGY() beta = (1 - 1 / el_lorentz_gamma**2)**0.5 gamma = 1 / sqrt(1 - beta**2) from pyrticle.distribution import KVZIntervalBeam beam = KVZIntervalBeam(units, total_charge=cloud_charge, p_charge=cloud_charge / nparticles, p_mass=electrons_per_particle * units.EL_MASS, radii=2 * [beam_radius], emittances=2 * [5 * units.MM * units.MRAD], z_length=tube_length, z_pos=tube_length / 2, beta=beta) state = method.make_state() method.add_particles(state, beam.generate_particles(), nparticles) # field ic ---------------------------------------------------------------- from pyrticle.cloud import guess_shape_bandwidth guess_shape_bandwidth(method, state, 2) from pyrticle.cloud import compute_initial_condition from hedge.data import ConstantGivenFunction fields = compute_initial_condition(rcon, discr, method, state, maxwell_op=max_op, potential_bc=ConstantGivenFunction()) # check against theory ---------------------------------------------------- q_per_unit_z = cloud_charge / beam.z_length class TheoreticalEField: shape = (3, ) def __call__(self, x, el): r = la.norm(x[:2]) if r >= max(beam.radii): xy_unit = x / r xy_unit[2] = 0 return xy_unit * ((q_per_unit_z) / (2 * pi * r * max_op.epsilon)) else: return numpy.zeros((3, )) def theory_indicator(x, el): r = la.norm(x[:2]) if r >= max(beam.radii): return 1 else: return 0 from hedge.tools import join_fields, to_obj_array e_theory = to_obj_array( discr.interpolate_volume_function(TheoreticalEField())) theory_ind = discr.interpolate_volume_function(theory_indicator) e_field, h_field = max_op.split_eh(fields) restricted_e = join_fields(*[e_i * theory_ind for e_i in e_field]) def l2_error(field, true): return discr.norm(field - true) / discr.norm(true) outer_l2 = l2_error(restricted_e, e_theory) assert outer_l2 < 0.08 if False: visf = vis.make_file("e_comparison") mesh_scalars, mesh_vectors = \ method.add_to_vis(vis, visf) vis.add_data(visf, [ ("e", restricted_e), ("e_theory", e_theory), ] + mesh_vectors + mesh_scalars) visf.close()
def __init__(self): from pyrticle.units import SIUnitsWithNaturalConstants self.units = units = SIUnitsWithNaturalConstants() ui = PICCPyUserInterface(units) setup = self.setup = ui.gather() from pytools.log import LogManager import os.path self.logmgr = LogManager(os.path.join( setup.output_path, "pic.dat"), "w") from hedge.backends import guess_run_context self.rcon = guess_run_context([]) if self.rcon.is_head_rank: mesh = self.rcon.distribute_mesh(setup.mesh) else: mesh = self.rcon.receive_mesh() self.discr = discr = \ self.rcon.make_discretization(mesh, order=setup.element_order, debug=setup.dg_debug) self.logmgr.set_constant("elements_total", len(setup.mesh.elements)) self.logmgr.set_constant("elements_local", len(mesh.elements)) self.logmgr.set_constant("element_order", setup.element_order) # em operator --------------------------------------------------------- maxwell_kwargs = { "epsilon": units.EPSILON0, "mu": units.MU0, "flux_type": setup.maxwell_flux_type, "bdry_flux_type": setup.maxwell_bdry_flux_type } if discr.dimensions == 3: from hedge.models.em import MaxwellOperator self.maxwell_op = MaxwellOperator(**maxwell_kwargs) elif discr.dimensions == 2: from hedge.models.em import TEMaxwellOperator self.maxwell_op = TEMaxwellOperator(**maxwell_kwargs) else: raise ValueError, "invalid mesh dimension" if setup.chi is not None: from pyrticle.hyperbolic import ECleaningMaxwellOperator self.maxwell_op = ECleaningMaxwellOperator(self.maxwell_op, chi=setup.chi, phi_decay=setup.phi_decay) if setup.phi_filter is not None: from pyrticle.hyperbolic import PhiFilter from hedge.discretization import Filter, ExponentialFilterResponseFunction em_filters.append( PhiFilter(maxwell_op, Filter(discr, ExponentialFilterResponseFunction(*setup.phi_filter)))) # timestepping setup -------------------------------------------------- goal_dt = self.maxwell_op.estimate_timestep(discr) * setup.dt_scale self.nsteps = int(setup.final_time/goal_dt)+1 self.dt = setup.final_time/self.nsteps self.stepper = setup.timestepper_maker(self.dt) # particle setup ------------------------------------------------------ from pyrticle.cloud import PicMethod, PicState, \ optimize_shape_bandwidth, \ guess_shape_bandwidth method = self.method = PicMethod(discr, units, setup.depositor, setup.pusher, dimensions_pos=setup.dimensions_pos, dimensions_velocity=setup.dimensions_velocity, debug=setup.debug) self.state = method.make_state() method.add_particles( self.state, setup.distribution.generate_particles(), setup.nparticles) self.total_charge = setup.nparticles*setup.distribution.mean()[2][0] if isinstance(setup.shape_bandwidth, str): if setup.shape_bandwidth == "optimize": optimize_shape_bandwidth(method, self.state, setup.distribution.get_rho_interpolant( discr, self.total_charge), setup.shape_exponent) elif setup.shape_bandwidth == "guess": guess_shape_bandwidth(method, self.state, setup.shape_exponent) else: raise ValueError, "invalid shape bandwidth setting '%s'" % ( setup.shape_bandwidth) else: from pyrticle._internal import PolynomialShapeFunction method.depositor.set_shape_function( self.state, PolynomialShapeFunction( float(setup.shape_bandwidth), method.mesh_data.dimensions, setup.shape_exponent, )) # initial condition --------------------------------------------------- if "no_ic" in setup.debug: self.fields = self.maxwell_op.assemble_eh(discr=discr) else: from pyrticle.cloud import compute_initial_condition self.fields = compute_initial_condition(self.rcon, discr, method, self.state, maxwell_op=self.maxwell_op, potential_bc=setup.potential_bc, force_zero=False) # rhs calculators ----------------------------------------------------- from pyrticle.cloud import \ FieldRhsCalculator, \ FieldToParticleRhsCalculator, \ ParticleRhsCalculator, \ ParticleToFieldRhsCalculator self.f_rhs_calculator = FieldRhsCalculator(self.method, self.maxwell_op) self.p_rhs_calculator = ParticleRhsCalculator(self.method, self.maxwell_op) self.f2p_rhs_calculator = FieldToParticleRhsCalculator(self.method, self.maxwell_op) self.p2f_rhs_calculator = ParticleToFieldRhsCalculator(self.method, self.maxwell_op) # instrumentation setup ----------------------------------------------- self.add_instrumentation(self.logmgr)
def test_efield_vs_gauss_law(): from hedge.mesh.generator import \ make_box_mesh, \ make_cylinder_mesh from math import sqrt, pi from pytools.arithmetic_container import \ ArithmeticList, join_fields from random import seed from pytools.stopwatch import Job from pyrticle.units import SIUnitsWithNaturalConstants units = SIUnitsWithNaturalConstants() seed(0) nparticles = 10000 beam_radius = 2.5 * units.MM emittance = 5 * units.MM * units.MRAD final_time = 0.1*units.M/units.VACUUM_LIGHT_SPEED() field_dump_interval = 1 tube_length = 20*units.MM # discretization setup ---------------------------------------------------- from pyrticle.geometry import make_cylinder_with_fine_core mesh = make_cylinder_with_fine_core( r=10*beam_radius, inner_r=1*beam_radius, min_z=0, max_z=tube_length, max_volume_inner=10*units.MM**3, max_volume_outer=100*units.MM**3, radial_subdiv=10, ) from hedge.backends import guess_run_context rcon = guess_run_context([]) discr = rcon.make_discretization(mesh, order=3) from hedge.models.em import MaxwellOperator max_op = MaxwellOperator( epsilon=units.EPSILON0, mu=units.MU0, flux_type=1) from hedge.models.nd_calculus import DivergenceOperator div_op = DivergenceOperator(discr.dimensions) # particles setup --------------------------------------------------------- from pyrticle.cloud import PicMethod from pyrticle.deposition.shape import ShapeFunctionDepositor from pyrticle.pusher import MonomialParticlePusher method = PicMethod(discr, units, ShapeFunctionDepositor(), MonomialParticlePusher(), 3, 3) # particle ic --------------------------------------------------------- cloud_charge = -1e-9 * units.C electrons_per_particle = abs(cloud_charge/nparticles/units.EL_CHARGE) el_energy = 10*units.EL_REST_ENERGY() el_lorentz_gamma = el_energy/units.EL_REST_ENERGY() beta = (1-1/el_lorentz_gamma**2)**0.5 gamma = 1/sqrt(1-beta**2) from pyrticle.distribution import KVZIntervalBeam beam = KVZIntervalBeam(units, total_charge=cloud_charge, p_charge=cloud_charge/nparticles, p_mass=electrons_per_particle*units.EL_MASS, radii=2*[beam_radius], emittances=2*[5 * units.MM * units.MRAD], z_length=tube_length, z_pos=tube_length/2, beta=beta) state = method.make_state() method.add_particles(state, beam.generate_particles(), nparticles) # field ic ---------------------------------------------------------------- from pyrticle.cloud import guess_shape_bandwidth guess_shape_bandwidth(method, state, 2) from pyrticle.cloud import compute_initial_condition from hedge.data import ConstantGivenFunction fields = compute_initial_condition( rcon, discr, method, state, maxwell_op=max_op, potential_bc=ConstantGivenFunction()) # check against theory ---------------------------------------------------- q_per_unit_z = cloud_charge/beam.z_length class TheoreticalEField: shape = (3,) def __call__(self, x, el): r = la.norm(x[:2]) if r >= max(beam.radii): xy_unit = x/r xy_unit[2] = 0 return xy_unit*((q_per_unit_z) / (2*pi*r*max_op.epsilon)) else: return numpy.zeros((3,)) def theory_indicator(x, el): r = la.norm(x[:2]) if r >= max(beam.radii): return 1 else: return 0 from hedge.tools import join_fields, to_obj_array e_theory = to_obj_array(discr.interpolate_volume_function(TheoreticalEField())) theory_ind = discr.interpolate_volume_function(theory_indicator) e_field, h_field = max_op.split_eh(fields) restricted_e = join_fields(*[e_i * theory_ind for e_i in e_field]) def l2_error(field, true): return discr.norm(field-true)/discr.norm(true) outer_l2 = l2_error(restricted_e, e_theory) assert outer_l2 < 0.08 if False: visf = vis.make_file("e_comparison") mesh_scalars, mesh_vectors = \ method.add_to_vis(vis, visf) vis.add_data(visf, [ ("e", restricted_e), ("e_theory", e_theory), ] + mesh_vectors + mesh_scalars ) visf.close()
def __init__(self): from pyrticle.units import SIUnitsWithNaturalConstants self.units = units = SIUnitsWithNaturalConstants() ui = PICCPyUserInterface(units) setup = self.setup = ui.gather() from pytools.log import LogManager import os.path self.logmgr = LogManager(os.path.join(setup.output_path, "pic.dat"), "w") from hedge.backends import guess_run_context self.rcon = guess_run_context([]) if self.rcon.is_head_rank: mesh = self.rcon.distribute_mesh(setup.mesh) else: mesh = self.rcon.receive_mesh() self.discr = discr = \ self.rcon.make_discretization(mesh, order=setup.element_order, debug=setup.dg_debug) self.logmgr.set_constant("elements_total", len(setup.mesh.elements)) self.logmgr.set_constant("elements_local", len(mesh.elements)) self.logmgr.set_constant("element_order", setup.element_order) # em operator --------------------------------------------------------- maxwell_kwargs = { "epsilon": units.EPSILON0, "mu": units.MU0, "flux_type": setup.maxwell_flux_type, "bdry_flux_type": setup.maxwell_bdry_flux_type } if discr.dimensions == 3: from hedge.models.em import MaxwellOperator self.maxwell_op = MaxwellOperator(**maxwell_kwargs) elif discr.dimensions == 2: from hedge.models.em import TEMaxwellOperator self.maxwell_op = TEMaxwellOperator(**maxwell_kwargs) else: raise ValueError, "invalid mesh dimension" if setup.chi is not None: from pyrticle.hyperbolic import ECleaningMaxwellOperator self.maxwell_op = ECleaningMaxwellOperator( self.maxwell_op, chi=setup.chi, phi_decay=setup.phi_decay) if setup.phi_filter is not None: from pyrticle.hyperbolic import PhiFilter from hedge.discretization import Filter, ExponentialFilterResponseFunction em_filters.append( PhiFilter( maxwell_op, Filter( discr, ExponentialFilterResponseFunction( *setup.phi_filter)))) # timestepping setup -------------------------------------------------- goal_dt = self.maxwell_op.estimate_timestep(discr) * setup.dt_scale self.nsteps = int(setup.final_time / goal_dt) + 1 self.dt = setup.final_time / self.nsteps self.stepper = setup.timestepper_maker(self.dt) # particle setup ------------------------------------------------------ from pyrticle.cloud import PicMethod, PicState, \ optimize_shape_bandwidth, \ guess_shape_bandwidth method = self.method = PicMethod( discr, units, setup.depositor, setup.pusher, dimensions_pos=setup.dimensions_pos, dimensions_velocity=setup.dimensions_velocity, debug=setup.debug) self.state = method.make_state() method.add_particles(self.state, setup.distribution.generate_particles(), setup.nparticles) self.total_charge = setup.nparticles * setup.distribution.mean()[2][0] if isinstance(setup.shape_bandwidth, str): if setup.shape_bandwidth == "optimize": optimize_shape_bandwidth( method, self.state, setup.distribution.get_rho_interpolant( discr, self.total_charge), setup.shape_exponent) elif setup.shape_bandwidth == "guess": guess_shape_bandwidth(method, self.state, setup.shape_exponent) else: raise ValueError, "invalid shape bandwidth setting '%s'" % ( setup.shape_bandwidth) else: from pyrticle._internal import PolynomialShapeFunction method.depositor.set_shape_function( self.state, PolynomialShapeFunction( float(setup.shape_bandwidth), method.mesh_data.dimensions, setup.shape_exponent, )) # initial condition --------------------------------------------------- if "no_ic" in setup.debug: self.fields = self.maxwell_op.assemble_eh(discr=discr) else: from pyrticle.cloud import compute_initial_condition self.fields = compute_initial_condition( self.rcon, discr, method, self.state, maxwell_op=self.maxwell_op, potential_bc=setup.potential_bc, force_zero=False) # rhs calculators ----------------------------------------------------- from pyrticle.cloud import \ FieldRhsCalculator, \ FieldToParticleRhsCalculator, \ ParticleRhsCalculator, \ ParticleToFieldRhsCalculator self.f_rhs_calculator = FieldRhsCalculator(self.method, self.maxwell_op) self.p_rhs_calculator = ParticleRhsCalculator(self.method, self.maxwell_op) self.f2p_rhs_calculator = FieldToParticleRhsCalculator( self.method, self.maxwell_op) self.p2f_rhs_calculator = ParticleToFieldRhsCalculator( self.method, self.maxwell_op) # instrumentation setup ----------------------------------------------- self.add_instrumentation(self.logmgr)