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 # TODO: Clean up this ugly if tree if self.parameters["propagator"] == "magnus_split": from MagnusPropagator import MagnusPropagator self.propagator = MagnusPropagator(self.parameters, potential) elif self.parameters["propagator"] == "semiclassical": from SemiclassicalPropagator import SemiclassicalPropagator self.propagator = SemiclassicalPropagator(self.parameters, potential) elif self.parameters["propagator"] == "hagedorn": from HagedornPropagator import HagedornPropagator self.propagator = HagedornPropagator(self.parameters, potential) else: raise NotImplementedError("Unknown propagator type: " + self.parameters["propagator"]) # Create suitable wavepackets chi = self.parameters["leading_component"] 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, chi)) # Add storage for each packet npackets = len(self.parameters["initvals"]) slots = self._tm.compute_number_saves() key = ("q","p","Q","P","S","adQ") for i in xrange(npackets): bid = self.IOManager.create_block() self.IOManager.add_wavepacket(self.parameters, timeslots=slots, blockid=bid, key=key) # Write some initial values to disk for packet in self.propagator.get_wavepackets(): self.IOManager.save_wavepacket_description(packet.get_description()) # Pi self.IOManager.save_wavepacket_parameters(packet.get_parameters(key=key), timestep=0, key=key) # Basis shapes for shape in packet.get_basis_shapes(): self.IOManager.save_wavepacket_basisshapes(shape) # Coefficients self.IOManager.save_wavepacket_coefficients(packet.get_coefficients(), packet.get_basis_shapes(), timestep=0)
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 ValueError: For invalid or missing input data. """ potential = PF().create_potential(self.parameters) N = potential.get_number_components() # Check for enough initial values if self.parameters["leading_component"] > N: raise ValueError("Leading component index out of range.") if len(self.parameters["parameters"]) < N: raise ValueError("Too few initial states given. Parameters are missing.") if len(self.parameters["coefficients"]) < N: raise ValueError("Too few initial states given. Coefficients are missing.") # Create a suitable wave packet packet = HagedornWavepacket(self.parameters) # See if we have a list of parameter tuples or just a single 5-tuple # This is for compatibility with the inhomogeneous case. try: # We have a list of parameter tuples, take the one given by the leading component len(self.parameters["parameters"][0]) parameters = self.parameters["parameters"][self.parameters["leading_component"]] except TypeError: # We have just a single 5-tuple of parameters, take it. parameters = self.parameters["parameters"] # Set the Hagedorn parameters packet.set_parameters(parameters) packet.set_quadrature(None) # Set the initial values for component, data in enumerate(self.parameters["coefficients"]): for index, value in data: packet.set_coefficient(component, index, value) # Project the initial values to the canonical basis packet.project_to_canonical(potential) # Finally create and initialize the propagator instace self.propagator = HagedornPropagator(potential, packet, self.parameters["leading_component"], self.parameters) # Which data do we want to save tm = self.parameters.get_timemanager() slots = tm.compute_number_saves() self.IOManager.add_grid(self.parameters, blockid="global") self.IOManager.add_wavepacket(self.parameters, timeslots=slots) # Write some initial values to disk nodes = self.parameters["f"] * sp.pi * sp.arange(-1, 1, 2.0 / self.parameters["ngn"], dtype=np.complexfloating) self.IOManager.save_grid(nodes, blockid="global") self.IOManager.save_wavepacket_parameters(self.propagator.get_wavepackets().get_parameters(), timestep=0) self.IOManager.save_wavepacket_coefficients(self.propagator.get_wavepackets().get_coefficients(), timestep=0)
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 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 instace # TODO: Attach the "leading_component to the hawp as codata self.propagator = HagedornPropagator(self.parameters, potential) # Create suitable wavepackets chi = self.parameters["leading_component"] for packet_descr in self.parameters["initvals"]: packet = BlockFactory().create_wavepacket(packet_descr) # Transform to canonical basis BT.set_matrix_builder(packet.get_quadrature()) BT.transform_to_canonical(packet) # And hand over self.propagator.add_wavepacket((packet, chi)) # Add storage for each packet npackets = len(self.parameters["initvals"]) slots = self._tm.compute_number_saves() for i in xrange(npackets): bid = self.IOManager.create_block() self.IOManager.add_wavepacket(self.parameters, timeslots=slots, blockid=bid) # Write some initial values to disk for packet in self.propagator.get_wavepackets(): self.IOManager.save_wavepacket_description(packet.get_description()) # Pi self.IOManager.save_wavepacket_parameters(packet.get_parameters(), timestep=0) # Basis shapes for shape in packet.get_basis_shape(): self.IOManager.save_wavepacket_basisshapes(shape) # Coefficients self.IOManager.save_wavepacket_coefficients(packet.get_coefficients(), packet.get_basis_shape(), timestep=0)
class SimulationLoopHagedorn(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. All values are read from the ``Parameters.py`` file. """ def __init__(self, parameters): r""" Create a new simulation loop instance. """ # 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 number of time steps we will perform. self.nsteps = parameters["nsteps"] # Set up serializing of simulation data self.IOManager = IOManager() self.IOManager.create_file(self.parameters) self.IOManager.create_block() 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 ValueError: For invalid or missing input data. """ potential = PF().create_potential(self.parameters) N = potential.get_number_components() # Check for enough initial values if self.parameters["leading_component"] > N: raise ValueError("Leading component index out of range.") if len(self.parameters["parameters"]) < N: raise ValueError("Too few initial states given. Parameters are missing.") if len(self.parameters["coefficients"]) < N: raise ValueError("Too few initial states given. Coefficients are missing.") # Create a suitable wave packet packet = HagedornWavepacket(self.parameters) # See if we have a list of parameter tuples or just a single 5-tuple # This is for compatibility with the inhomogeneous case. try: # We have a list of parameter tuples, take the one given by the leading component len(self.parameters["parameters"][0]) parameters = self.parameters["parameters"][self.parameters["leading_component"]] except TypeError: # We have just a single 5-tuple of parameters, take it. parameters = self.parameters["parameters"] # Set the Hagedorn parameters packet.set_parameters(parameters) packet.set_quadrature(None) # Set the initial values for component, data in enumerate(self.parameters["coefficients"]): for index, value in data: packet.set_coefficient(component, index, value) # Project the initial values to the canonical basis packet.project_to_canonical(potential) # Finally create and initialize the propagator instace self.propagator = HagedornPropagator(potential, packet, self.parameters["leading_component"], self.parameters) # Which data do we want to save tm = self.parameters.get_timemanager() slots = tm.compute_number_saves() self.IOManager.add_grid(self.parameters, blockid="global") self.IOManager.add_wavepacket(self.parameters, timeslots=slots) # Write some initial values to disk nodes = self.parameters["f"] * sp.pi * sp.arange(-1, 1, 2.0 / self.parameters["ngn"], dtype=np.complexfloating) self.IOManager.save_grid(nodes, blockid="global") self.IOManager.save_wavepacket_parameters(self.propagator.get_wavepackets().get_parameters(), timestep=0) self.IOManager.save_wavepacket_coefficients(self.propagator.get_wavepackets().get_coefficients(), timestep=0) def run_simulation(self): r""" Run the simulation loop for a number of time steps. The number of steps is calculated in the ``initialize`` function. """ tm = self.parameters.get_timemanager() # Run the simulation for a given number of timesteps for i in xrange(1, self.nsteps + 1): print(" doing timestep " + str(i)) self.propagator.propagate() # Save some simulation data if tm.must_save(i): self.IOManager.save_wavepacket_parameters( self.propagator.get_wavepackets().get_parameters(), timestep=i ) self.IOManager.save_wavepacket_coefficients( self.propagator.get_wavepackets().get_coefficients(), timestep=i ) def end_simulation(self): r""" Do the necessary cleanup after a simulation. For example request the IOManager to write the data and close the output files. """ self.IOManager.finalize()
class SimulationLoopHagedorn(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): 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. """ # 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(self.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 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 instace # TODO: Attach the "leading_component to the hawp as codata self.propagator = HagedornPropagator(self.parameters, potential) # Create suitable wavepackets chi = self.parameters["leading_component"] for packet_descr in self.parameters["initvals"]: packet = BlockFactory().create_wavepacket(packet_descr) # Transform to canonical basis BT.set_matrix_builder(packet.get_quadrature()) BT.transform_to_canonical(packet) # And hand over self.propagator.add_wavepacket((packet, chi)) # Add storage for each packet npackets = len(self.parameters["initvals"]) slots = self._tm.compute_number_saves() for i in xrange(npackets): bid = self.IOManager.create_block() self.IOManager.add_wavepacket(self.parameters, timeslots=slots, blockid=bid) # Write some initial values to disk for packet in self.propagator.get_wavepackets(): self.IOManager.save_wavepacket_description(packet.get_description()) # Pi self.IOManager.save_wavepacket_parameters(packet.get_parameters(), timestep=0) # Basis shapes for shape in packet.get_basis_shape(): self.IOManager.save_wavepacket_basisshapes(shape) # Coefficients self.IOManager.save_wavepacket_coefficients(packet.get_coefficients(), packet.get_basis_shape(), 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 simulation for a given number of timesteps for i in xrange(1, nsteps+1): print(" doing timestep "+str(i)) self.propagator.propagate() # Save some simulation data if self._tm.must_save(i): # TODO: Generalize for arbitrary number of wavepackets packets = self.propagator.get_wavepackets() assert len(packets) == 1 for packet in packets: # Pi self.IOManager.save_wavepacket_parameters(packet.get_parameters(), timestep=i) # Basis shapes (in case they changed!) for shape in packet.get_basis_shape(): self.IOManager.save_wavepacket_basisshapes(shape) # Coefficients self.IOManager.save_wavepacket_coefficients(packet.get_coefficients(), packet.get_basis_shape(), timestep=i) 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()