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

        :raise ValueError: For invalid or missing input data.
        """
        potential = PotentialFactory().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)
        packet.set_parameters(self.parameters["parameters"][self.parameters["leading_component"]])
        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
        inner = HagedornPropagator(potential, packet, self.parameters["leading_component"], self.parameters)
        self.propagator = SpawnAdiabaticPropagator(inner, potential, packet, self.parameters["leading_component"], self.parameters)

        # Write some initial values to disk
        slots = self.tm.compute_number_saves()
        for packet in self.propagator.get_wavepackets():
            bid = self.iom.create_block(groupid=self.gid)
            self.iom.add_wavepacket(self.parameters, timeslots=slots, blockid=bid)
            self.iom.save_wavepacket_coefficients(packet.get_coefficients(), blockid=bid, timestep=0)
            self.iom.save_wavepacket_parameters(packet.get_parameters(), blockid=bid, timestep=0)
class SimulationLoopSpawnAdiabatic(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

        self.tm = TimeManager(parameters)

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

        #: A ``IOManager`` instance for saving simulation results.
        self.iom = IOManager()
        self.iom.create_file(parameters)
        self.gid = self.iom.create_group()


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

        :raise ValueError: For invalid or missing input data.
        """
        potential = PotentialFactory().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)
        packet.set_parameters(self.parameters["parameters"][self.parameters["leading_component"]])
        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
        inner = HagedornPropagator(potential, packet, self.parameters["leading_component"], self.parameters)
        self.propagator = SpawnAdiabaticPropagator(inner, potential, packet, self.parameters["leading_component"], self.parameters)

        # Write some initial values to disk
        slots = self.tm.compute_number_saves()
        for packet in self.propagator.get_wavepackets():
            bid = self.iom.create_block(groupid=self.gid)
            self.iom.add_wavepacket(self.parameters, timeslots=slots, blockid=bid)
            self.iom.save_wavepacket_coefficients(packet.get_coefficients(), blockid=bid, timestep=0)
            self.iom.save_wavepacket_parameters(packet.get_parameters(), blockid=bid, 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.tm

        # Run the simulation for a given number of timesteps
        for i in xrange(1, tm.get_nsteps()+1):
            print(" doing timestep "+str(i))

            self.propagator.propagate(tm.compute_time(i))

            # Save some simulation data
            if tm.must_save(i):
                # Check if we need more data blocks for newly spawned packets
                while self.iom.get_number_blocks(groupid=self.gid) < self.propagator.get_number_packets():
                    bid = self.iom.create_block(groupid=self.gid)
                    self.iom.add_wavepacket(self.parameters, blockid=bid)

                for index, packet in enumerate(self.propagator.get_wavepackets()):
                    self.iom.save_wavepacket_coefficients(packet.get_coefficients(), timestep=i, blockid=index)
                    self.iom.save_wavepacket_parameters(packet.get_parameters(), timestep=i, blockid=index)


    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.iom.finalize()