def __init__(self,
                 potential: Potential,
                 dipole_separation: float,
                 prefactor: float = 1.5,
                 empirical_bound: float = float('inf'),
                 number_trials: int = 10000,
                 dipole_charge: float = 1.0,
                 periodic_boundaries: bool = True) -> None:
        """
        The constructor of the InnerPointEstimator class.

        Parameters
        ----------
        potential : potential.Potential
            Potential whose derivative is to be bounded.
        dipole_separation : float
            Separation of the two point masses within the constructed dipole.
        prefactor : float, optional
            A constant which gets multiplied to the bounds.
        empirical_bound : float, optional
            If a bound exceeds this value, this value will be returned instead.
        number_trials : int, optional
            The number of separation samples taken.
        dipole_charge : float, optional
            The absolute value of the charges in the dipole.
        periodic_boundaries : bool
            Whether the separations in the given region should be corrected for periodic boundaries.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the potential derivative method does not expect exactly one separation.
            If the potential derivative method does not expect exactly two charges.
        """
        log_init_arguments(logging.getLogger(__name__).debug,
                           self.__class__.__name__,
                           potential=potential.__class__.__name__,
                           dipole_separation=dipole_separation,
                           prefactor=prefactor,
                           empirical_bound=empirical_bound,
                           number_trials=number_trials,
                           dipole_charge=dipole_charge,
                           periodic_boundaries=periodic_boundaries)
        super().__init__(potential=potential,
                         prefactor=prefactor,
                         empirical_bound=empirical_bound)
        self._number_trials = number_trials
        self._dipole_separation = dipole_separation
        self._dipole_separation_over_two = dipole_separation / 2
        self._dipole_charge = dipole_charge
        if self._potential.number_separation_arguments != 1:
            raise ConfigurationError(
                "The estimator {0} expects a potential "
                "which handles exactly one separation!".format(
                    self.__class__.__name__))
        if self._potential.number_charge_arguments != 2:
            raise ConfigurationError(
                "The estimator {0} expects a potential "
                "which handles exactly two charges!".format(
                    self.__class__.__name__))
Beispiel #2
0
    def __init__(self, charge_values: Sequence[ChargeValues] = ()) -> None:
        """
        The constructor of the RandomNodeCreator class.

        Parameters
        ----------
        charge_values : Sequence[input_output_handler.input_handler.charge_values.ChargeValues], optional
            The sequence of charge values.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the charge values does not contain a charge for each child node within a root node.
        base.exceptions.ConfigurationError:
            If in the sequence of charge values a charge name appears more than once.
        """
        # Check that per charge value there is a charge given for every particle
        for charge_value in charge_values:
            if not len(charge_value) == self.number_of_nodes_per_root_node:
                raise ConfigurationError(
                    "Charge {0} is not given for every child of a composite point object."
                    .format(charge_value.charge_name))
        # Check that each charge value has a different name
        if not len(
                set(charge_value.charge_name
                    for charge_value in charge_values)) == len(charge_values):
            raise ConfigurationError(
                "Please choose a unique charge name for all the charges used.")
        self._charge_values = charge_values
    def __init__(self, prefactor: float = 1.5837) -> None:
        """
        The constructor of the InversePowerCoulombBoundingPotential class.

        Parameters
        ----------
        prefactor : float, optional
            The prefactor k of the potential.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the hypercubic setting is not initialized.
        base.exceptions.ConfigurationError
            If the dimension does not equal three.
        """
        log_init_arguments(logging.getLogger(__name__).debug,
                           self.__class__.__name__,
                           prefactor=prefactor)
        if not setting.initialized():
            raise ConfigurationError(
                "Potential {0} can only be used in a hypercubic setting.".
                format(self.__class__.__name__))
        if not setting.dimension == 3:
            raise ConfigurationError(
                "The potential {0} can only be used in 3 dimensions.".format(
                    self.__class__.__name__))
        super().__init__(prefactor=prefactor)
    def __init__(self, minimum_separation: float, maximum_separation: float) -> None:
        """
        The constructor of the HardDipolePotential class.

        Parameters
        ----------
        minimum_separation : float
            The minimum separation r.
        maximum_separation : float
            The maximum separation R.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the minimum separation r is not larger than 0.
            If the maximum separation R is not larger than 0.
            If the minimum separation r is not smaller than the maximum separation R.
        """
        log_init_arguments(logging.getLogger(__name__).debug, self.__class__.__name__,
                           minimum_separation=minimum_separation, maximum_separation=maximum_separation)
        if not minimum_separation > 0.0:
            raise ConfigurationError("The class {0} can only be used with a minimum separation bigger than 0.0."
                                     .format(self.__class__.__name__))
        if not maximum_separation:
            raise ConfigurationError("The class {0} can only be used with a maximum separation bigger than 0.0."
                                     .format(self.__class__.__name__))
        if not minimum_separation < maximum_separation:
            raise ConfigurationError("The class {0} can only be used with a minimum separation that is smaller than the"
                                     "maximum separation.".format(self.__class__.__name__))
        super().__init__()
        self._minimum_separation_squared = minimum_separation * minimum_separation
        self._maximum_separation_squared = maximum_separation * maximum_separation
