Esempio n. 1
0
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)),
                    ])
Esempio n. 2
0
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)),
                            ])
Esempio n. 3
0
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)
Esempio n. 4
0
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)