class SimulationLoopHagedornInhomogeneous(SimulationLoop):
    r"""This class acts as the main simulation loop. It owns a propagator that
    propagates a set of initial values during a time evolution.
    """
    def __init__(self, parameters, resultsfile):
        r"""Create a new simulation loop instance for a simulation
        using the semiclassical Hagedorn wavepacket based propagation
        method.

        :param parameters: The simulation parameters.
        :type parameters: A :py:class:`ParameterProvider` instance.
        :param resultsfile: Path and filename of the hdf5 output file.
        """
        # Keep a reference to the simulation parameters
        self.parameters = parameters

        # The time propagator instance driving the simulation.
        self.propagator = None

        # A `IOManager` instance for saving simulation results.
        self.IOManager = None

        # The time manager
        self._tm = TimeManager(self.parameters)

        # Set up serialization of simulation data
        self.IOManager = IOManager()
        self.IOManager.create_file(resultsfile)

        # Save the simulation parameters
        self.IOManager.add_parameters()
        self.IOManager.save_parameters(parameters)

    def prepare_simulation(self):
        r"""Set up a Hagedorn propagator for the simulation loop. Set the
        potential and initial values according to the configuration.

        :raise: :py:class:`ValueError` For invalid or missing input data.
        """
        BF = BlockFactory()

        # The potential instance
        potential = BF.create_potential(self.parameters)

        # Project the initial values to the canonical basis
        BT = BasisTransformationHAWP(potential)

        # Finally create and initialize the propagator instance
        # TODO: Attach the "leading_component to the hawp as codata
        self.propagator = BF.create_propagator(self.parameters, potential)

        # Create suitable wavepackets
        for packet_descr in self.parameters["initvals"]:
            packet = BF.create_wavepacket(packet_descr)
            # Transform to canonical basis
            BT.set_matrix_builder(packet.get_innerproduct())
            BT.transform_to_canonical(packet)
            # And hand over
            self.propagator.add_wavepacket((packet, ))

        # Add storage for each packet
        npackets = len(self.parameters["initvals"])
        slots = self._tm.compute_number_events()
        key = ("q", "p", "Q", "P", "S", "adQ")

        for i in range(npackets):
            bid = self.IOManager.create_block(
                dt=self.parameters.get("dt", 0.0))
            self.IOManager.add_inhomogwavepacket(self.parameters,
                                                 timeslots=slots,
                                                 blockid=bid,
                                                 key=key)

        # Write some initial values to disk
        for packet in self.propagator.get_wavepackets():
            self.IOManager.save_inhomogwavepacket_description(
                packet.get_description())

        if self._tm.is_event(0):
            for packet in self.propagator.get_wavepackets():
                # Pi
                self.IOManager.save_inhomogwavepacket_parameters(
                    packet.get_parameters(key=key), timestep=0, key=key)
                # Basis shapes
                for shape in packet.get_basis_shapes():
                    self.IOManager.save_inhomogwavepacket_basisshapes(shape)
                # Coefficients
                self.IOManager.save_inhomogwavepacket_coefficients(
                    packet.get_coefficients(),
                    packet.get_basis_shapes(),
                    timestep=0)

    def run_simulation(self):
        r"""Run the simulation loop for a number of time steps.
        """
        # The number of time steps we will perform.
        nsteps = self._tm.compute_number_timesteps()

        # Which parameter data to save.
        key = ("q", "p", "Q", "P", "S", "adQ")

        # Run the prepropagate step
        self.propagator.pre_propagate()
        # Note: We do not save any data here

        # Run the simulation for a given number of timesteps
        for i in range(1, nsteps + 1):
            print(" doing timestep {}".format(i))

            self.propagator.propagate()

            # Save some simulation data
            if self._tm.is_event(i):
                # Run the postpropagate step
                self.propagator.post_propagate()

                # TODO: Generalize for arbitrary number of wavepackets
                packets = self.propagator.get_wavepackets()
                assert len(packets) == 1

                for packet in packets:
                    # Pi
                    self.IOManager.save_inhomogwavepacket_parameters(
                        packet.get_parameters(key=key), timestep=i, key=key)
                    # Basis shapes (in case they changed!)
                    for shape in packet.get_basis_shapes():
                        self.IOManager.save_inhomogwavepacket_basisshapes(
                            shape)
                    # Coefficients
                    self.IOManager.save_inhomogwavepacket_coefficients(
                        packet.get_coefficients(),
                        packet.get_basis_shapes(),
                        timestep=i)

                # Run the prepropagate step
                self.propagator.pre_propagate()

        # Run the postpropagate step
        self.propagator.post_propagate()
        # Note: We do not save any data here

    def end_simulation(self):
        r"""Do the necessary cleanup after a simulation. For example request the
        :py:class:`IOManager` to write the data and close the output files.
        """
        self.IOManager.finalize()