Beispiel #5
0
    def __init__(self, chain_time: float, delta_phi_degree: float) -> None:
        """
        The constructor of the SingleIndependentActiveSequentialDirectionEndOfChainEventHandler class.

        The rotation angle in degrees by which the two-dimensional velocity vector is rotated on each end-of-chain event
        should be greater than 0.0 and smaller than 360.0. Moreover, 180.0 degrees is excluded to assure irreducibility
        of the Markov chain.

        Parameters
        ----------
        chain_time : float
            The time interval after which a new end-of-chain event occurs.
        delta_phi_degree : float
            The rotation angle in degrees by which the two-dimensional velocity vector is rotated on each end-of-chain
            event.

        Raises
        ------
        base.exceptions.ConfigurationError:
            If the rotation angle in degrees is not in the interval (0, 360.0) or equal to 180.0.
            If the dimension in the setting package is not set to two.
        """
        log_init_arguments(logging.getLogger(__name__).debug, self.__class__.__name__, chain_time=chain_time,
                           delta_phi_degree=delta_phi_degree)
        super().__init__(chain_time=chain_time)
        if not 0.0 < delta_phi_degree < 360.0 or delta_phi_degree == 180.0:
            raise ConfigurationError("The rotation angle of the velocity after an end-of-chain event in the event "
                                     "handler {0} has to be larger than 0.0 and smaller than 360.0, and is further not "
                                     "allowed to be exactly 180.0.".format(self.__class__.__name__))
        if not setting.dimension == 2:
            raise ConfigurationError("The event handler {0} can only be used in two dimensions."
                                     .format(self.__class__.__name__))
        delta_phi = delta_phi_degree * math.pi / 180.0
        self._cos_delta_phi = math.cos(delta_phi)
        self._sin_delta_phi = math.sin(delta_phi)
    def __init__(self,
                 potential: Potential,
                 bounding_potential: CellBoundingPotential,
                 charge: str = None) -> None:
        """
        The constructor of the TwoLeafUnitCellBoundingPotentialEventHandler class.

        Parameters
        ----------
        potential : potential.Potential
            The potential between the leaf units.
        bounding_potential : potential.cell_bounding_potential.CellBoundingPotential
            The invertible cell bounding potential between the leaf units.
        charge : str or None, optional
            The relevant charge for this event handler.

        Raises
        ------
        base.exceptions.ConfigurationError:
            If the cell bounding potential does not expect exactly one separation.
        base.exceptions.ConfigurationError:
            If the charge is not None but the potential or the cell bounding potential expects more than two charges.
        """
        log_init_arguments(
            logging.getLogger(__name__).debug,
            self.__class__.__name__,
            potential=potential.__class__.__name__,
            bounding_potential=bounding_potential.__class__.__name__,
            charge=charge)
        super().__init__(potential=potential,
                         bounding_potential=bounding_potential)
        self._charge = charge

        if self._bounding_potential.number_separation_arguments != 1:
            raise ConfigurationError(
                "The event handler {0} expects a cell bounding potential "
                "which handles exactly one separation!".format(
                    self.__class__.__name__))

        if charge is None:
            self._potential_charges = (lambda unit_one, unit_two: tuple(
                1.0 for _ in range(self._potential.number_charge_arguments)))
            self._bounding_potential_charges = (
                lambda unit_one, unit_two: tuple(1.0 for _ in range(
                    self._bounding_potential.number_charge_arguments)))
        else:
            if self._potential.number_charge_arguments == 2 and self._bounding_potential.number_charge_arguments == 2:
                self._potential_charges = lambda unit_one, unit_two: (
                    unit_one.charge[charge], unit_two.charge[charge])
                self._bounding_potential_charges = self._potential_charges
            else:
                raise ConfigurationError(
                    "The event handler {0} was initialized with a charge which is not None,"
                    " but its potential {1} and/or its bounding potential {2}"
                    "expects not exactly 2 charges.".format(
                        self.__class__.__name__,
                        self._potential.__class__.__name__,
                        self._bounding_potential.__class__.__name__))
