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 main(write_output=True, allow_features=None, flux_type_arg=1, bdry_flux_type_arg=None, extra_discr_args={}): from hedge.mesh.generator import make_cylinder_mesh, make_box_mesh from hedge.tools import EOCRecorder, to_obj_array from math import sqrt, pi from analytic_solutions import ( check_time_harmonic_solution, RealPartAdapter, SplitComplexAdapter, CylindricalFieldAdapter, CylindricalCavityMode, RectangularWaveguideMode, RectangularCavityMode, ) from hedge.models.em import MaxwellOperator from hedge.backends import guess_run_context rcon = guess_run_context(allow_features) epsilon0 = 8.8541878176e-12 # C**2 / (N m**2) mu0 = 4 * pi * 1e-7 # N/A**2. epsilon = 1 * epsilon0 mu = 1 * mu0 eoc_rec = EOCRecorder() cylindrical = False periodic = False if cylindrical: R = 1 d = 2 mode = CylindricalCavityMode(m=1, n=1, p=1, radius=R, height=d, epsilon=epsilon, mu=mu) r_sol = CylindricalFieldAdapter(RealPartAdapter(mode)) c_sol = SplitComplexAdapter(CylindricalFieldAdapter(mode)) if rcon.is_head_rank: mesh = make_cylinder_mesh(radius=R, height=d, max_volume=0.01) else: if periodic: mode = RectangularWaveguideMode(epsilon, mu, (3, 2, 1)) periodicity = (False, False, True) else: periodicity = None mode = RectangularCavityMode(epsilon, mu, (1, 2, 2)) if rcon.is_head_rank: mesh = make_box_mesh(max_volume=0.001, periodicity=periodicity) if rcon.is_head_rank: mesh_data = rcon.distribute_mesh(mesh) else: mesh_data = rcon.receive_mesh() for order in [4, 5, 6]: # for order in [1,2,3,4,5,6]: extra_discr_args.setdefault("debug", []).extend(["cuda_no_plan", "cuda_dump_kernels"]) op = MaxwellOperator(epsilon, mu, flux_type=flux_type_arg, bdry_flux_type=bdry_flux_type_arg) discr = rcon.make_discretization(mesh_data, order=order, tune_for=op.op_template(), **extra_discr_args) from hedge.visualization import VtkVisualizer if write_output: vis = VtkVisualizer(discr, rcon, "em-%d" % order) mode.set_time(0) def get_true_field(): return discr.convert_volume( to_obj_array(mode(discr).real.astype(discr.default_scalar_type).copy()), kind=discr.compute_kind ) fields = get_true_field() if rcon.is_head_rank: print "---------------------------------------------" print "order %d" % order print "---------------------------------------------" print "#elements=", len(mesh.elements) from hedge.timestep.runge_kutta import LSRK4TimeStepper stepper = LSRK4TimeStepper(dtype=discr.default_scalar_type, rcon=rcon) # from hedge.timestep.dumka3 import Dumka3TimeStepper # stepper = Dumka3TimeStepper(3, dtype=discr.default_scalar_type, rcon=rcon) # diagnostics setup --------------------------------------------------- from pytools.log import LogManager, add_general_quantities, add_simulation_quantities, add_run_info if write_output: log_file_name = "maxwell-%d.dat" % order else: log_file_name = None logmgr = LogManager(log_file_name, "w", rcon.communicator) add_run_info(logmgr) add_general_quantities(logmgr) add_simulation_quantities(logmgr) discr.add_instrumentation(logmgr) stepper.add_instrumentation(logmgr) from pytools.log import IntervalTimer vis_timer = IntervalTimer("t_vis", "Time spent visualizing") logmgr.add_quantity(vis_timer) from hedge.log import EMFieldGetter, add_em_quantities field_getter = EMFieldGetter(discr, op, lambda: fields) add_em_quantities(logmgr, op, field_getter) logmgr.add_watches(["step.max", "t_sim.max", ("W_field", "W_el+W_mag"), "t_step.max"]) # timestep loop ------------------------------------------------------- rhs = op.bind(discr) final_time = 0.5e-9 try: from hedge.timestep import times_and_steps step_it = times_and_steps( final_time=final_time, logmgr=logmgr, max_dt_getter=lambda t: op.estimate_timestep(discr, stepper=stepper, t=t, fields=fields), ) for step, t, dt in step_it: if step % 50 == 0 and write_output: sub_timer = vis_timer.start_sub_timer() e, h = op.split_eh(fields) visf = vis.make_file("em-%d-%04d" % (order, step)) vis.add_data( visf, [("e", discr.convert_volume(e, kind="numpy")), ("h", discr.convert_volume(h, kind="numpy"))], time=t, step=step, ) visf.close() sub_timer.stop().submit() fields = stepper(fields, t, dt, rhs) mode.set_time(final_time) eoc_rec.add_data_point(order, discr.norm(fields - get_true_field())) finally: if write_output: vis.close() logmgr.close() discr.close() if rcon.is_head_rank: print print eoc_rec.pretty_print("P.Deg.", "L2 Error") assert eoc_rec.estimate_order_of_convergence()[0, 1] > 6
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 main(write_output=True, allow_features=None, flux_type_arg=1, bdry_flux_type_arg=None, extra_discr_args={}): from hedge.mesh.generator import make_cylinder_mesh, make_box_mesh from hedge.tools import EOCRecorder, to_obj_array from math import sqrt, pi # noqa from analytic_solutions import ( # noqa RealPartAdapter, SplitComplexAdapter, CylindricalFieldAdapter, CylindricalCavityMode, RectangularWaveguideMode, RectangularCavityMode) from hedge.models.em import MaxwellOperator logging.basicConfig(level=logging.DEBUG) from hedge.backends import guess_run_context rcon = guess_run_context(allow_features) epsilon0 = 8.8541878176e-12 # C**2 / (N m**2) mu0 = 4 * pi * 1e-7 # N/A**2. epsilon = 1 * epsilon0 mu = 1 * mu0 eoc_rec = EOCRecorder() cylindrical = False periodic = False if cylindrical: R = 1 d = 2 mode = CylindricalCavityMode(m=1, n=1, p=1, radius=R, height=d, epsilon=epsilon, mu=mu) # r_sol = CylindricalFieldAdapter(RealPartAdapter(mode)) # c_sol = SplitComplexAdapter(CylindricalFieldAdapter(mode)) if rcon.is_head_rank: mesh = make_cylinder_mesh(radius=R, height=d, max_volume=0.01) else: if periodic: mode = RectangularWaveguideMode(epsilon, mu, (3, 2, 1)) periodicity = (False, False, True) else: periodicity = None mode = RectangularCavityMode(epsilon, mu, (1, 2, 2)) if rcon.is_head_rank: mesh = make_box_mesh(max_volume=0.001, periodicity=periodicity) if rcon.is_head_rank: mesh_data = rcon.distribute_mesh(mesh) else: mesh_data = rcon.receive_mesh() for order in [4, 5, 6]: #for order in [1,2,3,4,5,6]: extra_discr_args.setdefault("debug", []).extend( ["cuda_no_plan", "cuda_dump_kernels"]) op = MaxwellOperator(epsilon, mu, flux_type=flux_type_arg, bdry_flux_type=bdry_flux_type_arg) discr = rcon.make_discretization(mesh_data, order=order, tune_for=op.op_template(), **extra_discr_args) from hedge.visualization import VtkVisualizer if write_output: vis = VtkVisualizer(discr, rcon, "em-%d" % order) mode.set_time(0) def get_true_field(): return discr.convert_volume(to_obj_array( mode(discr).real.astype(discr.default_scalar_type).copy()), kind=discr.compute_kind) fields = get_true_field() if rcon.is_head_rank: print "---------------------------------------------" print "order %d" % order print "---------------------------------------------" print "#elements=", len(mesh.elements) from hedge.timestep.runge_kutta import LSRK4TimeStepper stepper = LSRK4TimeStepper(dtype=discr.default_scalar_type, rcon=rcon) #from hedge.timestep.dumka3 import Dumka3TimeStepper #stepper = Dumka3TimeStepper(3, dtype=discr.default_scalar_type, rcon=rcon) # {{{ diagnostics setup from pytools.log import LogManager, add_general_quantities, \ add_simulation_quantities, add_run_info if write_output: log_file_name = "maxwell-%d.dat" % order else: log_file_name = None logmgr = LogManager(log_file_name, "w", rcon.communicator) add_run_info(logmgr) add_general_quantities(logmgr) add_simulation_quantities(logmgr) discr.add_instrumentation(logmgr) stepper.add_instrumentation(logmgr) from pytools.log import IntervalTimer vis_timer = IntervalTimer("t_vis", "Time spent visualizing") logmgr.add_quantity(vis_timer) from hedge.log import EMFieldGetter, add_em_quantities field_getter = EMFieldGetter(discr, op, lambda: fields) add_em_quantities(logmgr, op, field_getter) logmgr.add_watches( ["step.max", "t_sim.max", ("W_field", "W_el+W_mag"), "t_step.max"]) # }}} # {{{ timestep loop rhs = op.bind(discr) final_time = 0.5e-9 try: from hedge.timestep import times_and_steps step_it = times_and_steps( final_time=final_time, logmgr=logmgr, max_dt_getter=lambda t: op.estimate_timestep( discr, stepper=stepper, t=t, fields=fields)) for step, t, dt in step_it: if step % 50 == 0 and write_output: sub_timer = vis_timer.start_sub_timer() e, h = op.split_eh(fields) visf = vis.make_file("em-%d-%04d" % (order, step)) vis.add_data(visf, [ ("e", discr.convert_volume(e, kind="numpy")), ("h", discr.convert_volume(h, kind="numpy")), ], time=t, step=step) visf.close() sub_timer.stop().submit() fields = stepper(fields, t, dt, rhs) mode.set_time(final_time) eoc_rec.add_data_point(order, discr.norm(fields - get_true_field())) finally: if write_output: vis.close() logmgr.close() discr.close() if rcon.is_head_rank: print print eoc_rec.pretty_print("P.Deg.", "L2 Error") # }}} assert eoc_rec.estimate_order_of_convergence()[0, 1] > 6