Ejemplo n.º 2
0
class SimulationLoopFourier(SimulationLoop):
    """This class acts as the main simulation loop. It owns a propagator that
    propagates a set of initial values during a time evolution.
    """
    def __init__(self, parameters, resultsfile):
        """Create a new simulation loop instance for a simulation
        using the Fourier propagation method.

        :param parameters: The simulation parameters.
        :type parameters: A :py:class:`ParameterProvider` instance.
        :param resultsfile: Path and filename of the hdf5 output file.
        """
        # Keep a reference to the simulation parameters
        self.parameters = parameters

        # The time propagator instance driving the simulation.
        self.propagator = None

        # An `IOManager` instance for saving simulation results.
        self.IOManager = None

        # Which data do we want to save
        self._tm = self.parameters.get_timemanager()

        # Set up serialization of simulation data
        self.IOManager = IOManager()
        self.IOManager.create_file(resultsfile)
        self.IOManager.create_block(dt=self.parameters.get("dt", 0.0))

        # Save the simulation parameters
        self.IOManager.add_parameters()
        self.IOManager.save_parameters(parameters)

    def prepare_simulation(self):
        r"""Set up a Fourier propagator for the simulation loop. Set the
        potential and initial values according to the configuration.

        :raise: :py:class:`ValueError` For invalid or missing input data.
        """
        BF = BlockFactory()

        # The potential instance
        potential = BF.create_potential(self.parameters)

        # Compute the position space grid points
        grid = BF.create_grid(self.parameters)

        # Construct initial values
        I = Initializer(self.parameters)
        initialvalues = I.initialize_for_fourier(grid)

        # Transform the initial values to the canonical basis
        BT = BasisTransformationWF(potential)
        BT.set_grid(grid)
        BT.transform_to_canonical(initialvalues)

        # Finally create and initialize the propagator instance
        self.propagator = BF.create_propagator(self.parameters, potential,
                                               initialvalues)

        # Write some initial values to disk
        slots = self._tm.compute_number_events()

        self.IOManager.add_grid(self.parameters, blockid="global")
        self.IOManager.add_fourieroperators(self.parameters)
        self.IOManager.add_wavefunction(self.parameters, timeslots=slots)

        self.IOManager.save_grid(grid.get_nodes(flat=True), blockid="global")
        self.IOManager.save_fourieroperators(self.propagator.get_operators())
        if self._tm.is_event(0):
            self.IOManager.save_wavefunction(initialvalues.get_values(),
                                             timestep=0)

    def run_simulation(self):
        r"""Run the simulation loop for a number of time steps.
        """
        # The number of time steps we will perform.
        nsteps = self._tm.compute_number_timesteps()

        # Run the prepropagate step
        self.propagator.pre_propagate()
        # Note: We do not save any data here

        # Run the simulation for a given number of timesteps
        for i in range(1, nsteps + 1):
            print(" doing timestep {}".format(i))

            self.propagator.propagate()

            # Save some simulation data
            if self._tm.is_event(i):
                # Run the postpropagate step
                self.propagator.post_propagate()
                self.IOManager.save_wavefunction(
                    self.propagator.get_wavefunction().get_values(),
                    timestep=i)
                # Run the prepropagate step
                self.propagator.pre_propagate()

        # Run the postpropagate step
        self.propagator.post_propagate()
        # Note: We do not save any data here

    def end_simulation(self):
        """Do the necessary cleanup after a simulation. For example request the
        :py:class:`IOManager` to write the data and close the output files.
        """
        self.IOManager.finalize()