Beispiel #7
0
    def initialize(self, extracted_global_state: Any) -> None:
        """
        Initialize all the taggers based on the internal states.

        Extends the initialize method of the abstract Activator class. This method is called once in the beginning of
        the run by the mediator. Only after a call of this method, other public methods of this class can be called
        without raising an error.

        The internal states get initialized in the super().initialize(extracted_global_state) using the extracted global
        state from the state handler.

        The precise format of the extracted_active_global_state is specified by the used state handler. Since it is
        just passed through to the internal states, only their initialize methods needs to be implemented for different
        versions of state handlers.

        Since taggers might only be able to provide a full list of their event handlers after a call to their initialize
        method (because, e.g., the tagger wants to first initialize a single event handler with information about an
        internal state, and then copy the initialized event handler), attributes of this class that rely on all event
        handlers are constructed here and not in the __init__ method.

        Parameters
        ----------
        extracted_global_state : Any
            The full extracted global state from the state handler.
        """
        super().initialize(extracted_global_state)
        for tagger in self._taggers:
            tagger.initialize_with_internal_states(self._internal_states)
            tagger.initialize()

        self._event_handlers = sum(
            (tagger.get_event_handlers() for tagger in self._taggers), [])
        self._event_handler_tagger_dictionary = {
            event_handler: tagger
            for tagger in self._taggers
            for event_handler in tagger.get_event_handlers()
        }
        self._running_event_handlers = {tagger: [] for tagger in self._taggers}
        self._not_running_event_handlers = {
            tagger: copy.copy(tagger.get_event_handlers())
            for tagger in self._taggers
        }

        # Search the one and only instance of StartOfRunEventHandler
        self._start_of_run_event_handler = None
        for event_handler in self._event_handlers:
            if isinstance(event_handler, StartOfRunEventHandler):
                if self._start_of_run_event_handler is None:
                    self._start_of_run_event_handler = event_handler
                else:
                    raise ConfigurationError(
                        "Please provide only one StartOfRunEventHandler!")
        if self._start_of_run_event_handler is None:
            raise ConfigurationError(
                "An StartOfRunEventHandler is required to run the program!")
    def __init__(self,
                 potential: Potential,
                 offset: float,
                 max_displacement: float,
                 charge: str = None) -> None:
        """
        The constructor of the TwoLeafUnitEventHandlerWithPiecewiseConstantBoundingPotential class.

        Parameters
        ----------
        potential : potential.Potential
            The potential between the leaf units.
        offset : float
            The offset used to create piecewise constant bounding potential.
        max_displacement :
            The maximum time displacement used to create piecewise constant bounding potential.
        charge : str or None, optional
            The relevant charge for this event handler.

        Raises
        ------
        base.exceptions.ConfigurationError:
            If the potential does not expect exactly one separation.
        base.exceptions.ConfigurationError:
            If the charge is not None but the potential expects more than two charges.
        """
        log_init_arguments(logging.getLogger(__name__).debug,
                           self.__class__.__name__,
                           potential=potential.__class__.__name__,
                           offset=offset,
                           max_displacement=max_displacement,
                           charge=charge)
        super().__init__(potential=potential,
                         offset=offset,
                         max_displacement=max_displacement)
        if self._potential.number_separation_arguments != 1:
            raise ConfigurationError(
                "The event handler {0} expects a potential "
                "which handles exactly one separation!".format(
                    self.__class__.__name__))

        if charge is None:
            self._charges = lambda unit_one, unit_two: tuple(
                1.0 for _ in range(self._potential.number_charge_arguments))
        else:
            if self._potential.number_charge_arguments == 2:
                self._charges = lambda unit_one, unit_two: (unit_one.charge[
                    charge], unit_two.charge[charge])
            else:
                raise ConfigurationError(
                    "The event handler {0} was initialized with a charge which is not None,"
                    " but its potential {1} expects not exactly 2 charges.".
                    format(self.__class__.__name__,
                           self._potential.__class__.__name__))
    def __init__(self,
                 potential: InvertiblePotential,
                 charge: str = None) -> None:
        """
        The constructor of the TwoLeafUnitEventHandler class.

        Parameters
        ----------
        potential : potential.InvertiblePotential
            The invertible potential.
        charge : str or None, optional
            The relevant charge for this event handler.

        Raises
        ------
        base.exceptions.ConfigurationError:
            If the potential does not expect exactly one separation.
        base.exceptions.ConfigurationError:
            If the charge is not None but the potential expects more than two charges.
        """
        log_init_arguments(logging.getLogger(__name__).debug,
                           self.__class__.__name__,
                           potential=potential.__class__.__name__,
                           charge=charge)
        super().__init__()
        self._potential = potential
        if self._potential.number_separation_arguments != 1:
            raise ConfigurationError(
                "The event handler {0} expects a potential "
                "which handles exactly one separation!".format(
                    self.__class__.__name__))

        if charge is None:
            self._charges = lambda unit_one, unit_two: tuple(
                1.0 for _ in range(self._potential.number_charge_arguments))
        else:
            if self._potential.number_charge_arguments == 2:
                self._charges = lambda unit_one, unit_two: (unit_one.charge[
                    charge], unit_two.charge[charge])
            else:
                raise ConfigurationError(
                    "The event handler {0} was initialized with a charge which is not None,"
                    " but its potential {1} expects not exactly 2 charges.".
                    format(self.__class__.__name__,
                           self._potential.__class__.__name__))

        if self._potential.potential_change_required:
            self._potential_displacement = (
                lambda *args, **kwargs: self._potential.displacement(
                    *args,
                    **kwargs,
                    potential_change=random.expovariate(setting.beta)))
        else:
            self._potential_displacement = self._potential.displacement
    def __init__(self, potential: Potential, **kwargs: Any):
        """
        The constructor of the EventHandlerWithBoundingPotential class.

        This class is designed for cooperative inheritance, meaning that it passes through all unused kwargs in the
        init to the next class in the MRO via super.

        Parameters
        ----------
        potential : potential.Potential
            The potential between the active and target leaf unit.
        kwargs : Any
            Additional kwargs which are passed to the __init__ method of the next class in the MRO.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the potential expects more than one separation.
        """
        super().__init__(**kwargs)
        self._bounding_event_rate = None
        self._potential = potential
        if self._potential.number_separation_arguments != 1:
            raise ConfigurationError("The event handler {0} expects a potential "
                                     "which handles exactly one separation!".format(self.__class__.__name__))
