def add_instrumentation(self, mgr, observer): Depositor.add_instrumentation(self, mgr, observer) # instrumentation from pytools.log import IntervalTimer, EventCounter self.element_activation_counter = EventCounter( "n_el_activations", "#Advective rec. elements activated this timestep") self.element_kill_counter = EventCounter( "n_el_kills", "#Advective rec. elements retired this timestep") self.advective_rhs_timer = IntervalTimer( "t_advective_rhs", "Time spent evaluating advective RHS") self.active_elements_log = ActiveAdvectiveElements(observer) mgr.add_quantity(self.element_activation_counter) mgr.add_quantity(self.element_kill_counter) mgr.add_quantity(self.advective_rhs_timer) mgr.add_quantity(self.active_elements_log) mgr.set_constant("el_activation_threshold", self.activation_threshold) mgr.set_constant("el_kill_threshold", self.kill_threshold) mgr.set_constant("adv_upwind_alpha", self.upwind_alpha) mgr.set_constant("filter_amp", self.filter_amp) mgr.set_constant("filter_amp", self.filter_order)
def __init__(self, order, startup_stepper=None, dtype=numpy.float64, rcon=None): self.f_history = [] from pytools import match_precision self.dtype = numpy.dtype(dtype) self.scalar_dtype = match_precision(numpy.dtype(numpy.float64), self.dtype) self.coefficients = numpy.asarray(make_ab_coefficients(order), dtype=self.scalar_dtype) if startup_stepper is not None: self.startup_stepper = startup_stepper else: from hedge.timestep.runge_kutta import LSRK4TimeStepper self.startup_stepper = LSRK4TimeStepper(self.dtype) from pytools.log import IntervalTimer, EventCounter timer_factory = IntervalTimer if rcon is not None: timer_factory = rcon.make_timer self.timer = timer_factory( "t_ab", "Time spent doing algebra in Adams-Bashforth") self.flop_counter = EventCounter( "n_flops_ab", "Floating point operations performed in AB")
def __init__(self, dtype=numpy.float64, rcon=None, vector_primitive_factory=None): if vector_primitive_factory is None: from hedge.vector_primitives import VectorPrimitiveFactory self.vector_primitive_factory = VectorPrimitiveFactory() else: self.vector_primitive_factory = vector_primitive_factory from pytools.log import IntervalTimer, EventCounter timer_factory = IntervalTimer if rcon is not None: timer_factory = rcon.make_timer self.timer = timer_factory("t_rk4", "Time spent doing algebra in RK4") self.flop_counter = EventCounter( "n_flops_rk4", "Floating point operations performed in RK4") from pytools import match_precision self.dtype = numpy.dtype(dtype) self.scalar_dtype = match_precision(numpy.dtype(numpy.float64), self.dtype) self.coeffs = numpy.array([self._RK4A, self._RK4B, self._RK4C], dtype=self.scalar_dtype).T
def __init__(self, order, startup_stepper=None, dtype=numpy.float64, rcon=None): self.f_history = [] from pytools import match_precision self.dtype = numpy.dtype(dtype) self.scalar_dtype = match_precision( numpy.dtype(numpy.float64), self.dtype) self.coefficients = numpy.asarray(make_ab_coefficients(order), dtype=self.scalar_dtype) if startup_stepper is not None: self.startup_stepper = startup_stepper else: from hedge.timestep.runge_kutta import LSRK4TimeStepper self.startup_stepper = LSRK4TimeStepper(self.dtype) from pytools.log import IntervalTimer, EventCounter timer_factory = IntervalTimer if rcon is not None: timer_factory = rcon.make_timer self.timer = timer_factory( "t_ab", "Time spent doing algebra in Adams-Bashforth") self.flop_counter = EventCounter( "n_flops_ab", "Floating point operations performed in AB")
def add_instrumentation(self, mgr, observer): mgr.set_constant("depositor", self.__class__.__name__) for key, value in self.log_constants.iteritems(): mgr.set_constant(key, value) from pytools.log import IntervalTimer, EventCounter,\ time_and_count_function self.deposit_timer = IntervalTimer("t_deposit", "Time spent depositing") self.deposit_counter = EventCounter("n_deposit", "Number of depositions") self.deposit_densities = time_and_count_function( self.deposit_densites, self.deposit_timer, self.deposit_counter, 1 + self.method.dimensions_velocity) self.deposit_j = time_and_count_function( self.deposit_j, self.deposit_timer, self.deposit_counter, self.method.dimensions_velocity) self.deposit_rho = time_and_count_function(self.deposit_rho, self.deposit_timer, self.deposit_counter) mgr.add_quantity(self.deposit_timer) mgr.add_quantity(self.deposit_counter)
def add_instrumentation(self, mgr): self.subdiscr.add_instrumentation(mgr) from pytools.log import EventCounter self.comm_flux_counter = EventCounter( "n_comm_flux", "Number of inner flux communication runs") mgr.add_quantity(self.comm_flux_counter)
def __init__(self, discr, units, depositor, pusher, dimensions_pos, dimensions_velocity, debug=set()): self.units = units self.discretization = discr self.debug = debug self.depositor = depositor self.pusher = pusher self.dimensions_mesh = discr.dimensions self.dimensions_pos = dimensions_pos self.dimensions_velocity = dimensions_velocity dims = (dimensions_pos, dimensions_velocity) self.mesh_data = _internal.MeshData(discr.dimensions) self.mesh_data.fill_from_hedge(discr) # subsystem init self.depositor.initialize(self) self.pusher.initialize(self) # instrumentation from pytools.log import IntervalTimer, EventCounter self.find_el_timer = IntervalTimer( "t_find", "Time spent finding new elements") self.find_same_counter = EventCounter( "n_find_same", "#Particles found in same element") self.find_by_neighbor_counter = EventCounter( "n_find_neighbor", "#Particles found through neighbor") self.find_by_vertex_counter = EventCounter( "n_find_by_vertex", "#Particles found by vertex") self.find_global_counter = EventCounter( "n_find_global", "#Particles found by global search")
def __init__(self, use_high_order=True, dtype=numpy.float64, rcon=None, vector_primitive_factory=None, atol=0, rtol=0, max_dt_growth=5, min_dt_shrinkage=0.1, limiter=None): if vector_primitive_factory is None: from hedge.vector_primitives import VectorPrimitiveFactory self.vector_primitive_factory = VectorPrimitiveFactory() else: self.vector_primitive_factory = vector_primitive_factory from pytools.log import IntervalTimer, EventCounter timer_factory = IntervalTimer if rcon is not None: timer_factory = rcon.make_timer if limiter is None: self.limiter = lambda x: x else: self.limiter = limiter self.timer = timer_factory("t_rk", "Time spent doing algebra in Runge-Kutta") self.flop_counter = EventCounter( "n_flops_rk", "Floating point operations performed in Runge-Kutta") self.use_high_order = use_high_order self.dtype = numpy.dtype(dtype) self.adaptive = bool(atol or rtol) self.atol = atol self.rtol = rtol from pytools import match_precision self.scalar_dtype = match_precision(numpy.dtype(numpy.float64), self.dtype) self.max_dt_growth = max_dt_growth self.min_dt_shrinkage = min_dt_shrinkage self.linear_combiner_cache = {}
def __init__(self, discr, units, depositor, pusher, dimensions_pos, dimensions_velocity, debug=set()): self.units = units self.discretization = discr self.debug = debug self.depositor = depositor self.pusher = pusher self.dimensions_mesh = discr.dimensions self.dimensions_pos = dimensions_pos self.dimensions_velocity = dimensions_velocity dims = (dimensions_pos, dimensions_velocity) self.mesh_data = _internal.MeshData(discr.dimensions) self.mesh_data.fill_from_hedge(discr) # subsystem init self.depositor.initialize(self) self.pusher.initialize(self) # instrumentation from pytools.log import IntervalTimer, EventCounter self.find_el_timer = IntervalTimer("t_find", "Time spent finding new elements") self.find_same_counter = EventCounter( "n_find_same", "#Particles found in same element") self.find_by_neighbor_counter = EventCounter( "n_find_neighbor", "#Particles found through neighbor") self.find_by_vertex_counter = EventCounter( "n_find_by_vertex", "#Particles found by vertex") self.find_global_counter = EventCounter( "n_find_global", "#Particles found by global search")
def __init__(self, dtype=numpy.float64, rcon=None, vector_primitive_factory=None): if vector_primitive_factory is None: from hedge.vector_primitives import VectorPrimitiveFactory self.vector_primitive_factory = VectorPrimitiveFactory() else: self.vector_primitive_factory = vector_primitive_factory from pytools.log import IntervalTimer, EventCounter timer_factory = IntervalTimer if rcon is not None: timer_factory = rcon.make_timer self.timer = timer_factory( "t_rk4", "Time spent doing algebra in RK4") self.flop_counter = EventCounter( "n_flops_rk4", "Floating point operations performed in RK4") from pytools import match_precision self.dtype = numpy.dtype(dtype) self.scalar_dtype = match_precision( numpy.dtype(numpy.float64), self.dtype) self.coeffs = numpy.array([self._RK4A, self._RK4B, self._RK4C], dtype=self.scalar_dtype).T
class AdamsBashforthTimeStepper(TimeStepper): dt_fudge_factor = 0.95 def __init__(self, order, startup_stepper=None, dtype=numpy.float64, rcon=None): self.f_history = [] from pytools import match_precision self.dtype = numpy.dtype(dtype) self.scalar_dtype = match_precision( numpy.dtype(numpy.float64), self.dtype) self.coefficients = numpy.asarray(make_ab_coefficients(order), dtype=self.scalar_dtype) if startup_stepper is not None: self.startup_stepper = startup_stepper else: from hedge.timestep.runge_kutta import LSRK4TimeStepper self.startup_stepper = LSRK4TimeStepper(self.dtype) from pytools.log import IntervalTimer, EventCounter timer_factory = IntervalTimer if rcon is not None: timer_factory = rcon.make_timer self.timer = timer_factory( "t_ab", "Time spent doing algebra in Adams-Bashforth") self.flop_counter = EventCounter( "n_flops_ab", "Floating point operations performed in AB") @property def order(self): return len(self.coefficients) def get_stability_relevant_init_args(self): return (self.order,) def add_instrumentation(self, logmgr): logmgr.add_quantity(self.timer) logmgr.add_quantity(self.flop_counter) def __getinitargs__(self): return (self.order, self.startup_stepper) def __call__(self, y, t, dt, rhs): if len(self.f_history) == 0: # insert IC self.f_history.append(rhs(t, y)) from hedge.tools import count_dofs self.dof_count = count_dofs(self.f_history[0]) if len(self.f_history) < len(self.coefficients): ynew = self.startup_stepper(y, t, dt, rhs) if len(self.f_history) == len(self.coefficients) - 1: # here's some memory we won't need any more del self.startup_stepper else: from operator import add sub_timer = self.timer.start_sub_timer() assert len(self.coefficients) == len(self.f_history) ynew = y + dt * reduce(add, (coeff * f for coeff, f in zip(self.coefficients, self.f_history))) self.f_history.pop() sub_timer.stop().submit() self.flop_counter.add((2+2*len(self.coefficients)-1)*self.dof_count) self.f_history.insert(0, rhs(t+dt, ynew)) return ynew
class PicMethod(object): """ @arg debug: A set of strings telling what to debug. So far, the following debug flags are in use: - depositor: Debug the depositor. - verbose_vis: Generate E and B fields and force visualizations at particle locations. - ic: Check the initial condition when it's generated. - no_ic: Start with zero fields. - discretization: (See driver.py.) Turn on debug mode for the discretization. - shape_bw: Debug the finding of the optimal shape bandwidth. - interactive: Allow debug measures that require user interaction. - vis_files: Allow debug measures that write extra visualization files. """ def __init__(self, discr, units, depositor, pusher, dimensions_pos, dimensions_velocity, debug=set()): self.units = units self.discretization = discr self.debug = debug self.depositor = depositor self.pusher = pusher self.dimensions_mesh = discr.dimensions self.dimensions_pos = dimensions_pos self.dimensions_velocity = dimensions_velocity dims = (dimensions_pos, dimensions_velocity) self.mesh_data = _internal.MeshData(discr.dimensions) self.mesh_data.fill_from_hedge(discr) # subsystem init self.depositor.initialize(self) self.pusher.initialize(self) # instrumentation from pytools.log import IntervalTimer, EventCounter self.find_el_timer = IntervalTimer("t_find", "Time spent finding new elements") self.find_same_counter = EventCounter( "n_find_same", "#Particles found in same element") self.find_by_neighbor_counter = EventCounter( "n_find_neighbor", "#Particles found through neighbor") self.find_by_vertex_counter = EventCounter( "n_find_by_vertex", "#Particles found by vertex") self.find_global_counter = EventCounter( "n_find_global", "#Particles found by global search") def make_state(self): state = PicState(self) state.particle_number_shift_signaller.subscribe_with_state( self.depositor) state.particle_number_shift_signaller.subscribe_with_state(self.pusher) return state def get_dimensionality_suffix(self): return "%dd%dv" % (self.dimensions_pos, self.dimensions_velocity) def get_shape_function_class(self): from pyrticle.tools import \ PolynomialShapeFunction, \ CInfinityShapeFunction from pyrticle._internal import get_shape_function_name name = get_shape_function_name() if name == "c_infinity": return CInfinityShapeFunction elif name == "polynomial": return PolynomialShapeFunction else: raise ValueError, "unknown shape function class" def set_ignore_core_warnings(self, ignore): from pyrticle.tools import WarningForwarder, WarningIgnorer import pyrticle.tools del pyrticle.tools.warning_forwarder if ignore: pyrticle.tools.warning_forwarder = WarningIgnorer() else: pyrticle.tools.warning_forwarder = WarningForwarder() def add_instrumentation(self, mgr, observer): mgr.add_quantity(self.find_el_timer) mgr.add_quantity(self.find_same_counter) mgr.add_quantity(self.find_by_neighbor_counter) mgr.add_quantity(self.find_by_vertex_counter) mgr.add_quantity(self.find_global_counter) self.depositor.add_instrumentation(mgr, observer) self.pusher.add_instrumentation(mgr, observer) def velocities(self, state): try: return state.derived_quantity_cache["velocities"] except KeyError: result = _internal.get_velocities(state.particle_state, self.units.VACUUM_LIGHT_SPEED()) state.derived_quantity_cache["velocities"] = result return result def mean_beta(self, state): if len(state): return numpy.average(self.velocities(state), axis=0) \ / self.units.VACUUM_LIGHT_SPEED() else: return numpy.zeros((self.dimensions_velocity, )) def add_particles(self, state, iterable, maxcount=None): """Add the particles from C{iterable} to the cloud. C{iterable} is expected to yield tuples C{(position, velocity, charge, mass)}. If C{maxcount} is specified, maximally C{maxcount} particles are obtained from the iterable. """ pstate = state.particle_state if maxcount is not None: if pstate.particle_count + maxcount >= len( pstate.containing_elements): state.resize(pstate.particle_count + maxcount) for pos, vel, charge, mass in iterable: if maxcount is not None: if maxcount == 0: break maxcount -= 1 assert len(pos) == self.dimensions_pos assert len(vel) == self.dimensions_velocity pos = numpy.asarray(pos) vel = numpy.asarray(vel) mom = mass * self.units.gamma_from_v(vel) * vel cont_el = self.mesh_data.find_containing_element(pos) if cont_el == MeshData.INVALID_ELEMENT: print "not in valid element" continue if pstate.particle_count >= len(pstate.containing_elements): state.resize(max(128, 2 * pstate.particle_count)) pstate.containing_elements[pstate.particle_count] = cont_el pstate.positions[pstate.particle_count] = pos pstate.momenta[pstate.particle_count] = mom pstate.charges[pstate.particle_count] = charge pstate.masses[pstate.particle_count] = mass pstate.particle_count += 1 self.check_containment(state) state.particle_number_shift_signaller.note_change_size( pstate.particle_count) state.derived_quantity_cache.clear() def check_containment(self, state): """Check that a containing element is known for each particle. This is a new invariant as of 1/17/08, and violations of this end up segfaulting, which we should avoid. """ assert (state.particle_state.containing_elements[:len(state)] != MeshData.INVALID_ELEMENT).all() def upkeep(self, state): """Perform any operations must fall in between timesteps, such as resampling or deleting particles. """ self.depositor.upkeep(state) self.pusher.upkeep(state) state.vis_listener.clear() # deposition ---------------------------------------------------------- def deposit_densities(self, state): """Return a tuple (charge_density, current_densities), where current_densities is an d-by-n array, where d is the number of velocity dimensions, and n is the discretization nodes. """ def all_getter(): rho, j = self.depositor.deposit_densities(state, self.velocities()) j = numpy.asarray(j.T, order="C") return rho, j return state.get_derived_quantities_from_cache( ["rho", "j"], [self.deposit_rho, self.deposit_j], all_getter) def deposit_j(self, state): """Return a the current densities as an d-by-n array, where d is the number of velocity dimensions, and n is the number of discretization nodes. """ def j_getter(): return numpy.asarray(self.depositor.deposit_j( state, self.velocities(state)).T, order="C") return state.get_derived_quantity_from_cache("j", j_getter) def deposit_rho(self, state): """Return a the charge_density as a volume vector.""" def rho_getter(): return self.depositor.deposit_rho(state) return state.get_derived_quantity_from_cache("rho", rho_getter) # time advance ------------------------------------------------------------ def advance_state(self, state, dx, dp, ddep): pstate = state.particle_state cnt = pstate.particle_count positions = pstate.positions.copy() momenta = pstate.momenta.copy() positions[:cnt] += dx momenta[:cnt] += dp new_state = PicState( self, particle_count=cnt, containing_elements=pstate.containing_elements, positions=positions, momenta=momenta, charges=pstate.charges, masses=pstate.masses, depositor_state=self.depositor.advance_state(state, ddep), pusher_state=self.pusher.advance_state(state), pnss=state.particle_number_shift_signaller, vis_listener=state.vis_listener, ) from pyrticle._internal import FindEventCounters find_counters = FindEventCounters() class BHitListener(_internal.BoundaryHitListener): def note_boundary_hit(subself, pn): _internal.kill_particle( new_state.particle_state, pn, new_state.particle_number_shift_signaller) from pyrticle._internal import update_containing_elements sub_timer = self.find_el_timer.start_sub_timer() update_containing_elements(self.mesh_data, new_state.particle_state, BHitListener(), find_counters) sub_timer.stop().submit() self.find_same_counter.transfer(find_counters.find_same) self.find_by_neighbor_counter.transfer(find_counters.find_by_neighbor) self.find_by_vertex_counter.transfer(find_counters.find_by_vertex) self.find_global_counter.transfer(find_counters.find_global) return new_state # visualization ----------------------------------------------------------- def get_mesh_vis_vars(self): return self.vis_listener.mesh_vis_map.items() def add_to_vis(self, visualizer, vis_file, state, time=None, step=None, beamaxis=None, vis_listener=None): from hedge.visualization import VtkVisualizer, SiloVisualizer if isinstance(visualizer, VtkVisualizer): return self._add_to_vtk(visualizer, vis_file, state, time, step) elif isinstance(visualizer, SiloVisualizer): return self._add_to_silo(visualizer, vis_file, state, time, step, beamaxis, vis_listener) else: raise ValueError, "unknown visualizer type `%s'" % type(visualizer) def _add_to_silo(self, visualizer, db, state, time, step, beamaxis, vis_listener=None): from pylo import DBOPT_DTIME, DBOPT_CYCLE optlist = {} if time is not None: optlist[DBOPT_DTIME] = time if step is not None: optlist[DBOPT_CYCLE] = step pcount = len(state) if pcount: # real-space ------------------------------------------------------ db.put_pointmesh("particles", numpy.asarray(state.positions.T, order="C"), optlist) db.put_pointvar1("charge", "particles", state.charges) db.put_pointvar1("mass", "particles", state.masses) db.put_pointvar("momentum", "particles", numpy.asarray(state.momenta.T, order="C")) db.put_pointvar("velocity", "particles", numpy.asarray(self.velocities(state).T, order="C")) if vis_listener is not None: for name, value in self.vis_listener.particle_vis_map.iteritems( ): from pyrticle.tools import NumberShiftableVector value = NumberShiftableVector.unwrap(value) dim, remainder = divmod(len(value), pcount) assert remainder == 0, ( "particle vis value '%s' had invalid number of entries: " "%d (#particles=%d)" % (name, len(value), pcount)) if dim == 1: db.put_pointvar1(name, "particles", value) else: db.put_pointvar(name, "particles", [value[i::dim] for i in range(dim)]) # phase-space ----------------------------------------------------- axes_names = ["x", "y", "z"] if beamaxis is not None: for axis in range( min(self.dimensions_pos, self.dimensions_velocity)): if axis == beamaxis: continue axname = axes_names[axis] db.put_defvars("phasespace_%s" % axname, [ ("part_%s" % axname, "coord(particles)[%d]" % axis), ("part_%s_prime" % axname, "momentum[%d]/momentum[%d]" % (axis, beamaxis)), ("part_%s_momentum" % axname, "momentum[%d]" % (axis)), ])
class PicMethod(object): """ @arg debug: A set of strings telling what to debug. So far, the following debug flags are in use: - depositor: Debug the depositor. - verbose_vis: Generate E and B fields and force visualizations at particle locations. - ic: Check the initial condition when it's generated. - no_ic: Start with zero fields. - discretization: (See driver.py.) Turn on debug mode for the discretization. - shape_bw: Debug the finding of the optimal shape bandwidth. - interactive: Allow debug measures that require user interaction. - vis_files: Allow debug measures that write extra visualization files. """ def __init__(self, discr, units, depositor, pusher, dimensions_pos, dimensions_velocity, debug=set()): self.units = units self.discretization = discr self.debug = debug self.depositor = depositor self.pusher = pusher self.dimensions_mesh = discr.dimensions self.dimensions_pos = dimensions_pos self.dimensions_velocity = dimensions_velocity dims = (dimensions_pos, dimensions_velocity) self.mesh_data = _internal.MeshData(discr.dimensions) self.mesh_data.fill_from_hedge(discr) # subsystem init self.depositor.initialize(self) self.pusher.initialize(self) # instrumentation from pytools.log import IntervalTimer, EventCounter self.find_el_timer = IntervalTimer( "t_find", "Time spent finding new elements") self.find_same_counter = EventCounter( "n_find_same", "#Particles found in same element") self.find_by_neighbor_counter = EventCounter( "n_find_neighbor", "#Particles found through neighbor") self.find_by_vertex_counter = EventCounter( "n_find_by_vertex", "#Particles found by vertex") self.find_global_counter = EventCounter( "n_find_global", "#Particles found by global search") def make_state(self): state = PicState(self) state.particle_number_shift_signaller.subscribe_with_state(self.depositor) state.particle_number_shift_signaller.subscribe_with_state(self.pusher) return state def get_dimensionality_suffix(self): return "%dd%dv" % (self.dimensions_pos, self.dimensions_velocity) def get_shape_function_class(self): from pyrticle.tools import \ PolynomialShapeFunction, \ CInfinityShapeFunction from pyrticle._internal import get_shape_function_name name = get_shape_function_name() if name == "c_infinity": return CInfinityShapeFunction elif name == "polynomial": return PolynomialShapeFunction else: raise ValueError, "unknown shape function class" def set_ignore_core_warnings(self, ignore): from pyrticle.tools import WarningForwarder, WarningIgnorer import pyrticle.tools del pyrticle.tools.warning_forwarder if ignore: pyrticle.tools.warning_forwarder = WarningIgnorer() else: pyrticle.tools.warning_forwarder = WarningForwarder() def add_instrumentation(self, mgr, observer): mgr.add_quantity(self.find_el_timer) mgr.add_quantity(self.find_same_counter) mgr.add_quantity(self.find_by_neighbor_counter) mgr.add_quantity(self.find_by_vertex_counter) mgr.add_quantity(self.find_global_counter) self.depositor.add_instrumentation(mgr, observer) self.pusher.add_instrumentation(mgr, observer) def velocities(self, state): try: return state.derived_quantity_cache["velocities"] except KeyError: result = _internal.get_velocities( state.particle_state, self.units.VACUUM_LIGHT_SPEED()) state.derived_quantity_cache["velocities"] = result return result def mean_beta(self, state): if len(state): return numpy.average(self.velocities(state), axis=0) \ / self.units.VACUUM_LIGHT_SPEED() else: return numpy.zeros((self.dimensions_velocity,)) def add_particles(self, state, iterable, maxcount=None): """Add the particles from C{iterable} to the cloud. C{iterable} is expected to yield tuples C{(position, velocity, charge, mass)}. If C{maxcount} is specified, maximally C{maxcount} particles are obtained from the iterable. """ pstate = state.particle_state if maxcount is not None: if pstate.particle_count+maxcount >= len(pstate.containing_elements): state.resize(pstate.particle_count+maxcount) for pos, vel, charge, mass in iterable: if maxcount is not None: if maxcount == 0: break maxcount -= 1 assert len(pos) == self.dimensions_pos assert len(vel) == self.dimensions_velocity pos = numpy.asarray(pos) vel = numpy.asarray(vel) mom = mass*self.units.gamma_from_v(vel)*vel cont_el = self.mesh_data.find_containing_element(pos) if cont_el == MeshData.INVALID_ELEMENT: print "not in valid element" continue if pstate.particle_count >= len(pstate.containing_elements): state.resize(max(128, 2*pstate.particle_count)) pstate.containing_elements[pstate.particle_count] = cont_el pstate.positions[pstate.particle_count] = pos pstate.momenta[pstate.particle_count] = mom pstate.charges[pstate.particle_count] = charge pstate.masses[pstate.particle_count] = mass pstate.particle_count += 1 self.check_containment(state) state.particle_number_shift_signaller.note_change_size( pstate.particle_count) state.derived_quantity_cache.clear() def check_containment(self, state): """Check that a containing element is known for each particle. This is a new invariant as of 1/17/08, and violations of this end up segfaulting, which we should avoid. """ assert (state.particle_state.containing_elements[:len(state)] != MeshData.INVALID_ELEMENT).all() def upkeep(self, state): """Perform any operations must fall in between timesteps, such as resampling or deleting particles. """ self.depositor.upkeep(state) self.pusher.upkeep(state) state.vis_listener.clear() # deposition ---------------------------------------------------------- def deposit_densities(self, state): """Return a tuple (charge_density, current_densities), where current_densities is an d-by-n array, where d is the number of velocity dimensions, and n is the discretization nodes. """ def all_getter(): rho, j = self.depositor.deposit_densities(state, self.velocities()) j = numpy.asarray(j.T, order="C") return rho, j return state.get_derived_quantities_from_cache( ["rho", "j"], [self.deposit_rho, self.deposit_j], all_getter) def deposit_j(self, state): """Return a the current densities as an d-by-n array, where d is the number of velocity dimensions, and n is the number of discretization nodes. """ def j_getter(): return numpy.asarray( self.depositor.deposit_j( state, self.velocities(state)) .T, order="C") return state.get_derived_quantity_from_cache("j", j_getter) def deposit_rho(self, state): """Return a the charge_density as a volume vector.""" def rho_getter(): return self.depositor.deposit_rho(state) return state.get_derived_quantity_from_cache("rho", rho_getter) # time advance ------------------------------------------------------------ def advance_state(self, state, dx, dp, ddep): pstate = state.particle_state cnt = pstate.particle_count positions = pstate.positions.copy() momenta = pstate.momenta.copy() positions[:cnt] += dx momenta[:cnt] += dp new_state = PicState( self, particle_count=cnt, containing_elements=pstate.containing_elements, positions=positions, momenta=momenta, charges=pstate.charges, masses=pstate.masses, depositor_state=self.depositor.advance_state( state, ddep), pusher_state=self.pusher.advance_state(state), pnss=state.particle_number_shift_signaller, vis_listener=state.vis_listener, ) from pyrticle._internal import FindEventCounters find_counters = FindEventCounters() class BHitListener(_internal.BoundaryHitListener): def note_boundary_hit(subself, pn): _internal.kill_particle( new_state.particle_state, pn, new_state.particle_number_shift_signaller) from pyrticle._internal import update_containing_elements sub_timer = self.find_el_timer.start_sub_timer() update_containing_elements( self.mesh_data, new_state.particle_state, BHitListener(), find_counters) sub_timer.stop().submit() self.find_same_counter.transfer( find_counters.find_same) self.find_by_neighbor_counter.transfer( find_counters.find_by_neighbor) self.find_by_vertex_counter.transfer( find_counters.find_by_vertex) self.find_global_counter.transfer( find_counters.find_global) return new_state # visualization ----------------------------------------------------------- def get_mesh_vis_vars(self): return self.vis_listener.mesh_vis_map.items() def add_to_vis(self, visualizer, vis_file, state, time=None, step=None, beamaxis=None, vis_listener=None): from hedge.visualization import VtkVisualizer, SiloVisualizer if isinstance(visualizer, VtkVisualizer): return self._add_to_vtk(visualizer, vis_file, state, time, step) elif isinstance(visualizer, SiloVisualizer): return self._add_to_silo(visualizer, vis_file, state, time, step, beamaxis, vis_listener) else: raise ValueError, "unknown visualizer type `%s'" % type(visualizer) def _add_to_silo(self, visualizer, db, state, time, step, beamaxis, vis_listener=None): from pylo import DBOPT_DTIME, DBOPT_CYCLE optlist = {} if time is not None: optlist[DBOPT_DTIME] = time if step is not None: optlist[DBOPT_CYCLE] = step pcount = len(state) if pcount: # real-space ------------------------------------------------------ db.put_pointmesh("particles", numpy.asarray(state.positions.T, order="C"), optlist) db.put_pointvar1("charge", "particles", state.charges) db.put_pointvar1("mass", "particles", state.masses) db.put_pointvar("momentum", "particles", numpy.asarray(state.momenta.T, order="C")) db.put_pointvar("velocity", "particles", numpy.asarray(self.velocities(state).T, order="C")) if vis_listener is not None: for name, value in self.vis_listener.particle_vis_map.iteritems(): from pyrticle.tools import NumberShiftableVector value = NumberShiftableVector.unwrap(value) dim, remainder = divmod(len(value), pcount) assert remainder == 0, ( "particle vis value '%s' had invalid number of entries: " "%d (#particles=%d)" % (name, len(value), pcount)) if dim == 1: db.put_pointvar1(name, "particles", value) else: db.put_pointvar(name, "particles", [value[i::dim] for i in range(dim)]) # phase-space ----------------------------------------------------- axes_names = ["x", "y", "z"] if beamaxis is not None: for axis in range(min(self.dimensions_pos, self.dimensions_velocity)): if axis == beamaxis: continue axname = axes_names[axis] db.put_defvars("phasespace_%s" % axname, [ ("part_%s" % axname, "coord(particles)[%d]" % axis), ("part_%s_prime" % axname, "momentum[%d]/momentum[%d]" % (axis, beamaxis)), ("part_%s_momentum" % axname, "momentum[%d]" % (axis)), ])
class LSRK4TimeStepper(TimeStepper): """A low storage fourth-order Runge-Kutta method See JSH, TW: Nodal Discontinuous Galerkin Methods p.64 or Carpenter, M.H., and Kennedy, C.A., Fourth-order-2N-storage Runge-Kutta schemes, NASA Langley Tech Report TM 109112, 1994 """ _RK4A = [0.0, -567301805773 /1357537059087, -2404267990393/2016746695238, -3550918686646/2091501179385, -1275806237668/ 842570457699, ] _RK4B = [1432997174477/ 9575080441755, 5161836677717 /13612068292357, 1720146321549 / 2090206949498, 3134564353537 / 4481467310338, 2277821191437 /14882151754819, ] _RK4C = [0.0, 1432997174477/9575080441755, 2526269341429/6820363962896, 2006345519317/3224310063776, 2802321613138/2924317926251, #1, ] dt_fudge_factor = 1 adaptive = False def __init__(self, dtype=numpy.float64, rcon=None, vector_primitive_factory=None): if vector_primitive_factory is None: from hedge.vector_primitives import VectorPrimitiveFactory self.vector_primitive_factory = VectorPrimitiveFactory() else: self.vector_primitive_factory = vector_primitive_factory from pytools.log import IntervalTimer, EventCounter timer_factory = IntervalTimer if rcon is not None: timer_factory = rcon.make_timer self.timer = timer_factory( "t_rk4", "Time spent doing algebra in RK4") self.flop_counter = EventCounter( "n_flops_rk4", "Floating point operations performed in RK4") from pytools import match_precision self.dtype = numpy.dtype(dtype) self.scalar_dtype = match_precision( numpy.dtype(numpy.float64), self.dtype) self.coeffs = numpy.array([self._RK4A, self._RK4B, self._RK4C], dtype=self.scalar_dtype).T def get_stability_relevant_init_args(self): return () def add_instrumentation(self, logmgr): logmgr.add_quantity(self.timer) logmgr.add_quantity(self.flop_counter) def __call__(self, y, t, dt, rhs): try: self.residual except AttributeError: self.residual = 0*rhs(t, y) from hedge.tools import count_dofs self.dof_count = count_dofs(self.residual) self.linear_combiner = self.vector_primitive_factory\ .make_linear_combiner(self.dtype, self.scalar_dtype, y, arg_count=2) lc = self.linear_combiner for a, b, c in self.coeffs: this_rhs = rhs(t + c*dt, y) sub_timer = self.timer.start_sub_timer() self.residual = lc((a, self.residual), (dt, this_rhs)) del this_rhs y = lc((1, y), (b, self.residual)) sub_timer.stop().submit() # 5 is the number of flops above, *NOT* the number of stages, # which is already captured in len(self.coeffs) self.flop_counter.add(len(self.coeffs)*self.dof_count*5) return y
class AdamsBashforthTimeStepper(TimeStepper): dt_fudge_factor = 0.95 def __init__(self, order, startup_stepper=None, dtype=numpy.float64, rcon=None): self.f_history = [] from pytools import match_precision self.dtype = numpy.dtype(dtype) self.scalar_dtype = match_precision(numpy.dtype(numpy.float64), self.dtype) self.coefficients = numpy.asarray(make_ab_coefficients(order), dtype=self.scalar_dtype) if startup_stepper is not None: self.startup_stepper = startup_stepper else: from hedge.timestep.runge_kutta import LSRK4TimeStepper self.startup_stepper = LSRK4TimeStepper(self.dtype) from pytools.log import IntervalTimer, EventCounter timer_factory = IntervalTimer if rcon is not None: timer_factory = rcon.make_timer self.timer = timer_factory( "t_ab", "Time spent doing algebra in Adams-Bashforth") self.flop_counter = EventCounter( "n_flops_ab", "Floating point operations performed in AB") @property def order(self): return len(self.coefficients) def get_stability_relevant_init_args(self): return (self.order, ) def add_instrumentation(self, logmgr): logmgr.add_quantity(self.timer) logmgr.add_quantity(self.flop_counter) def __getinitargs__(self): return (self.order, self.startup_stepper) def __call__(self, y, t, dt, rhs): if len(self.f_history) == 0: # insert IC self.f_history.append(rhs(t, y)) from hedge.tools import count_dofs self.dof_count = count_dofs(self.f_history[0]) if len(self.f_history) < len(self.coefficients): ynew = self.startup_stepper(y, t, dt, rhs) if len(self.f_history) == len(self.coefficients) - 1: # here's some memory we won't need any more del self.startup_stepper else: from operator import add sub_timer = self.timer.start_sub_timer() assert len(self.coefficients) == len(self.f_history) ynew = y + dt * reduce( add, (coeff * f for coeff, f in zip(self.coefficients, self.f_history))) self.f_history.pop() sub_timer.stop().submit() self.flop_counter.add( (2 + 2 * len(self.coefficients) - 1) * self.dof_count) self.f_history.insert(0, rhs(t + dt, ynew)) return ynew
def simple_wave_entrypoint(dim=2, num_elems=256, order=4, num_steps=30, log_filename="grudge.dat"): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) from mpi4py import MPI comm = MPI.COMM_WORLD num_parts = comm.Get_size() n = int(num_elems**(1. / dim)) from meshmode.distributed import MPIMeshDistributor mesh_dist = MPIMeshDistributor(comm) if mesh_dist.is_mananger_rank(): from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim, b=(0.5, ) * dim, n=(n, ) * dim) from pymetis import part_graph _, p = part_graph(num_parts, xadj=mesh.nodal_adjacency.neighbors_starts.tolist(), adjncy=mesh.nodal_adjacency.neighbors.tolist()) part_per_element = np.array(p) local_mesh = mesh_dist.send_mesh_parts(mesh, part_per_element, num_parts) else: local_mesh = mesh_dist.receive_mesh_part() vol_discr = DGDiscretizationWithBoundaries(cl_ctx, local_mesh, order=order, mpi_communicator=comm) source_center = np.array([0.1, 0.22, 0.33])[:local_mesh.dim] source_width = 0.05 source_omega = 3 sym_x = sym.nodes(local_mesh.dim) sym_source_center_dist = sym_x - source_center sym_t = sym.ScalarVariable("t") from grudge.models.wave import StrongWaveOperator from meshmode.mesh import BTAG_ALL, BTAG_NONE op = StrongWaveOperator( -0.1, vol_discr.dim, source_f=( sym.sin(source_omega * sym_t) * sym.exp(-np.dot(sym_source_center_dist, sym_source_center_dist) / source_width**2)), dirichlet_tag=BTAG_NONE, neumann_tag=BTAG_NONE, radiation_tag=BTAG_ALL, flux_type="upwind") from pytools.obj_array import join_fields fields = join_fields( vol_discr.zeros(queue), [vol_discr.zeros(queue) for i in range(vol_discr.dim)]) from pytools.log import LogManager, \ add_general_quantities, \ add_run_info, \ IntervalTimer, EventCounter # NOTE: LogManager hangs when using a file on a shared directory. logmgr = LogManager(log_filename, "w", comm) add_run_info(logmgr) add_general_quantities(logmgr) log_quantities =\ {"rank_data_swap_timer": IntervalTimer("rank_data_swap_timer", "Time spent evaluating RankDataSwapAssign"), "rank_data_swap_counter": EventCounter("rank_data_swap_counter", "Number of RankDataSwapAssign instructions evaluated"), "exec_timer": IntervalTimer("exec_timer", "Total time spent executing instructions"), "insn_eval_timer": IntervalTimer("insn_eval_timer", "Time spend evaluating instructions"), "future_eval_timer": IntervalTimer("future_eval_timer", "Time spent evaluating futures"), "busy_wait_timer": IntervalTimer("busy_wait_timer", "Time wasted doing busy wait")} for quantity in log_quantities.values(): logmgr.add_quantity(quantity) bound_op = bind(vol_discr, op.sym_operator()) def rhs(t, w): val, rhs.profile_data = bound_op(queue, profile_data=rhs.profile_data, log_quantities=log_quantities, t=t, w=w) return val rhs.profile_data = {} dt = 0.04 dt_stepper = set_up_rk4("w", dt, fields, rhs) logmgr.tick_before() for event in dt_stepper.run(t_end=dt * num_steps): if isinstance(event, dt_stepper.StateComputed): logmgr.tick_after() logmgr.tick_before() logmgr.tick_after() def print_profile_data(data): print("""execute() for rank %d: \tInstruction Evaluation: %f%% \tFuture Evaluation: %f%% \tBusy Wait: %f%% \tTotal: %f seconds""" % (comm.Get_rank(), data['insn_eval_time'] / data['total_time'] * 100, data['future_eval_time'] / data['total_time'] * 100, data['busy_wait_time'] / data['total_time'] * 100, data['total_time'])) print_profile_data(rhs.profile_data) logmgr.close()
class LSRK4TimeStepper(TimeStepper): """A low storage fourth-order Runge-Kutta method See JSH, TW: Nodal Discontinuous Galerkin Methods p.64 or Carpenter, M.H., and Kennedy, C.A., Fourth-order-2N-storage Runge-Kutta schemes, NASA Langley Tech Report TM 109112, 1994 """ _RK4A = [ 0.0, -567301805773 / 1357537059087, -2404267990393 / 2016746695238, -3550918686646 / 2091501179385, -1275806237668 / 842570457699, ] _RK4B = [ 1432997174477 / 9575080441755, 5161836677717 / 13612068292357, 1720146321549 / 2090206949498, 3134564353537 / 4481467310338, 2277821191437 / 14882151754819, ] _RK4C = [ 0.0, 1432997174477 / 9575080441755, 2526269341429 / 6820363962896, 2006345519317 / 3224310063776, 2802321613138 / 2924317926251, #1, ] dt_fudge_factor = 1 adaptive = False def __init__(self, dtype=numpy.float64, rcon=None, vector_primitive_factory=None): if vector_primitive_factory is None: from hedge.vector_primitives import VectorPrimitiveFactory self.vector_primitive_factory = VectorPrimitiveFactory() else: self.vector_primitive_factory = vector_primitive_factory from pytools.log import IntervalTimer, EventCounter timer_factory = IntervalTimer if rcon is not None: timer_factory = rcon.make_timer self.timer = timer_factory("t_rk4", "Time spent doing algebra in RK4") self.flop_counter = EventCounter( "n_flops_rk4", "Floating point operations performed in RK4") from pytools import match_precision self.dtype = numpy.dtype(dtype) self.scalar_dtype = match_precision(numpy.dtype(numpy.float64), self.dtype) self.coeffs = numpy.array([self._RK4A, self._RK4B, self._RK4C], dtype=self.scalar_dtype).T def get_stability_relevant_init_args(self): return () def add_instrumentation(self, logmgr): logmgr.add_quantity(self.timer) logmgr.add_quantity(self.flop_counter) def __call__(self, y, t, dt, rhs): try: self.residual except AttributeError: self.residual = 0 * rhs(t, y) from hedge.tools import count_dofs self.dof_count = count_dofs(self.residual) self.linear_combiner = self.vector_primitive_factory\ .make_linear_combiner(self.dtype, self.scalar_dtype, y, arg_count=2) lc = self.linear_combiner for a, b, c in self.coeffs: this_rhs = rhs(t + c * dt, y) sub_timer = self.timer.start_sub_timer() self.residual = lc((a, self.residual), (dt, this_rhs)) del this_rhs y = lc((1, y), (b, self.residual)) sub_timer.stop().submit() # 5 is the number of flops above, *NOT* the number of stages, # which is already captured in len(self.coeffs) self.flop_counter.add(len(self.coeffs) * self.dof_count * 5) return y
class AdvectiveDepositor(Depositor): name = "Advective" def __init__(self, activation_threshold=1e-5, kill_threshold=1e-3, filter_amp=None, filter_order=None, upwind_alpha=1, ): Depositor.__init__(self) self.activation_threshold = activation_threshold self.kill_threshold = kill_threshold self.upwind_alpha = upwind_alpha self.shape_function = None self.filter_amp = filter_amp self.filter_order = filter_order if filter_amp is not None: from hedge.discretization import ExponentialFilterResponseFunction self.filter_response = ExponentialFilterResponseFunction( filter_amp, filter_order) else: self.filter_response = None def initialize(self, method): Depositor.initialize(self, method) discr = method.discretization eg, = discr.element_groups fg, = discr.face_groups ldis = eg.local_discretization from hedge.mesh import TAG_ALL bdry = discr.get_boundary(TAG_ALL) bdry_fg, = bdry.face_groups if self.filter_response: from hedge.discretization import Filter filter = Filter(discr, self.filter_response) filter_mat, = filter.filter_matrices else: filter_mat = numpy.zeros((0,0)) backend_class = getattr(_internal, "AdvectiveDepositor" + method.get_dimensionality_suffix()) self.backend = backend_class(method.mesh_data, len(ldis.face_indices()), ldis.node_count(), ldis.mass_matrix(), ldis.inverse_mass_matrix(), filter_mat, ldis.face_mass_matrix(), fg, bdry_fg, self.activation_threshold, self.kill_threshold, self.upwind_alpha) for i, diffmat in enumerate(ldis.differentiation_matrices()): self.backend.add_local_diff_matrix(i, diffmat) def make_state(self, state): state = self.backend.DepositorState() from pyrticle.tools import NumberShiftMultiplexer state.rho_dof_shift_listener = NumberShiftMultiplexer( name="advective_rho_dofs") eg, = self.method.discretization.element_groups ldis = eg.local_discretization #state.resize_rho(eg.local_discretization.node_count() * 1024) return state def add_instrumentation(self, mgr, observer): Depositor.add_instrumentation(self, mgr, observer) # instrumentation from pytools.log import IntervalTimer, EventCounter self.element_activation_counter = EventCounter( "n_el_activations", "#Advective rec. elements activated this timestep") self.element_kill_counter = EventCounter( "n_el_kills", "#Advective rec. elements retired this timestep") self.advective_rhs_timer = IntervalTimer( "t_advective_rhs", "Time spent evaluating advective RHS") self.active_elements_log = ActiveAdvectiveElements(observer) mgr.add_quantity(self.element_activation_counter) mgr.add_quantity(self.element_kill_counter) mgr.add_quantity(self.advective_rhs_timer) mgr.add_quantity(self.active_elements_log) mgr.set_constant("el_activation_threshold", self.activation_threshold) mgr.set_constant("el_kill_threshold", self.kill_threshold) mgr.set_constant("adv_upwind_alpha", self.upwind_alpha) mgr.set_constant("filter_amp", self.filter_amp) mgr.set_constant("filter_amp", self.filter_order) def set_shape_function(self, state, sf): Depositor.set_shape_function(self, state, sf) state.depositor_state.clear() for pn in xrange(len(state)): self.backend.add_advective_particle( state.depositor_state, state.particle_state, sf, pn) def note_move(self, state, orig, dest, size): self.backend.note_move(state.depositor_state, orig, dest, size) def note_change_size(self, state, new_size): self.backend.note_change_size(state.depositor_state, new_size) if (self.shape_function is not None and new_size > state.depositor_state.count_advective_particles()): for pn in range( state.depositor_state.count_advective_particles(), new_size): self.backend.add_advective_particle( state.depositor_state, state.particle_state, self.shape_function, pn) def clear_particles(self): Depositor.clear_particles(self) self.cloud.pic_algorithm.clear_advective_particles() def upkeep(self, state): self.backend.perform_depositor_upkeep( state.depositor_state, state.particle_state) def rhs(self, state): from pyrticle.tools import NumberShiftableVector sub_timer = self.advective_rhs_timer.start_sub_timer() result = NumberShiftableVector( self.backend.get_advective_particle_rhs( state.depositor_state, state.particle_state, self.method.velocities(state)), signaller=state.depositor_state.rho_dof_shift_listener ) sub_timer.stop() self.element_activation_counter.transfer( state.depositor_state.element_activation_counter) self.element_kill_counter.transfer( state.depositor_state.element_kill_counter) return result def advance_state(self, state, rhs): # depositor states tend to linger on for a bit--ours here are # big, so they need to go. from gc import collect collect() from pyrticle.tools import NumberShiftableVector return self.backend.apply_advective_particle_rhs( state.depositor_state, state.particle_state, NumberShiftableVector.unwrap(rhs), state.depositor_state.rho_dof_shift_listener)
def mpi_communication_entrypoint(): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) from mpi4py import MPI comm = MPI.COMM_WORLD i_local_rank = comm.Get_rank() num_parts = comm.Get_size() from meshmode.distributed import MPIMeshDistributor, get_partition_by_pymetis mesh_dist = MPIMeshDistributor(comm) dim = 2 dt = 0.04 order = 4 if mesh_dist.is_mananger_rank(): from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim, b=(0.5, ) * dim, n=(16, ) * dim) part_per_element = get_partition_by_pymetis(mesh, num_parts) local_mesh = mesh_dist.send_mesh_parts(mesh, part_per_element, num_parts) else: local_mesh = mesh_dist.receive_mesh_part() vol_discr = DGDiscretizationWithBoundaries(cl_ctx, local_mesh, order=order, mpi_communicator=comm) source_center = np.array([0.1, 0.22, 0.33])[:local_mesh.dim] source_width = 0.05 source_omega = 3 sym_x = sym.nodes(local_mesh.dim) sym_source_center_dist = sym_x - source_center sym_t = sym.ScalarVariable("t") from grudge.models.wave import StrongWaveOperator from meshmode.mesh import BTAG_ALL, BTAG_NONE op = StrongWaveOperator( -0.1, vol_discr.dim, source_f=( sym.sin(source_omega * sym_t) * sym.exp(-np.dot(sym_source_center_dist, sym_source_center_dist) / source_width**2)), dirichlet_tag=BTAG_NONE, neumann_tag=BTAG_NONE, radiation_tag=BTAG_ALL, flux_type="upwind") from pytools.obj_array import join_fields fields = join_fields( vol_discr.zeros(queue), [vol_discr.zeros(queue) for i in range(vol_discr.dim)]) # FIXME # dt = op.estimate_rk4_timestep(vol_discr, fields=fields) # FIXME: Should meshmode consider BTAG_PARTITION to be a boundary? # Fails because: "found faces without boundary conditions" # op.check_bc_coverage(local_mesh) from pytools.log import LogManager, \ add_general_quantities, \ add_run_info, \ IntervalTimer, EventCounter log_filename = None # NOTE: LogManager hangs when using a file on a shared directory. # log_filename = 'grudge_log.dat' logmgr = LogManager(log_filename, "w", comm) add_run_info(logmgr) add_general_quantities(logmgr) log_quantities =\ {"rank_data_swap_timer": IntervalTimer("rank_data_swap_timer", "Time spent evaluating RankDataSwapAssign"), "rank_data_swap_counter": EventCounter("rank_data_swap_counter", "Number of RankDataSwapAssign instructions evaluated"), "exec_timer": IntervalTimer("exec_timer", "Total time spent executing instructions"), "insn_eval_timer": IntervalTimer("insn_eval_timer", "Time spend evaluating instructions"), "future_eval_timer": IntervalTimer("future_eval_timer", "Time spent evaluating futures"), "busy_wait_timer": IntervalTimer("busy_wait_timer", "Time wasted doing busy wait")} for quantity in log_quantities.values(): logmgr.add_quantity(quantity) # print(sym.pretty(op.sym_operator())) bound_op = bind(vol_discr, op.sym_operator()) # print(bound_op) # 1/0 def rhs(t, w): val, rhs.profile_data = bound_op(queue, profile_data=rhs.profile_data, log_quantities=log_quantities, t=t, w=w) return val rhs.profile_data = {} dt_stepper = set_up_rk4("w", dt, fields, rhs) final_t = 4 nsteps = int(final_t / dt) print("rank=%d dt=%g nsteps=%d" % (i_local_rank, dt, nsteps)) # from grudge.shortcuts import make_visualizer # vis = make_visualizer(vol_discr, vis_order=order) step = 0 norm = bind(vol_discr, sym.norm(2, sym.var("u"))) from time import time t_last_step = time() logmgr.tick_before() for event in dt_stepper.run(t_end=final_t): if isinstance(event, dt_stepper.StateComputed): assert event.component_id == "w" step += 1 print(step, event.t, norm(queue, u=event.state_component[0]), time() - t_last_step) # if step % 10 == 0: # vis.write_vtk_file("rank%d-fld-%04d.vtu" % (i_local_rank, step), # [("u", event.state_component[0]), # ("v", event.state_component[1:])]) t_last_step = time() logmgr.tick_after() logmgr.tick_before() logmgr.tick_after() def print_profile_data(data): print("""execute() for rank %d: \tInstruction Evaluation: %f%% \tFuture Evaluation: %f%% \tBusy Wait: %f%% \tTotal: %f seconds""" % (i_local_rank, data['insn_eval_time'] / data['total_time'] * 100, data['future_eval_time'] / data['total_time'] * 100, data['busy_wait_time'] / data['total_time'] * 100, data['total_time'])) print_profile_data(rhs.profile_data) logmgr.close() logger.debug("Rank %d exiting", i_local_rank)
class AdvectiveDepositor(Depositor): name = "Advective" def __init__( self, activation_threshold=1e-5, kill_threshold=1e-3, filter_amp=None, filter_order=None, upwind_alpha=1, ): Depositor.__init__(self) self.activation_threshold = activation_threshold self.kill_threshold = kill_threshold self.upwind_alpha = upwind_alpha self.shape_function = None self.filter_amp = filter_amp self.filter_order = filter_order if filter_amp is not None: from hedge.discretization import ExponentialFilterResponseFunction self.filter_response = ExponentialFilterResponseFunction( filter_amp, filter_order) else: self.filter_response = None def initialize(self, method): Depositor.initialize(self, method) discr = method.discretization eg, = discr.element_groups fg, = discr.face_groups ldis = eg.local_discretization from hedge.mesh import TAG_ALL bdry = discr.get_boundary(TAG_ALL) bdry_fg, = bdry.face_groups if self.filter_response: from hedge.discretization import Filter filter = Filter(discr, self.filter_response) filter_mat, = filter.filter_matrices else: filter_mat = numpy.zeros((0, 0)) backend_class = getattr( _internal, "AdvectiveDepositor" + method.get_dimensionality_suffix()) self.backend = backend_class(method.mesh_data, len(ldis.face_indices()), ldis.node_count(), ldis.mass_matrix(), ldis.inverse_mass_matrix(), filter_mat, ldis.face_mass_matrix(), fg, bdry_fg, self.activation_threshold, self.kill_threshold, self.upwind_alpha) for i, diffmat in enumerate(ldis.differentiation_matrices()): self.backend.add_local_diff_matrix(i, diffmat) def make_state(self, state): state = self.backend.DepositorState() from pyrticle.tools import NumberShiftMultiplexer state.rho_dof_shift_listener = NumberShiftMultiplexer( name="advective_rho_dofs") eg, = self.method.discretization.element_groups ldis = eg.local_discretization #state.resize_rho(eg.local_discretization.node_count() * 1024) return state def add_instrumentation(self, mgr, observer): Depositor.add_instrumentation(self, mgr, observer) # instrumentation from pytools.log import IntervalTimer, EventCounter self.element_activation_counter = EventCounter( "n_el_activations", "#Advective rec. elements activated this timestep") self.element_kill_counter = EventCounter( "n_el_kills", "#Advective rec. elements retired this timestep") self.advective_rhs_timer = IntervalTimer( "t_advective_rhs", "Time spent evaluating advective RHS") self.active_elements_log = ActiveAdvectiveElements(observer) mgr.add_quantity(self.element_activation_counter) mgr.add_quantity(self.element_kill_counter) mgr.add_quantity(self.advective_rhs_timer) mgr.add_quantity(self.active_elements_log) mgr.set_constant("el_activation_threshold", self.activation_threshold) mgr.set_constant("el_kill_threshold", self.kill_threshold) mgr.set_constant("adv_upwind_alpha", self.upwind_alpha) mgr.set_constant("filter_amp", self.filter_amp) mgr.set_constant("filter_amp", self.filter_order) def set_shape_function(self, state, sf): Depositor.set_shape_function(self, state, sf) state.depositor_state.clear() for pn in xrange(len(state)): self.backend.add_advective_particle(state.depositor_state, state.particle_state, sf, pn) def note_move(self, state, orig, dest, size): self.backend.note_move(state.depositor_state, orig, dest, size) def note_change_size(self, state, new_size): self.backend.note_change_size(state.depositor_state, new_size) if (self.shape_function is not None and new_size > state.depositor_state.count_advective_particles()): for pn in range(state.depositor_state.count_advective_particles(), new_size): self.backend.add_advective_particle(state.depositor_state, state.particle_state, self.shape_function, pn) def clear_particles(self): Depositor.clear_particles(self) self.cloud.pic_algorithm.clear_advective_particles() def upkeep(self, state): self.backend.perform_depositor_upkeep(state.depositor_state, state.particle_state) def rhs(self, state): from pyrticle.tools import NumberShiftableVector sub_timer = self.advective_rhs_timer.start_sub_timer() result = NumberShiftableVector( self.backend.get_advective_particle_rhs( state.depositor_state, state.particle_state, self.method.velocities(state)), signaller=state.depositor_state.rho_dof_shift_listener) sub_timer.stop() self.element_activation_counter.transfer( state.depositor_state.element_activation_counter) self.element_kill_counter.transfer( state.depositor_state.element_kill_counter) return result def advance_state(self, state, rhs): # depositor states tend to linger on for a bit--ours here are # big, so they need to go. from gc import collect collect() from pyrticle.tools import NumberShiftableVector return self.backend.apply_advective_particle_rhs( state.depositor_state, state.particle_state, NumberShiftableVector.unwrap(rhs), state.depositor_state.rho_dof_shift_listener)