class SimulationLoopHagedornInhomogeneous(SimulationLoop):
    r"""This class acts as the main simulation loop. It owns a propagator that
    propagates a set of initial values during a time evolution.
    """

    def __init__(self, parameters, resultsfile):
        r"""Create a new simulation loop instance for a simulation
        using the semiclassical Hagedorn wavepacket based propagation
        method.

        :param parameters: The simulation parameters.
        :type parameters: A :py:class:`ParameterProvider` instance.
        :param resultsfile: Path and filename of the hdf5 output file.
        """
        # Keep a reference to the simulation parameters
        self.parameters = parameters

        # The time propagator instance driving the simulation.
        self.propagator = None

        # A `IOManager` instance for saving simulation results.
        self.IOManager = None

        # The time manager
        self._tm = TimeManager(self.parameters)

        # Set up serialization of simulation data
        self.IOManager = IOManager()
        self.IOManager.create_file(resultsfile)

        # Save the simulation parameters
        self.IOManager.add_parameters()
        self.IOManager.save_parameters(parameters)


    def prepare_simulation(self):
        r"""Set up a Hagedorn propagator for the simulation loop. Set the
        potential and initial values according to the configuration.

        :raise: :py:class:`ValueError` For invalid or missing input data.
        """
        # The potential instance
        potential = BlockFactory().create_potential(self.parameters)

        # Project the initial values to the canonical basis
        BT = BasisTransformationHAWP(potential)

        # Finally create and initialize the propagator instance
        # TODO: Attach the "leading_component to the hawp as codata
        self.propagator = HagedornPropagatorInhomogeneous(self.parameters, potential)

        # Create suitable wavepackets
        for packet_descr in self.parameters["initvals"]:
            packet = BlockFactory().create_wavepacket(packet_descr)
            # Transform to canonical basis
            BT.set_matrix_builder(packet.get_innerproduct())
            BT.transform_to_canonical(packet)
            # And hand over
            self.propagator.add_wavepacket((packet,))

        # Add storage for each packet
        npackets = len(self.parameters["initvals"])
        slots = self._tm.compute_number_events()
        key = ("q", "p", "Q", "P", "S", "adQ")

        for i in range(npackets):
            bid = self.IOManager.create_block()
            self.IOManager.add_inhomogwavepacket(self.parameters, timeslots=slots, blockid=bid, key=key)

        # Write some initial values to disk
        for packet in self.propagator.get_wavepackets():
            self.IOManager.save_inhomogwavepacket_description(packet.get_description())

        if self._tm.is_event(0):
            for packet in self.propagator.get_wavepackets():
                # Pi
                self.IOManager.save_inhomogwavepacket_parameters(packet.get_parameters(key=key), timestep=0, key=key)
                # Basis shapes
                for shape in packet.get_basis_shapes():
                    self.IOManager.save_inhomogwavepacket_basisshapes(shape)
                # Coefficients
                self.IOManager.save_inhomogwavepacket_coefficients(packet.get_coefficients(), packet.get_basis_shapes(), timestep=0)


    def run_simulation(self):
        r"""Run the simulation loop for a number of time steps.
        """
        # The number of time steps we will perform.
        nsteps = self._tm.compute_number_timesteps()

        # Which parameter data to save.
        key = ("q", "p", "Q", "P", "S", "adQ")

        # Run the prepropagate step
        self.propagator.pre_propagate()
        # Note: We do not save any data here

        # Run the simulation for a given number of timesteps
        for i in range(1, nsteps + 1):
            print(" doing timestep {}".format(i))

            self.propagator.propagate()

            # Save some simulation data
            if self._tm.is_event(i):
                # Run the postpropagate step
                self.propagator.post_propagate()

                # TODO: Generalize for arbitrary number of wavepackets
                packets = self.propagator.get_wavepackets()
                assert len(packets) == 1

                for packet in packets:
                    # Pi
                    self.IOManager.save_inhomogwavepacket_parameters(packet.get_parameters(key=key), timestep=i, key=key)
                    # Basis shapes (in case they changed!)
                    for shape in packet.get_basis_shapes():
                        self.IOManager.save_inhomogwavepacket_basisshapes(shape)
                    # Coefficients
                    self.IOManager.save_inhomogwavepacket_coefficients(packet.get_coefficients(), packet.get_basis_shapes(), timestep=i)

                # Run the prepropagate step
                self.propagator.pre_propagate()

        # Run the postpropagate step
        self.propagator.post_propagate()
        # Note: We do not save any data here


    def end_simulation(self):
        r"""Do the necessary cleanup after a simulation. For example request the
        :py:class:`IOManager` to write the data and close the output files.
        """
        self.IOManager.finalize()