Beispiel #11
0
    def __init__(self, filename: str, charge: str) -> None:
        """
        The constructor of the PolarizationOutputHandler class.

        This class uses a HardBufferedTextWriter to first write the polarization to a temporary file.

        Parameters
        ----------
        filename : str
            The filename of the file this output handler is connected to.
        charge : str
            The charge used to calculate the polarization.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the number of node levels is not two or the number of nodes per root node is not three.
        """
        log_init_arguments(logging.getLogger(__name__).debug, self.__class__.__name__, filename=filename, charge=charge)
        super().__init__(filename)
        self._file = HardBufferedTextWriter(filename)
        self._charge = charge
        if setting.number_of_node_levels != 2 or setting.number_of_nodes_per_root_node == 1:
            raise ConfigurationError("The output handler {0} can only be used with charge neutral composite point"
                                     " objects.".format(self.__class__.__name__))
        print("# Polarization Vector", file=self._file)
    def initialize(self, cells: PeriodicCells,
                   calculate_lower_bound: bool) -> None:
        """
        Initialize the cell bounding potential.

        This is done by handing the cells to the cell bounding potential, and by telling it whether it needs to
        determine a lower bound on the derivatives for all not excluded cell separations, or not.

        Since in this version of JeLLyFysh, cell separations are only defined for periodic cell systems (i.e., with
        taking periodic boundary conditions into account), a cell bounding potential can only be initialized with an
        instance of the 'PeriodicCells' class. The same restriction thus holds for this event handler.

        Extends the initialize method of the abstract Initializer class. This method is called once in the beginning of
        the run by the activator. Only after a call of this method, other public methods of this class can be called
        without raising an error.

        Parameters
        ----------
        cells : activator.internal_state.cell_occupancy.cells.Cells
            The cell system.
        calculate_lower_bound : bool
            Whether the cell bounding potential needs to compute a lower bound or not.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the cell system is not an instance of a periodic cell system.
        """
        super().initialize()
        if not isinstance(cells, PeriodicCells):
            raise ConfigurationError(
                "The event handler {0} can only be initialized with an instance of the "
                "'PeriodicCells' class.".format(self.__class__.__name__))
        self._cells = cells
        self._bounding_potential.initialize(cells, calculate_lower_bound)
    def __init__(self, cells: Cells, cell_level: int, maximum_number_occupants: int = 1, charge: str = None) -> None:
        """
        The constructor of the SingleActiveCellOccupancy class.

        Parameters
        ----------
        cells : activator.internal_state.cell_occupancy.cells.Cells
            The underlying cell system.
        cell_level : int
            The length of the global state identifiers which should be stored in this internal state.
        maximum_number_occupants : int, optional
            The maximum number of allowed occupants per cell. If this number is smaller than or equal to zero, this
            class allows for an infinite number of occupants per cell.
        charge : str or None, optional
            The charge of the unit that must be unequal zero in order for the corresponding identifier to be stored.
            If the charge is None, all global state identifiers with the correct length are stored.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the cell_level corresponds to composite point objects which cannot have a charge but the charge is set.
        """
        log_init_arguments(logging.getLogger(__name__).debug, self.__class__.__name__, cells=cells.__class__.__name__,
                           cell_level=cell_level, maximum_number_occupants=maximum_number_occupants, charge=charge)
        super().__init__(cells, cell_level, maximum_number_occupants)
        if cell_level < setting.number_of_node_levels and charge is not None:
            raise ConfigurationError("Chosen cell level stores composite point objects which cannot have a charge!")
        self._surplus = {}
        self._occupants = {cell: [] for cell in self._cells.yield_cells()}
        self._active_unit_identifier = None
        self._is_relevant_unit = (lambda unit: unit.charge[charge] != 0) if charge is not None else lambda unit: True
        self._active_cell = None
    def __init__(self, end_of_run_time: float, output_handler: str = None) -> None:
        """
        The constructor of the FinalTimeEndOfRunEventHandler class.

        Parameters
        ----------
        end_of_run_time : float
            The event time at which the run is ended.
        output_handler : str or None, optional
            The name of the output handler.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the end of run time is not greater than or equal to zero (the latter case logs a warning).
        """
        log_init_arguments(logging.getLogger(__name__).debug, self.__class__.__name__,
                           end_of_run_time=end_of_run_time, output_handler=output_handler)
        super().__init__(output_handler=output_handler)
        if not end_of_run_time >= 0.0:
            raise ConfigurationError("The end_of_run_time in the event handler {0} has to be >= 0.0."
                                     .format(self.__class__.__name__))
        if end_of_run_time == 0.0:
            logging.getLogger(__name__).warning("The end_of_run_time in the event handler {0} is equal to 0.0. The "
                                                "simulation will stop immediately once the run is started."
                                                .format(self.__class__.__name__))
        self._event_time = Time.from_float(end_of_run_time)
    def initialize_with_internal_states(self, internal_states: Sequence[InternalState]) -> None:
        """
        Initialize the tagger based on the initialized internal states.

        Extends the initialize_with_internal_states method of the base TaggerWithInternal class. This method is a second
        initialize method relevant to the base Initializer class. It is called once in the beginning of the run by the
        tag activator. However, this method does not call the initialize method of the Initializer class. Therefore,
        other public methods of this class can still not be called without raising an error after this method has been
        used. To finalize the initialization of this class, use the initialize method (which should be called after this
        method).

        This method checks if the internal state of this label is a cell-occupancy system.

        Parameters
        ----------
        internal_states : Sequence[activator.internal_state.InternalState]
            Sequence of all initialized internal states in the activator.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the internal state is not an instance of CellOccupancy.
        """
        super().initialize_with_internal_states(internal_states)
        if not isinstance(self._internal_state, CellOccupancy):
            raise ConfigurationError("The tagger {0} can only be used with an instance of the CellOccupancy class as "
                                     "the internal state.".format(self.__class__.__name__))
