qmat.solvers.dahlquist ====================== .. py:module:: qmat.solvers.dahlquist .. autoapi-nested-parse:: Solvers for the Dahlquist equation based on :math:`Q` coefficients, also implementing SDC sweeps with given :math:`Q_\Delta` coefficients. Classes ------- .. autoapisummary:: qmat.solvers.dahlquist.Dahlquist qmat.solvers.dahlquist.DahlquistIMEX Module Contents --------------- .. py:class:: Dahlquist(lam, u0=1, tEnd=1, nSteps=1) Solver for the classical Dahlquist equation .. math:: \frac{du}{dt} = \lambda u, \quad u(0)=u_0, \quad t \in [0,T]. It can be used to solve the equation with multiple :math:`\lambda` values (multiple trajectories) using efficient vectorized computation. Furthermore, it has no restriction on the used :math:`Q` and :math:`Q_\Delta` matrices (can be dense), which is not the case for the generic :class:`CoeffSolver` used with :class:`qmat.solvers.generic.diffops.Dahlquist`. :Parameters: * **lam** (*scalar or array*) -- Value(s) used for :math:`\lambda`. * **u0** (*scalar or array, optional*) -- Initial value :math:`\lambda`, must be compatible with `lam`. The default is 1. * **tEnd** (*float, optional*) -- Final simulation time :math:`T`. The default is 1. * **nSteps** (*float, optional*) -- Number of time-step to solve. The default is 1. .. py:attribute:: u0 :value: 1 initial solution value .. py:attribute:: tEnd :value: 1 final simulation time .. py:attribute:: nSteps :value: 1 number of time-steps .. py:attribute:: dt :value: 1.0 time-step size .. py:attribute:: lam array storing the :math:`\lambda` values .. py:attribute:: uShape shape of the solution at a given time .. py:attribute:: dtype solution datatype .. py:method:: checkCoeff(Q, weights) :staticmethod: Check :math:`Q` coefficients and associated weights. :Parameters: * **Q** (*2D array-like*) -- The :math:`Q` coefficients. * **weights** (*1D array-like*) -- Quadrature weights associated to the nodes. :returns: * **nNodes** (*int*) -- Number of nodes (stages). * **Q** (*np.2darray*) -- The :math:`Q` coefficients. * **weights** (*np.1darray*) -- Quadrature weights associated to the nodes. .. py:method:: solve(Q, weights) Solve for all :math:`\lambda` using a direct solve of the :math:`Q` matrix, *i.e* for each time-step it solves : .. math:: (I - \Delta{t}\lambda Q){\bf u} = {\bf u}_0, where :math:`{\bf u}_0` is the vector containing the initial solution of the time-step in each entry. The next step solution is computed using the **step update** : .. math:: u_1 = u_0 + \Delta{t}\lambda{\bf w}^T{\bf u}, or simply use the last **node solution** :math:`{\bf u}[-1]` if no weights are given (`weights=None`). :Parameters: * **Q** (*2D array-like*) -- The :math:`Q` coefficients. * **weights** (*1D array-like or None*) -- Quadrature weights associated to the nodes. If None, do not use them for the step update (requires last node equal to 1) :returns: **uNum** -- The solution at each time-steps (+ initial solution). :rtype: np.ndarray .. py:method:: checkCoeffSDC(Q, weights, QDelta, nSweeps) :staticmethod: Check SDC coefficients :Parameters: * **Q** (*2D array-like*) -- The :math:`Q` coefficients. * **weights** (*1D array-like*) -- Quadrature weights associated to the nodes. * **QDelta** (*2D or 3D array-like*) -- The :math:`Q_\Delta` coefficients (3D if changes with sweeps). * **nSweeps** (*int*) -- Number of sweeps. :returns: * **nNodes** (*int*) -- Number of nodes. * **Q** (*np.2darray*) -- The :math:`Q` coefficients. * **weights** (*np.1darray*) -- Quadrature weights associated to the nodes. * **QDelta** (*np.2darray*) -- The :math:`Q_\Delta` coefficients for each sweep. * **nSweeps** (*int*) -- The number of sweeps. .. py:method:: solveSDC(Q, weights, QDelta, nSweeps) Solve for all :math:`\lambda` using SDC sweeps, *i.e* solves for each time-step and sweep :math:`k` : .. math:: (I - \Delta{t}\lambda Q_\Delta){\bf u}^{k+1} = {\bf u}_0 + \Delta{t}\lambda(Q - Q_\Delta){\bf u}^{k}, where :math:`{\bf u}_0` is the vector containing the initial solution of the time-step in each entry and :math:`{\bf u}^0 = {\bf u}_0` (copy initialization). The next step solution is computed using the **step update** : .. math:: u_1 = u_0 + \Delta{t}\lambda{\bf w}^T{\bf u}^{K}, where :math:`K` is the total number of sweeps. If no weights are given (`weights=None`), it simply uses the last **node solution** :math:`{\bf u}[-1]`. :Parameters: * **Q** (*2D array-like*) -- The :math:`Q` coefficients. * **weights** (*1D array-like or None*) -- Quadrature weights associated to the nodes. If None, do not use them for the step update (requires last node equal to 1) * **QDelta** (*2D or 3D array-like*) -- The :math:`Q_\Delta` coefficients (3D if changes with sweeps). * **nSweeps** (*int*) -- Number of sweeps. :returns: **uNum** -- The solution at each time-steps (+ initial solution). :rtype: np.ndarray .. py:class:: DahlquistIMEX(lamI, lamE, u0=1, tEnd=1, nSteps=1) Solver for the IMEX Dahlquist equation .. math:: \frac{du}{dt} = (\lambda_I + \lambda_E) u, \quad u(0)=u_0, \quad t \in [0,T]. It can be used to solve the equation with multiple :math:`\lambda_I` and / or :math:`\lambda_E` values (multiple trajectories). :Parameters: * **lamI** (*TYPE*) -- Value(s) used for :math:`\lambda_I`.. * **lamE** (*scalar or array*) -- Value(s) used for :math:`\lambda_E`. * **u0** (*scalar or array, optional*) -- Initial value :math:`\lambda`, must be compatible with `lam`. The default is 1. * **tEnd** (*float, optional*) -- Final simulation time :math:`T`. The default is 1. * **nSteps** (*float, optional*) -- Number of time-step to solve. The default is 1. .. py:attribute:: u0 :value: 1 initial solution value .. py:attribute:: tEnd :value: 1 final simulation time .. py:attribute:: nSteps :value: 1 number of time-steps .. py:attribute:: dt :value: 1.0 time-step size .. py:attribute:: lamI array storing the :math:`\lambda_I` values .. py:attribute:: lamE array storing the :math:`\lambda_E` values .. py:attribute:: uShape shape of the solution at one given time .. py:attribute:: dtype datatype of the solution array .. py:method:: checkCoeff(QI, wI, QE, wE) :staticmethod: Check IMEX :math:`Q` coefficients and assert their consistency. :Parameters: * **QI** (*2D array-like*) -- :math:`Q` coefficients used for :math:`\lambda_I`. * **wI** (*1D array-like or None*) -- Weights used for the step update on :math:`\lambda_I`. If None, then step update is not done. * **QE** (*2D array-like*) -- :math:`Q` coefficients used for :math:`\lambda_E`. * **wE** (*1D array-like or None*) -- Weights used for the step update on :math:`\lambda_E`. If None, then step update is not done. :returns: * **nNodes** (*int*) -- Number of nodes. * **QI** (*np.2darray*) -- :math:`Q` coefficients used for :math:`\lambda_I`. * **wI** (*np.1darray or None*) -- Weights used for the step update on :math:`\lambda_I`. * **QE** (*np.2darray*) -- :math:`Q` coefficients used for :math:`\lambda_E`. * **wE** (*np.1darray or None*) -- Weights used for the step update on :math:`\lambda_E`. * **useWeights** (*boll*) -- Wether or not the step update (using weights) is done. .. py:method:: solve(QI, wI, QE, wE) Solve for all :math:`\lambda_I` and :math:`\lambda_E` using a direct solve of the :math:`Q^I` and :math:`Q^E` matrices, *i.e* for each time-step it solves : .. math:: (I - \lambda_I Q^I - \lambda_E Q^E){\bf u} = {\bf u}_0 where :math:`{\bf u}_0` is the vector containing the initial solution of the time-step in each entry. The next step solution is computed using the IMEX **step update** : .. math:: u_1 = u_0 + \Delta{t}\lambda_I{\bf w}_I^T{\bf u} + \Delta{t}\lambda_E{\bf w}_E^T{\bf u}, or simply use the last **node solution** :math:`{\bf u}[-1]` if no weights are given (`wI=wE=None`). :Parameters: * **QI** (*2D array-like*) -- :math:`Q^I` coefficients used for :math:`\lambda_I`. * **wI** (*1D array-like or None*) -- Weights used for the step update on :math:`\lambda_I`. If None, then step update is not done. * **QE** (*2D array-like*) -- :math:`Q^E` coefficients used for :math:`\lambda_E`. * **wE** (*1D array-like or None*) -- Weights used for the step update on :math:`\lambda_E`. If None, then step update is not done. :returns: **uNum** -- The solution at each time-steps (+ initial solution). :rtype: np.ndarray .. py:method:: checkCoeffSDC(Q, weights, QDeltaI, QDeltaE, nSweeps) :staticmethod: Check coefficients given for a IMEX SDC sweeps :Parameters: * **Q** (*2D array-like*) -- The :math:`Q` coefficients. * **weights** (*1D array-like or none*) -- Quadrature weights associated to the nodes. If None, last node is used for the step update. * **QDeltaE** (*2D or 3D array-like*) -- The :math:`Q_\Delta^I` coefficients used for the :math:`\lambda_I` term (3D if changes with sweeps). * **QDeltaE** (*2D or 3D array-like*) -- The :math:`Q_\Delta^E` coefficients used for the :math:`\lambda_E` term (3D if changes with sweeps). * **nSweeps** (*int*) -- Number of sweeps. :returns: * **nNodes** (*int*) -- Number of nodes. * **Q** (*np.2darray*) -- The :math:`Q` coefficients. * **weights** (*np.1darray*) -- Quadrature weights associated to the nodes. * **QDeltaI** (*np.3darray*) -- The :math:`Q_\Delta^I` coefficients used for the :math:`\lambda_I` term for each sweeps. * **QDeltaE** (*np.3darray*) -- The :math:`Q_\Delta^E` coefficients used for the :math:`\lambda_E` term for each sweeps. * **nSweeps** (*int*) -- Number of SDC sweeps. .. py:method:: solveSDC(Q, weights, QDeltaI, QDeltaE, nSweeps) Solve for all :math:`\lambda_I` and :math:`\lambda_E` using SDC sweeps, *i.e* for each time-step and sweep :math:`k` it solves : .. math:: (I - \Delta{t}\lambda_I Q_\Delta^I - \Delta{t}\lambda_E Q_\Delta^I){\bf u}^{k+1} = {\bf u}_0 + \Delta{t}\left[ \lambda Q - \lambda_I Q_\Delta^I - \lambda_E Q_\Delta^E\right] {\bf u}^{k}, where :math:`{\bf u}_0` is the vector containing the initial solution of the time-step in each entry and :math:`{\bf u}^0 = {\bf u}_0` (copy initialization). The next step solution is computed using the **step update** : .. math:: u_1 = u_0 + \Delta{t}\lambda{\bf w}^T{\bf u}^{K}, where :math:`K` is the total number of sweeps. If no weights are given (`weights=None`), it simply uses the last **node solution** :math:`{\bf u}[-1]`. :Parameters: * **Q** (*2D array-like*) -- The :math:`Q` coefficients. * **weights** (*1D array-like or none*) -- Quadrature weights associated to the nodes. If None, last node is used for the step update. * **QDeltaE** (*2D or 3D array-like*) -- The :math:`Q_\Delta^I` coefficients used for the :math:`\lambda_I` term (3D if changes with sweeps). * **QDeltaE** (*2D or 3D array-like*) -- The :math:`Q_\Delta^E` coefficients used for the :math:`\lambda_E` term (3D if changes with sweeps). * **nSweeps** (*int*) -- Number of sweeps. :returns: **uNum** -- The solution at each time-steps (+ initial solution). :rtype: np.ndarray