class SimulationLoopFourier(SimulationLoop):
    """This class acts as the main simulation loop. It owns a propagator that
    propagates a set of initial values during a time evolution.
    """

    def __init__(self, parameters, resultsfile):
        """Create a new simulation loop instance for a simulation
        using the Fourier propagation method.

        :param parameters: The simulation parameters.
        :type parameters: A :py:class:`ParameterProvider` instance.
        :param resultsfile: Path and filename of the hdf5 output file.
        """
        # Keep a reference to the simulation parameters
        self.parameters = parameters

        # The time propagator instance driving the simulation.
        self.propagator = None

        # An `IOManager` instance for saving simulation results.
        self.IOManager = None

        # Which data do we want to save
        self._tm = self.parameters.get_timemanager()

        # Set up serialization of simulation data
        self.IOManager = IOManager()
        self.IOManager.create_file(resultsfile)
        self.IOManager.create_block(dt=self.parameters.get("dt", 0.0))

        # Save the simulation parameters
        self.IOManager.add_parameters()
        self.IOManager.save_parameters(parameters)

    def prepare_simulation(self):
        r"""Set up a Fourier propagator for the simulation loop. Set the
        potential and initial values according to the configuration.

        :raise: :py:class:`ValueError` For invalid or missing input data.
        """
        BF = BlockFactory()

        # The potential instance
        potential = BF.create_potential(self.parameters)

        # Compute the position space grid points
        grid = BF.create_grid(self.parameters)

        # Construct initial values
        I = Initializer(self.parameters)
        initialvalues = I.initialize_for_fourier(grid)

        # Transform the initial values to the canonical basis
        BT = BasisTransformationWF(potential)
        BT.set_grid(grid)
        BT.transform_to_canonical(initialvalues)

        # Finally create and initialize the propagator instance
        self.propagator = BF.create_propagator(self.parameters, potential, initialvalues)

        # Write some initial values to disk
        slots = self._tm.compute_number_events()

        self.IOManager.add_grid(self.parameters, blockid="global")
        self.IOManager.add_fourieroperators(self.parameters)
        self.IOManager.add_wavefunction(self.parameters, timeslots=slots)

        self.IOManager.save_grid(grid.get_nodes(flat=True), blockid="global")
        self.IOManager.save_fourieroperators(self.propagator.get_operators())
        if self._tm.is_event(0):
            self.IOManager.save_wavefunction(initialvalues.get_values(), timestep=0)

    def run_simulation(self):
        r"""Run the simulation loop for a number of time steps.
        """
        # The number of time steps we will perform.
        nsteps = self._tm.compute_number_timesteps()

        # Run the prepropagate step
        self.propagator.pre_propagate()
        # Note: We do not save any data here

        # Run the simulation for a given number of timesteps
        for i in range(1, nsteps + 1):
            print(" doing timestep {}".format(i))

            self.propagator.propagate()

            # Save some simulation data
            if self._tm.is_event(i):
                # Run the postpropagate step
                self.propagator.post_propagate()
                self.IOManager.save_wavefunction(self.propagator.get_wavefunction().get_values(), timestep=i)
                # Run the prepropagate step
                self.propagator.pre_propagate()

        # Run the postpropagate step
        self.propagator.post_propagate()
        # Note: We do not save any data here

    def end_simulation(self):
        """Do the necessary cleanup after a simulation. For example request the
        :py:class:`IOManager` to write the data and close the output files.
        """
        self.IOManager.finalize()