Beispiel #16
0
    def __init__(self, filename: str) -> None:
        """
        The constructor of the DumpingOutputHandler class.

        Parameters
        ----------
        filename : str
            The filename of the file this output handler is connected to.

        Raises
        ------
        AssertionError
            If the filename does not contain a file format.
        """
        log_init_arguments(logging.getLogger(__name__).debug,
                           self.__class__.__name__,
                           filename=filename)
        split_filename = filename.split(".")
        if len(split_filename) != 2:
            raise ConfigurationError(
                "The given filename {0} contains more than one '.'.".format(
                    filename))
        # Include python implementation and version (implementation_major_minor_macro in filename)
        dumping_filename = (
            split_filename[0] + "_" + sys.implementation.name + "_" +
            "_".join([str(sys.version_info[i])
                      for i in range(3)]) + "." + split_filename[1])

        super().__init__(dumping_filename)
    def __init__(self, power: float, prefactor: float) -> None:
        """
        The constructor of the InversePowerPotential.

        Parameters
        ----------
        power : float
            The power p of the potential.
        prefactor : float
            The prefactor k of the potential.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the power p is not larger than 0.
        """
        log_init_arguments(logging.getLogger(__name__).debug, self.__class__.__name__,
                           power=power, prefactor=prefactor)
        super().__init__(prefactor=prefactor)
        if not power > 0.0:
            raise ConfigurationError("Give a power > 0.0 as the power for the potential {0}."
                                     .format(self.__class__.__name__))
        self._power = power
        self._two_over_power = 2.0 / self._power
        self._power_over_two = self._power / 2.0
        self._power_plus_two = self._power + 2
        self._infinity = float('inf')
    def __init__(self, potential: Potential, offset: float, max_displacement: float, **kwargs: Any):
        """
        The constructor of the EventHandlerWithPiecewiseConstantBoundingPotential class.

        This class is designed for cooperative inheritance, meaning that it passes through all unused kwargs in the
        init to the next class in the MRO via super.

        Parameters
        ----------
        potential : potential.Potential
            The potential between the leaf units.
        offset : float
            The offset.
        max_displacement : float
            The maximum time displacement by which the active unit is displaced to determine the bounding event rate.
        kwargs : Any
            Additional kwargs which are passed to the __init__ method of the next class in the MRO.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the maximum time displacement is not larger than zero.
        """
        super().__init__(**kwargs)
        self._potential = potential
        self._offset = offset
        if not max_displacement > 0.0:
            raise ConfigurationError("Please use a value for max_displacement > 0.0 in the class {0}."
                                     .format(self.__class__.__name__))
        self._max_displacement = max_displacement
        self._bounding_event_rate = None
Beispiel #19
0
    def __init__(
        self,
        create: Sequence[str],
        trash: Sequence[str],
        event_handler: EventHandler,
        number_event_handlers: int = 1,
        tag: str = None,
        activate: Sequence[str] = (),
        deactivate: Sequence[str] = ()
    ) -> None:
        """
        The constructor of the ActiveRootUnitInStateTagger class.

        Parameters
        ----------
        create : Sequence[str]
            Sequence of tags to create after an event handler of this tagger has committed an event to the global state.
        trash : Sequence[str]
            Sequence of tags to trash after an event handler of this tagger has committed an event to the global state.
        event_handler : event_handler.EventHandler
            A single event handler instance.
        number_event_handlers : int, optional
            Number of event handlers to prepare. The tagger will deepcopy the given event handler instance to create
            this number of event handlers.
        tag : str or None, optional
            Tag used in all four lists (also of other taggers). If None, the class name (or the alias set in the
            factory) will be used as the tag.
        activate : Sequence[str], optional
            Sequence of tags to activate after an event handler of this tagger has committed an event to the global
            state.
        deactivate : Sequence[str], optional
            Sequence of tags to deactivate after an event handler of this tagger has committed an event to the global
            state.

        Raises
        ------
        base.exceptions.ConfigurationError
            If no composite point objects are involved in the run (setting.number_of_node_levels not > 1).
        """
        log_init_arguments(logging.getLogger(__name__).debug,
                           self.__class__.__name__,
                           event_handler=event_handler.__class__.__name__,
                           number_event_handlers=number_event_handlers,
                           create=create,
                           trash=trash,
                           activate=activate,
                           deactivate=deactivate,
                           tag=tag)
        super().__init__(create,
                         trash,
                         event_handler,
                         number_event_handlers=number_event_handlers,
                         tag=tag,
                         activate=activate,
                         deactivate=deactivate)
        if not setting.number_of_node_levels > 1:
            raise ConfigurationError(
                "The tagger {0} can only be used when composite point objects are involved in the"
                "simulation (setting.number_of_node_levels > 1).".format(
                    self.__class__.__name__))
