wavepacket ========== .. py:module:: wavepacket .. autoapi-nested-parse:: A package for solving Schrödinger and Liouville von Neumann equations. .. !! processed by numpydoc !! Submodules ---------- .. toctree:: :maxdepth: 1 /autoapi/wavepacket/builder/index /autoapi/wavepacket/expression/index /autoapi/wavepacket/grid/index /autoapi/wavepacket/operator/index /autoapi/wavepacket/plot/index /autoapi/wavepacket/solver/index /autoapi/wavepacket/special/index /autoapi/wavepacket/testing/index /autoapi/wavepacket/typing/index Exceptions ---------- .. autoapisummary:: wavepacket.BadFunctionCall wavepacket.BadGridError wavepacket.BadStateError wavepacket.ExecutionError wavepacket.InvalidValueError Functions --------- .. autoapisummary:: wavepacket.log wavepacket.dvr_density wavepacket.fbr_density wavepacket.normalize wavepacket.orthonormalize wavepacket.population wavepacket.trace wavepacket.diagonalize wavepacket.expectation_value Package Contents ---------------- .. py:exception:: BadFunctionCall Bases: :py:obj:`Exception` Signals that a function was called incorrectly. A typical but rare use-case would be a function that was called with incorrect parameters. .. !! processed by numpydoc !! .. py:exception:: BadGridError Bases: :py:obj:`Exception` An invalid grid was supplied. Most often, you attempt an operation between objects that must be defined on the same grid. For example, the addition of two operators defined on different grids is not a useful operation. The grid may also miss required properties, for example an operation may expect a specific degree of freedom type along some index. .. !! processed by numpydoc !! .. py:exception:: BadStateError Bases: :py:obj:`Exception` An invalid state was supplied. Either the state is completely invalid (neither wave function nor density operator), or you supplied the wrong type of state to a function, for example passing a density operator where a wave function was required. .. !! processed by numpydoc !! .. py:exception:: ExecutionError Bases: :py:obj:`Exception` An unrecoverable problem was encountered in foreign code. The main example is the :py:class:`wavepacket.solver.odesolver` getting an error back while integrating. .. !! processed by numpydoc !! .. py:exception:: InvalidValueError Bases: :py:obj:`Exception` A function argument was incorrect, for example out of bounds. .. !! processed by numpydoc !! .. py:function:: log(t: float, state: wavepacket.grid.State, precision: int = 6) -> None Prints some data about the state for inspection. The idea is that you call this function during every solver step and get a log with the most important values about the propagation, for example the state trace (if it deviates from one, this may be caused by poor convergence). :Parameters: **t** : float The time at which you log. **state** : wp.grid.State The state to log. **precision** : int, default=6 How many decimal places should be printed. .. !! processed by numpydoc !! .. py:function:: dvr_density(state: wavepacket.grid.State, dof_index: int | None = None) -> wavepacket.typing.RealData Returns the density of the input state at the DVR grid points. The density is returned as a real-valued coefficient array with the same shape as the underlying grid. The density is mostly a dead end: useful for plotting and inspection, but not for further computations. Note that this function returns the density in DVR, that is, the raw density values without grid weights or such. These are not useful for computations, but can be plotted or otherwise inspected. :Parameters: **state** : wp.grid.State The state (wave function or density operator) whose density should be computed. **dof_index: int|None, default=None** If set, return the reduced density, i.e., the density integrated over all degrees of freedom except the one with the given index. :Returns: wpt.RealData The coefficient array of the density values at the DVR grid points. :Raises: wp.BadStateError If the supplied state is neither a wave function nor a density operator. IndexError If the dof_index is out of range. .. !! processed by numpydoc !! .. py:function:: fbr_density(state: wavepacket.grid.State, dof_index: int | None = None) -> wavepacket.typing.RealData Returns the FBR density of the input state at the FBR grid points. The density is returned as a real-valued coefficient array with the same shape as the underlying grid. The density is mostly a dead end: useful for plotting and inspection, but not for further computations. Note that this function returns the FBR density, i.e., the coefficients or diagonal when expanding the wave function or density operator in the underlying grid's basis, respectively. :Parameters: **state** : wp.grid.State The state (wave function or density operator) whose FBR density should be computed. **dof_index: int | None, default=None** If set, return the reduced density, i.e., the density integrated over all degrees of freedom except the one with the given index. :Returns: wpt.RealData The coefficient array of the FBR density values at the FBR grid points. :Raises: wp.BadStateError If the supplied state is neither a wave function nor a density operator. IndexError If the dof_index is out of range. .. !! processed by numpydoc !! .. py:function:: normalize(state: wavepacket.grid.State) -> wavepacket.grid.State Normalizes the input state. :Parameters: **state** : wp.grid.State The state (wave function or density operator) that should be normalized. :Returns: wp.grid.State The normalized input state. :Raises: wp.BadStateError If the supplied state is neither a wave function nor a density operator. .. !! processed by numpydoc !! .. py:function:: orthonormalize(states: collections.abc.Sequence[wavepacket.grid.State]) -> list[wavepacket.grid.State] Orthogonalizes and normalizes a set of linearly independent wave functions. This function does a simple Gram-Schmidt orthogonalization followed by a normalization of the resulting orthogonal vectors. As such, it is not efficient for a large number of vectors, and produces artifacts for linearly dependent vectors. :Parameters: **states: Sequence[wp.grid.State]** The wave functions to orthonormalize. Must be linearly independent. May be empty or contain only one element, in which case the normalized wave function is returned. :Returns: list[State] A set of wave functions that span the same subspace as the input, but are normalized and orthogonal. The first element is just the normalized state of the first input, the second element has the first input projected out, the third element has the first two inputs projected out etc. :Raises: wp.BadGridError Raised if the input states are defined on different grids. wp.BadStateError Raised if any input state is either not a wave function or has zero trace. .. !! processed by numpydoc !! .. py:function:: population(state: wavepacket.grid.State, target: wavepacket.grid.State) -> float Calculates how much a target state is populated in a given state. The return value is simply the absolute square of the scalar product of the two states. The target state is normalized before the calculation. This operation can be thought of as a shortcut for creating a :py:class:`wp.operator.Projection` with the target and calculating the :py:func:`wp.expectation_value` of the input state. :Parameters: **state: wp.grid.State** The state that is projected onto the target state **target: wp.grid.State** The wave function onto which the input state is projected. This function is normalized before use. :Raises: wp.BadGridError Raised if the input and the target state are defined on different grids. wp.BadStateError Raised if the target is not a wave function. .. seealso:: :obj:`wavepacket.operator.Projection` For advanced calculations .. !! processed by numpydoc !! .. py:function:: trace(state: wavepacket.grid.State) -> float Returns the trace of the supplied input state. For density operators, this is the usual trace norm, i.e., sum over the diagonal elements. For wave functions, it is the square of the usual L2 norm. :Parameters: **state** : wp.grid.State The state (wave function or density operator) for which to calculate the trace. :Returns: float The trace of the input state. :Raises: wp.BadStateError If the supplied state is neither a wave function nor a density operator. .. !! processed by numpydoc !! .. py:function:: diagonalize(op: wavepacket.operator.OperatorBase, t: float | None = None) -> Iterator[tuple[float, wavepacket.typing.ComplexData]] Calculates the eigenstates and -values of an operator. See :doc:`/tutorials/eigenstates` for a discussion of this topic. This function is a wrapper around `numpy.linalg.eigh` that calculates a matrix representation of the operator transforms the calculated eigenstates into a :py:class:`wp.grid.State` for easier consumption, and provides a generator for looping instead of a matrix with all eigenvalues in one go. This function diagonalizes a full, dense operator matrix, so it requires Typically, you solve the eigenproblem for time-independent operators, but you can also calculate instantaneous states and energies by specifying a time value. :Parameters: **op: wp.operator.OperatorBase** The operator whose eigenstates and -values are calculated. **t: float | None = None** The time at which the operator is evaluated. Required only for time-dependent operators. :Yields: Tuples consisting of the eigenenergy and the eigenstate of the operator. .. The output is sorted by the eigenvalues. .. :Raises: wp.InvalidValueError If no time was supplied for a time-dependent operator .. rubric:: Examples Iterate over the eigenvalues and -vectors >>> hamiltonian = ... >>> for energy, state in wp.diagonalize(hamiltonian): >>> print(f'E = {energy}, trace norm = {wp.trace(state)}') .. !! processed by numpydoc !! .. py:function:: expectation_value(op: wavepacket.operator.OperatorBase, state: wavepacket.grid.State, t: float | None = None) -> complex Calculates the expectation value of an operator for a given state. :Parameters: **op** : wp.operator.OperatorBase The operator whose expectation value is calculated. **state** : wp.grid.State The wave function or density operator that is used for the calculation. **t** : float | None The time at which the operator should be evaluated. Only required for time-dependent operators. :Raises: InvalidValueError If a time-dependent operator was supplied, but no time value was given. .. !! processed by numpydoc !!