def op_template(self, w=None): from hedge.tools import count_subset fld_cnt = count_subset(self.get_eh_subset()) if w is None: from hedge.optemplate import make_sym_vector w = make_sym_vector("w", fld_cnt + 2 * self.dimensions) from hedge.tools import join_fields return join_fields(MaxwellOperator.op_template(self, w[:fld_cnt]), numpy.zeros((2 * self.dimensions, ), dtype=object)) + self.pml_local_op(w)
def op_template(self, w=None): from hedge.tools import count_subset fld_cnt = count_subset(self.get_eh_subset()) if w is None: from hedge.optemplate import make_vector_field w = make_vector_field("w", fld_cnt+2*self.dimensions) from hedge.tools import join_fields return join_fields( MaxwellOperator.op_template(self, w[:fld_cnt]), numpy.zeros((2*self.dimensions,), dtype=object) ) + self.pml_local_op(w)
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 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, *args, **kwargs): self.add_decay = kwargs.pop("add_decay", True) MaxwellOperator.__init__(self, *args, **kwargs)
def bind(self, discr, coefficients): return MaxwellOperator.bind(self, discr, sigma=coefficients.sigma, sigma_prime=coefficients.sigma_prime, tau=coefficients.tau)
def run_setup(units, casename, setup, discr, pusher, visualize=False): from hedge.timestep.runge_kutta import LSRK4TimeStepper from hedge.visualization import SiloVisualizer from hedge.models.em import MaxwellOperator vis = SiloVisualizer(discr) from pyrticle.cloud import PicMethod from pyrticle.deposition.shape import ShapeFunctionDepositor method = PicMethod(discr, units, ShapeFunctionDepositor(), pusher(), 3, 3, debug=set(["verbose_vis"])) e, h = setup.fields(discr) b = units.MU0 * h init_positions = setup.positions(0) init_velocities = setup.velocities(0) nparticles = len(init_positions) state = method.make_state() method.add_particles( state, zip( init_positions, init_velocities, nparticles * [setup.charge], nparticles * [units.EL_MASS], ), nparticles) final_time = setup.final_time() nsteps = setup.nsteps() dt = final_time / nsteps # timestepping ------------------------------------------------------------ from hedge.models.em import MaxwellOperator max_op = MaxwellOperator(epsilon=units.EPSILON0, mu=units.MU0, flux_type=1) fields = max_op.assemble_eh(e, h) from pyrticle.cloud import \ FieldToParticleRhsCalculator, \ ParticleRhsCalculator p_rhs_calculator = ParticleRhsCalculator(method, max_op) f2p_rhs_calculator = FieldToParticleRhsCalculator(method, max_op) def rhs(t, ts_state): return (p_rhs_calculator(t, lambda: fields, lambda: ts_state.state) + f2p_rhs_calculator(t, lambda: fields, lambda: ts_state.state)) stepper = LSRK4TimeStepper() t = 0 bbox = discr.mesh.bounding_box() z_period = bbox[1][2] - bbox[0][2] def check_result(): from hedge.tools import cross deriv_dt = 1e-12 dim = discr.dimensions true_x = setup.positions(t) true_v = setup.velocities(t) true_f = [(p2 - p1) / (2 * deriv_dt) for p1, p2 in zip( setup.momenta(t - deriv_dt), setup.momenta(t + deriv_dt))] state = ts_state.state from pyrticle.tools import NumberShiftableVector vis_info = state.vis_listener.particle_vis_map sim_x = state.positions sim_v = method.velocities(state) sim_f = NumberShiftableVector.unwrap(vis_info["mag_force"] + vis_info["el_force"]) sim_el_f = NumberShiftableVector.unwrap(vis_info["el_force"]) sim_mag_f = NumberShiftableVector.unwrap(vis_info["mag_force"]) local_e = setup.e() local_b = units.MU0 * setup.h() x_err = 0 v_err = 0 f_err = 0 for i in range(len(state)): #real_f = numpy.array(cross(sim_v, setup.charge*local_b)) + setup.charge*local_e my_true_x = true_x[i] my_true_x[2] = my_true_x[2] % z_period if False and i == 0: #print "particle %d" % i print "pos:", la.norm(true_x[i] - sim_x[i]) / la.norm( true_x[i]) #print "vel:", la.norm(true_v[i]-sim_v[i])/la.norm(true_v[i]) #print "force:", la.norm(true_f[i]-sim_f[i])/la.norm(true_f[i]) print "pos:", true_x[i], sim_x[i] #print "vel:", true_v[i], sim_v[i] #print "force:", true_f[i], sim_f[i] #print "forces%d:..." % i, sim_el_f[i], sim_mag_f[i] #print "acc%d:" % i, la.norm(a-sim_a) #u = numpy.vstack((v, sim_v, f, sim_f, real_f)) #print "acc%d:\n%s" % (i, u) #raw_input() def rel_err(sim, true): return la.norm(true - sim) / la.norm(true) x_err = max(x_err, rel_err(sim_x[i], my_true_x)) v_err = max(v_err, rel_err(sim_v[i], true_v[i])) f_err = max(f_err, rel_err(sim_f[i], true_f[i])) return x_err, v_err, f_err # make sure verbose-vis fields are filled from pyrticle.cloud import TimesteppablePicState ts_state = TimesteppablePicState(method, state) del state rhs(t, ts_state) errors = (0, 0, 0) for step in xrange(nsteps): if step % int(setup.nsteps() / 300) == 0: errors = tuple( max(old_err, new_err) for old_err, new_err in zip(errors, check_result())) if visualize: visf = vis.make_file("%s-%04d" % (casename, step)) method.add_to_vis(vis, visf, ts_state.state, time=t, step=step) if True: vis.add_data(visf, [ ("e", e), ("h", h), ], time=t, step=step) else: vis.add_data(visf, [], time=t, step=step) visf.close() method.upkeep(ts_state.state) ts_state = stepper(ts_state, t, dt, rhs) t += dt assert errors[0] < 2e-12, casename + "-pos" assert errors[1] < 2e-13, casename + "-vel" assert errors[2] < 2e-4, casename + "-acc" vis.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 main(write_output=True, allow_features=None): from hedge.timestep import RK4TimeStepper from hedge.mesh import make_ball_mesh, make_cylinder_mesh, make_box_mesh from hedge.visualization import \ VtkVisualizer, \ SiloVisualizer, \ get_rank_partition from math import sqrt, pi 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 dims = 3 if rcon.is_head_rank: if dims == 2: from hedge.mesh import make_rect_mesh mesh = make_rect_mesh(a=(-10.5, -1.5), b=(10.5, 1.5), max_area=0.1) elif dims == 3: from hedge.mesh import make_box_mesh mesh = make_box_mesh(a=(-10.5, -1.5, -1.5), b=(10.5, 1.5, 1.5), max_volume=0.1) if rcon.is_head_rank: mesh_data = rcon.distribute_mesh(mesh) else: mesh_data = rcon.receive_mesh() #for order in [1,2,3,4,5,6]: discr = rcon.make_discretization(mesh_data, order=3) if write_output: vis = VtkVisualizer(discr, rcon, "dipole") from analytic_solutions import DipoleFarField, SphericalFieldAdapter from hedge.data import ITimeDependentGivenFunction sph_dipole = DipoleFarField( q=1, #C d=1 / 39, omega=2 * pi * 1e8, epsilon=epsilon0, mu=mu0, ) cart_dipole = SphericalFieldAdapter(sph_dipole) class PointDipoleSource(ITimeDependentGivenFunction): def __init__(self): from pyrticle.tools import CInfinityShapeFunction sf = CInfinityShapeFunction(0.1 * sph_dipole.wavelength, discr.dimensions) self.num_sf = discr.interpolate_volume_function( lambda x, el: sf(x)) self.vol_0 = discr.volume_zeros() def volume_interpolant(self, t, discr): from hedge.tools import make_obj_array return make_obj_array([ self.vol_0, self.vol_0, sph_dipole.source_modulation(t) * self.num_sf ]) from hedge.mesh import TAG_ALL, TAG_NONE if dims == 2: from hedge.models.em import TMMaxwellOperator as MaxwellOperator else: from hedge.models.em import MaxwellOperator op = MaxwellOperator( epsilon, mu, flux_type=1, pec_tag=TAG_NONE, absorb_tag=TAG_ALL, current=PointDipoleSource(), ) fields = op.assemble_eh(discr=discr) if rcon.is_head_rank: print "#elements=", len(mesh.elements) stepper = RK4TimeStepper() # diagnostics setup --------------------------------------------------- from pytools.log import LogManager, add_general_quantities, \ add_simulation_quantities, add_run_info if write_output: log_file_name = "dipole.dat" 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) from pytools.log import PushLogQuantity relerr_e_q = PushLogQuantity("relerr_e", "1", "Relative error in masked E-field") relerr_h_q = PushLogQuantity("relerr_h", "1", "Relative error in masked H-field") logmgr.add_quantity(relerr_e_q) logmgr.add_quantity(relerr_h_q) logmgr.add_watches([ "step.max", "t_sim.max", ("W_field", "W_el+W_mag"), "t_step.max", "relerr_e", "relerr_h" ]) if write_output: point_timeseries = [(open("b-x%d-vs-time.dat" % i, "w"), open("b-x%d-vs-time-true.dat" % i, "w"), discr.get_point_evaluator( numpy.array([i, 0, 0][:dims], dtype=discr.default_scalar_type))) for i in range(1, 5)] # timestep loop ------------------------------------------------------- mask = discr.interpolate_volume_function(sph_dipole.far_field_mask) def apply_mask(field): from hedge.tools import log_shape ls = log_shape(field) result = discr.volume_empty(ls) from pytools import indices_in_shape for i in indices_in_shape(ls): result[i] = mask * field[i] return result rhs = op.bind(discr) t = 0 try: from hedge.timestep import times_and_steps step_it = times_and_steps( final_time=1e-8, 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 write_output and step % 10 == 0: sub_timer = vis_timer.start_sub_timer() e, h = op.split_eh(fields) sph_dipole.set_time(t) true_e, true_h = op.split_eh( discr.interpolate_volume_function(cart_dipole)) visf = vis.make_file("dipole-%04d" % step) mask_e = apply_mask(e) mask_h = apply_mask(h) mask_true_e = apply_mask(true_e) mask_true_h = apply_mask(true_h) from pyvisfile.silo import DB_VARTYPE_VECTOR vis.add_data(visf, [("e", e), ("h", h), ("true_e", true_e), ("true_h", true_h), ("mask_e", mask_e), ("mask_h", mask_h), ("mask_true_e", mask_true_e), ("mask_true_h", mask_true_h)], time=t, step=step) visf.close() sub_timer.stop().submit() from hedge.tools import relative_error relerr_e_q.push_value( relative_error(discr.norm(mask_e - mask_true_e), discr.norm(mask_true_e))) relerr_h_q.push_value( relative_error(discr.norm(mask_h - mask_true_h), discr.norm(mask_true_h))) if write_output: for outf_num, outf_true, evaluator in point_timeseries: for outf, ev_h in zip([outf_num, outf_true], [h, true_h]): outf.write("%g\t%g\n" % (t, op.mu * evaluator(ev_h[1]))) outf.flush() fields = stepper(fields, t, dt, rhs) finally: if write_output: vis.close() logmgr.save() discr.close()
def run_setup(units, casename, setup, discr, pusher, visualize=False): from hedge.timestep.runge_kutta import LSRK4TimeStepper from hedge.visualization import SiloVisualizer from hedge.models.em import MaxwellOperator vis = SiloVisualizer(discr) from pyrticle.cloud import PicMethod from pyrticle.deposition.shape import ShapeFunctionDepositor method = PicMethod(discr, units, ShapeFunctionDepositor(), pusher(), 3, 3, debug=set(["verbose_vis"])) e, h = setup.fields(discr) b = units.MU0 * h init_positions = setup.positions(0) init_velocities = setup.velocities(0) nparticles = len(init_positions) state = method.make_state() method.add_particles(state, zip(init_positions, init_velocities, nparticles * [setup.charge], nparticles * [units.EL_MASS], ), nparticles) final_time = setup.final_time() nsteps = setup.nsteps() dt = final_time/nsteps # timestepping ------------------------------------------------------------ from hedge.models.em import MaxwellOperator max_op = MaxwellOperator( epsilon=units.EPSILON0, mu=units.MU0, flux_type=1) fields = max_op.assemble_eh(e, h) from pyrticle.cloud import \ FieldToParticleRhsCalculator, \ ParticleRhsCalculator p_rhs_calculator = ParticleRhsCalculator(method, max_op) f2p_rhs_calculator = FieldToParticleRhsCalculator(method, max_op) def rhs(t, ts_state): return (p_rhs_calculator(t, lambda: fields, lambda: ts_state.state) + f2p_rhs_calculator(t, lambda: fields, lambda: ts_state.state)) stepper = LSRK4TimeStepper() t = 0 bbox = discr.mesh.bounding_box() z_period = bbox[1][2] - bbox[0][2] def check_result(): from hedge.tools import cross deriv_dt = 1e-12 dim = discr.dimensions true_x = setup.positions(t) true_v = setup.velocities(t) true_f = [(p2-p1)/(2*deriv_dt) for p1, p2 in zip(setup.momenta(t-deriv_dt), setup.momenta(t+deriv_dt))] state = ts_state.state from pyrticle.tools import NumberShiftableVector vis_info = state.vis_listener.particle_vis_map sim_x = state.positions sim_v = method.velocities(state) sim_f = NumberShiftableVector.unwrap( vis_info["mag_force"] + vis_info["el_force"]) sim_el_f = NumberShiftableVector.unwrap(vis_info["el_force"]) sim_mag_f = NumberShiftableVector.unwrap(vis_info["mag_force"]) local_e = setup.e() local_b = units.MU0 * setup.h() x_err = 0 v_err = 0 f_err = 0 for i in range(len(state)): #real_f = numpy.array(cross(sim_v, setup.charge*local_b)) + setup.charge*local_e my_true_x = true_x[i] my_true_x[2] = my_true_x[2] % z_period if False and i == 0: #print "particle %d" % i print "pos:", la.norm(true_x[i]-sim_x[i])/la.norm(true_x[i]) #print "vel:", la.norm(true_v[i]-sim_v[i])/la.norm(true_v[i]) #print "force:", la.norm(true_f[i]-sim_f[i])/la.norm(true_f[i]) print "pos:", true_x[i], sim_x[i] #print "vel:", true_v[i], sim_v[i] #print "force:", true_f[i], sim_f[i] #print "forces%d:..." % i, sim_el_f[i], sim_mag_f[i] #print "acc%d:" % i, la.norm(a-sim_a) #u = numpy.vstack((v, sim_v, f, sim_f, real_f)) #print "acc%d:\n%s" % (i, u) #raw_input() def rel_err(sim, true): return la.norm(true-sim)/la.norm(true) x_err = max(x_err, rel_err(sim_x[i], my_true_x)) v_err = max(v_err, rel_err(sim_v[i], true_v[i])) f_err = max(f_err, rel_err(sim_f[i], true_f[i])) return x_err, v_err, f_err # make sure verbose-vis fields are filled from pyrticle.cloud import TimesteppablePicState ts_state = TimesteppablePicState(method, state) del state rhs(t, ts_state) errors = (0, 0, 0) for step in xrange(nsteps): if step % int(setup.nsteps()/300) == 0: errors = tuple( max(old_err, new_err) for old_err, new_err in zip(errors, check_result())) if visualize: visf = vis.make_file("%s-%04d" % (casename, step)) method.add_to_vis(vis, visf, ts_state.state, time=t, step=step) if True: vis.add_data(visf, [ ("e", e), ("h", h), ], time=t, step=step) else: vis.add_data(visf, [], time=t, step=step) visf.close() method.upkeep(ts_state.state) ts_state = stepper(ts_state, t, dt, rhs) t += dt assert errors[0] < 2e-12, casename+"-pos" assert errors[1] < 2e-13, casename+"-vel" assert errors[2] < 2e-4, casename+"-acc" vis.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 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