Beispiel #20
0
    def initialize(self, cells: PeriodicCells, cell_level: int) -> None:
        """
        Initialize the cell boundary event handler.

        Here, the event handler gets access to the relevant periodic cell system and the cell level of the corresponding
        cell-occupancy system.

        This cell boundary event handler requires a periodic cell system (and not a simple cell system) so that each
        cell always has a neighbor cell.

        Extends the initialize method of the abstract Initializer class. This method is called once in the beginning of
        the run by the activator. Only after a call of this method, other public methods of this class can be called
        without raising an error.

        Parameters
        ----------
        cells : activator.internal_state.cell_occupancy.cells.PeriodicCells
            The periodic cell system.
        cell_level : int
            The cell level.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the cell system is not an instance of the PeriodicCells class.
        """
        super().initialize()
        if not isinstance(cells, PeriodicCells):
            raise ConfigurationError("The event handler {0} can only be initialized with an instance of the "
                                     "PeriodicCells class.".format(self.__class__.__name__))
        self._cells = cells
        self._cell_level = cell_level
    def __init__(self, equilibrium_separation: float, power: int, prefactor: float = 1.0) -> None:
        """
        The constructor of the DisplacedEvenPowerPotential class.

        Parameters
        ----------
        equilibrium_separation : float
            The absolute value r_0 of the equilibrium separation of the potential.
        power : int
            The power p of the potential.
        prefactor : float, optional
            The prefactor k of the potential.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the power p is not larger than 0 or if p is odd.
        """
        log_init_arguments(logging.getLogger(__name__).debug, self.__class__.__name__,
                           equilibrium_separation=equilibrium_separation, power=power, prefactor=prefactor)
        super().__init__(prefactor=prefactor, equilibrium_separation=equilibrium_separation)
        if not (power > 0 and power % 2 == 0):
            raise ConfigurationError("The potential {0} can only be used with "
                                     "a power > 0 divisible by 2!".format(self.__class__.__name__))
        self._equilibrium_separation = equilibrium_separation
        self._equilibrium_separation_squared = equilibrium_separation * equilibrium_separation
        self._power = power
        self._inverse_power = 1.0 / power
    def __init__(self, dumping_interval: float, output_handler: str) -> None:
        """
        The constructor of the FixedIntervalDumpingEventHandler class.

        Parameters
        ----------
        dumping_interval : float
            The time interval of the dumping.
        output_handler :
            The name of the output handler.

        Raises
        ------
        base.exceptions.ConfigurationError:
            If the dumping interval is not greater than zero.
        """
        log_init_arguments(logging.getLogger(__name__).debug,
                           self.__class__.__name__,
                           dumping_interval=dumping_interval,
                           output_handler=output_handler)
        super().__init__(output_handler=output_handler)
        if not dumping_interval > 0.0:
            raise ConfigurationError(
                "The dumping_interval in the event handler {0} has to be > 0.0."
                .format(self.__class__.__name__))
        self._dumping_interval = dumping_interval
        self._event_time = Time(0.0, 0.0)
    def __init__(self, filename: str):
        """
        The constructor of the BondLengthAndAngleOutputHandler class.

        This class uses a HardBufferedTextWriter to first write the bond lengths and angles to temporary files.

        Parameters
        ----------
        filename : str
            The filename of the file this output handler is connected to.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the number of node levels is not two or the number of nodes per root node is not three.
        """
        log_init_arguments(logging.getLogger(__name__).debug, self.__class__.__name__, filename=filename)
        super().__init__(filename)
        filename_dot_position = self._output_filename.rfind('.')
        bond_length_filename = (self._output_filename[:filename_dot_position]
                                + '_Length' + self._output_filename[filename_dot_position:])
        bond_angle_filename = (self._output_filename[:filename_dot_position]
                               + '_Angle' + self._output_filename[filename_dot_position:])
        self._file_bond_lengths = HardBufferedTextWriter(bond_length_filename)
        self._file_bond_angles = HardBufferedTextWriter(bond_angle_filename)
        if setting.number_of_node_levels != 2 or setting.number_of_nodes_per_root_node != 3:
            raise ConfigurationError("The output handler {0} can only be used if each root node has 3 child nodes."
                                     .format(self.__class__.__name__))
    def __init__(self, bounding_potential: CellBoundingPotential,
                 **kwargs: Any) -> None:
        """
        The constructor of the CellBoundingPotentialEventHandler class.

        This class is designed for cooperative inheritance, meaning that it passes through all unused kwargs in the
        init to the next class in the MRO via super.

        Parameters
        ----------
        bounding_potential : potential.cell_bounding_potential.CellBoundingPotential
            The cell bounding potential.
        kwargs : Any
            Additional kwargs which are passed to the __init__ method of the next class in the MRO.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the bounding potential is not an instance of a cell bounding potential.
        """
        super().__init__(**kwargs)
        self._cells = None
        self._active_cell = None
        self._relative_cell = None
        self._bounding_potential = bounding_potential
        if not isinstance(self._bounding_potential, CellBoundingPotential):
            raise ConfigurationError(
                "The event handler {0} can only be used "
                "with the class CellBoundingPotential!".format(
                    self.__class__.__name__))
    def write(self, output_handler: str, *args: Any) -> None:
        """
        Pass the arguments to the output handler.

        The arguments could be for example the full global state so that the output handler can start its sampling.
        This method is called in the mediating methods of event handlers in the mediator. There, each event handler
        defines itself, which methods should be passed to its output handler.
        When the output handlers were built using the JF factory, their names can include an alias. Then the output
        handler name should be this alias.

        Parameters
        ----------
        output_handler : str
            The name of the output handler which should receive the arguments.
        args : Any
            The arguments passed to output handler.

        Raises
        ------
        base.exceptions.ConfigurationError
            If no output handler with the given name exists.
        """
        try:
            self._output_handlers_dictionary[output_handler].write(*args)
        except KeyError:
            raise ConfigurationError("The given output handler {0} does not exist.".format(output_handler))
Beispiel #26
0
    def __init__(self, sampling_interval: float, output_handler: str, first_event_time_zero: bool = False) -> None:
        """
        The constructor of the FixedIntervalSamplingEventHandler class.

        Parameters
        ----------
        sampling_interval : float
            The time interval of the sampling.
        output_handler : str
            The name of the output handler.
        first_event_time_zero : bool, optional
            If the first returned candidate event time is zero.

        Raises
        ------
        base.exceptions.ConfigurationError:
            If the sampling interval is not greater than zero.
        """
        log_init_arguments(logging.getLogger(__name__).debug, self.__class__.__name__,
                           sampling_interval=sampling_interval, output_handler=output_handler)
        super().__init__(output_handler=output_handler)
        if not sampling_interval > 0.0:
            raise ConfigurationError("The sampling_interval in the event handler {0} has to be > 0.0."
                                     .format(self.__class__.__name__))
        self._sampling_interval = sampling_interval
        self._event_time = Time(0.0, 0.0) if not first_event_time_zero else Time.from_float(-sampling_interval)
Beispiel #27
0
    def initialize_with_internal_states(self, internal_states: Sequence[InternalState]) -> None:
        """
        Initialize the tagger based on the initialized internal states.

        Extends the initialize_with_internal_states method of the base TaggerWithInternal class. This method is a second
        initialize method relevant to the base Initializer class. It is called once in the beginning of the run by the
        tag activator. However, this method does not call the initialize method of the Initializer class. Therefore,
        other public methods of this class can still not be called without raising an error after this method has been
        used. To finalize the initialization of this class, use the initialize method (which should be called after this
        method).

        This method checks if the internal state of this tagger is a cell-occupancy system. Also, the cell bounding
        potential event handler in the self._event_handler_to_copy attribute gets knowledge about the cell system, and
        is initialized itself. This event handler is deepcopied in the subsequent call of the initialize method to
        create the desired number of (initialized) event handlers for this tagger (see Tagger base class).

        Parameters
        ----------
        internal_states : Sequence[activator.internal_state.InternalState]
            Sequence of all initialized internal states in the activator.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the internal state is not an instance of CellOccupancy.
        """
        super().initialize_with_internal_states(internal_states)
        if not isinstance(self._internal_state, CellOccupancy):
            raise ConfigurationError("The tagger {0} can only be used with an instance of the CellOccupancy class as "
                                     "the internal state.".format(self.__class__.__name__))
        # noinspection PyUnresolvedReferences
        self._event_handler_to_copy.initialize(self._internal_state.cells)
Beispiel #28
0
    def __init__(self,
                 create: Sequence[str],
                 trash: Sequence[str],
                 event_handler: EventHandler,
                 internal_state_label: str,
                 number_event_handlers: int = 1,
                 tag: str = None) -> None:
        """
        The constructor of the CellVetoTagger class.

        This class uses an internal state and therefore inherits from the TaggerWithInternalState class. The
        internal_state_label should refer to a cell-occupancy system.

        Note that the activate and deactivate sequences are always empty for a tagger of this kind.

        The event handler should be an instance of a CellVetoEventHandler. The number of event handlers should be
        set to the number of active units that are relevant to the cell-occupancy system.

        Parameters
        ----------
        create : Sequence[str]
            Sequence of tags to create after an event handler of this tagger has committed an event to the global state.
        trash : Sequence[str]
            Sequence of tags to trash after an event handler of this tagger has committed an event to the global state.
        event_handler : event_handler.cell_boundary_event_handler.CellBoundaryEventHandler
            A single event handler instance.
        internal_state_label : str
            The label of the internal state this tagger wants to use.
        number_event_handlers : int, optional
            Number of event handlers to prepare. The tagger will deepcopy the given event handler instance to create
            this number of event handlers.
        tag : str or None, optional
            Tag used in all four lists (also of other taggers). If None, the class name (or the alias set in the
            factory) will be used as the tag.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the event handler is not an instance of a CellVetoEventHandler.
        """
        log_init_arguments(logging.getLogger(__name__).debug,
                           self.__class__.__name__,
                           event_handler=event_handler.__class__.__name__,
                           number_event_handlers=number_event_handlers,
                           internal_state_label=internal_state_label,
                           create=create,
                           trash=trash,
                           tag=tag)
        if not isinstance(event_handler, CellVetoEventHandler):
            raise ConfigurationError(
                "The class {0} can only be used with an instance of the class "
                "CellVetoEventHandler as the event handler".format(
                    self.__class__.__name__))
        super().__init__(create,
                         trash,
                         event_handler,
                         number_event_handlers=number_event_handlers,
                         internal_state_label=internal_state_label,
                         tag=tag)
    def __init__(self, potential: Potential, lifting: Lifting, charge: str = None, **kwargs: Any) -> None:
        """
        The constructor of the TwoCompositeObjectBoundingPotentialEventHandler class.

        This class is designed for cooperative inheritance, meaning that it passes through all unused kwargs in the
        init to the next class in the MRO via super.

        Parameters
        ----------
        potential : potential.Potential
            The potential between all pairs of units in different composite objects.
        lifting : lifting.Lifting
            The lifting scheme.
        charge : str or None, optional
            The charge this event handler passes to the potential. If None, the potential just gets one as the charges.
        kwargs : Any
            Additional kwargs which are passed to the __init__ method of the next class in the MRO.

        Raises
        ------
        base.exceptions.ConfigurationError
            If the number of nodes per root node is one and therefore no composite objects are present in the run.
        base.exceptions.ConfigurationError
            If the potential expects more than one separation.
        base.exceptions.ConfigurationError
            If the charge is not None but the potential expects more than two charges.
        """
        super().__init__(potential=potential, **kwargs)
        self._lifting = lifting
        if not setting.number_of_nodes_per_root_node > 1:
            raise ConfigurationError("Class {0} can only be used when composite point objects are present!"
                                     .format(self.__class__.__name__))
        if self._potential.number_separation_arguments != 1:
            raise ConfigurationError("The event handler {0} expects a potential "
                                     "which handles exactly one separation!".format(self.__class__.__name__))
        if charge is None:
            self._potential_charges = (lambda unit_one, unit_two:
                                       tuple(1.0 for _ in range(self._potential.number_charge_arguments)))
        else:
            if self._potential.number_charge_arguments == 2:
                self._potential_charges = lambda unit_one, unit_two: (unit_one.charge[charge], unit_two.charge[charge])
            else:
                raise ConfigurationError("The event handler {0} was initialized with a charge which is not None,"
                                         " but its potential {1} "
                                         "expects not exactly 2 charges."
                                         .format(self.__class__.__name__, self._potential.__class__.__name__))
    def __init__(self, potential: Potential, lifting: Lifting, offset: float, max_displacement: float,
                 separations: Sequence[int]) -> None:
        """
        The constructor of the FixedSeparationsEventHandlerWithPiecewiseConstantBoundingPotential class.

        Parameters
        ----------
        potential : potential.Potential
            The potential between the leaf units.
        lifting : lifting.Lifting
            The lifting scheme.
        offset : float
            The offset used to create piecewise constant bounding potential.
        max_displacement : float
            The maximum time displacement used to create piecewise constant bounding potential.
        separations : Sequence[int]
            A sequence of integers in the format [i1, j1, i2, j2...in, jn]. The separations passed to the potential
            will be [r_j1 - r_i1, r_j2 - r_i2, ..., r_jn - r_in].

        Raises
        ------
        base.exceptions.ConfigurationError:
            If the separations sequence is not divisible by two.
        base.exceptions.ConfigurationError:
            If the number of separations which can be constructed from the separations sequence does not equal the
            number of separation arguments of the potential.
        """
        log_init_arguments(logging.getLogger(__name__).debug, self.__class__.__name__,
                           potential=potential.__class__.__name__,
                           lifting=lifting.__class__.__name__, offset=offset, max_displacement=max_displacement,
                           separations=separations)
        super().__init__(potential=potential, offset=offset, max_displacement=max_displacement)
        self._lifting = lifting
        self._separations = separations
        if len(self._separations) % 2 != 0:
            raise ConfigurationError("The given array of indices {0} which should be used to calculate the separations"
                                     " handed over to the potential is not divisible by two!".format(separations))
        if self._potential.number_separation_arguments != len(self._separations) // 2:
            raise ConfigurationError("The event handler {0} expects a potential "
                                     "which handles exactly the number of separations specified"
                                     " by the list of identifiers {1} used to calculate these separations"
                                     " (length of the list divided by 2)!"
                                     .format(self.__class__.__name__, self._separations))
        # The charges the potential expects will always be set to 1.0
        self._number_charges = self._potential.number_charge_arguments