o
    EbC                     @   s   d dl Zd dlmZmZ d dlmZmZmZ d dl	m
Z
 d dlmZ ddlmZmZmZmZmZmZmZmZ ddlmZmZ d	Zd
ZdZdZdd Zdd Zdd ZG dd deZ G dd deZ!dS )    N)	lu_factorlu_solve)issparse
csc_matrixeye)splu)group_columns   )validate_max_stepvalidate_tolselect_initial_stepnormEPSnum_jacvalidate_first_stepwarn_extraneous)	OdeSolverDenseOutput      g?
   c                 C   s|   t d| d dddf }t d| d }t | d | d f}|d ||  | |ddddf< d|d< t j|ddS )z6Compute the matrix for changing the differences array.r	   Nr   Zaxis)nparangeZzeroscumprod)orderfactorIJM r    :/usr/lib/python3/dist-packages/scipy/integrate/_ivp/bdf.py	compute_R   s   $r"   c                 C   sH   t ||}t |d}||}t|j| d|d  | d|d < dS )z<Change differences array in-place when step size is changed.r	   N)r"   dotr   T)Dr   r   RUZRUr    r    r!   change_D   s   


*r(   c	                 C   s   d}	|  }
d}d}ttD ]e}| ||
}tt|s nU|||| | |	 }t|| }|du r7d}n|| }|durS|dksQ|t|  d|  | |krS n!|
|7 }
|	|7 }	|dksm|durq|d|  | |k rqd} n|}q||d |
|	fS )z5Solve the algebraic system resulting from BDF method.r   NFr	   T)copyrangeNEWTON_MAXITERr   allZisfiniter   )funt_new	y_predictcpsiLUsolve_luscaleZtoldyZdy_norm_old	convergedkfZdyZdy_normZrater    r    r!   solve_bdf_system$   s8   
r:   c                       sJ   e Zd ZdZejddddddf fdd	Zdd	 Zd
d Zdd Z	  Z
S )BDFa  Implicit method based on backward-differentiation formulas.

    This is a variable order method with the order varying automatically from
    1 to 5. The general framework of the BDF algorithm is described in [1]_.
    This class implements a quasi-constant step size as explained in [2]_.
    The error estimation strategy for the constant-step BDF is derived in [3]_.
    An accuracy enhancement using modified formulas (NDF) [2]_ is also implemented.

    Can be applied in the complex domain.

    Parameters
    ----------
    fun : callable
        Right-hand side of the system. The calling signature is ``fun(t, y)``.
        Here ``t`` is a scalar, and there are two options for the ndarray ``y``:
        It can either have shape (n,); then ``fun`` must return array_like with
        shape (n,). Alternatively it can have shape (n, k); then ``fun``
        must return an array_like with shape (n, k), i.e. each column
        corresponds to a single column in ``y``. The choice between the two
        options is determined by `vectorized` argument (see below). The
        vectorized implementation allows a faster approximation of the Jacobian
        by finite differences (required for this solver).
    t0 : float
        Initial time.
    y0 : array_like, shape (n,)
        Initial state.
    t_bound : float
        Boundary time - the integration won't continue beyond it. It also
        determines the direction of the integration.
    first_step : float or None, optional
        Initial step size. Default is ``None`` which means that the algorithm
        should choose.
    max_step : float, optional
        Maximum allowed step size. Default is np.inf, i.e., the step size is not
        bounded and determined solely by the solver.
    rtol, atol : float and array_like, optional
        Relative and absolute tolerances. The solver keeps the local error
        estimates less than ``atol + rtol * abs(y)``. Here `rtol` controls a
        relative accuracy (number of correct digits), while `atol` controls
        absolute accuracy (number of correct decimal places). To achieve the
        desired `rtol`, set `atol` to be lower than the lowest value that can
        be expected from ``rtol * abs(y)`` so that `rtol` dominates the
        allowable error. If `atol` is larger than ``rtol * abs(y)`` the
        number of correct digits is not guaranteed. Conversely, to achieve the
        desired `atol` set `rtol` such that ``rtol * abs(y)`` is always lower
        than `atol`. If components of y have different scales, it might be
        beneficial to set different `atol` values for different components by
        passing array_like with shape (n,) for `atol`. Default values are
        1e-3 for `rtol` and 1e-6 for `atol`.
    jac : {None, array_like, sparse_matrix, callable}, optional
        Jacobian matrix of the right-hand side of the system with respect to y,
        required by this method. The Jacobian matrix has shape (n, n) and its
        element (i, j) is equal to ``d f_i / d y_j``.
        There are three ways to define the Jacobian:

            * If array_like or sparse_matrix, the Jacobian is assumed to
              be constant.
            * If callable, the Jacobian is assumed to depend on both
              t and y; it will be called as ``jac(t, y)`` as necessary.
              For the 'Radau' and 'BDF' methods, the return value might be a
              sparse matrix.
            * If None (default), the Jacobian will be approximated by
              finite differences.

        It is generally recommended to provide the Jacobian rather than
        relying on a finite-difference approximation.
    jac_sparsity : {None, array_like, sparse matrix}, optional
        Defines a sparsity structure of the Jacobian matrix for a
        finite-difference approximation. Its shape must be (n, n). This argument
        is ignored if `jac` is not `None`. If the Jacobian has only few non-zero
        elements in *each* row, providing the sparsity structure will greatly
        speed up the computations [4]_. A zero entry means that a corresponding
        element in the Jacobian is always zero. If None (default), the Jacobian
        is assumed to be dense.
    vectorized : bool, optional
        Whether `fun` is implemented in a vectorized fashion. Default is False.

    Attributes
    ----------
    n : int
        Number of equations.
    status : string
        Current status of the solver: 'running', 'finished' or 'failed'.
    t_bound : float
        Boundary time.
    direction : float
        Integration direction: +1 or -1.
    t : float
        Current time.
    y : ndarray
        Current state.
    t_old : float
        Previous time. None if no steps were made yet.
    step_size : float
        Size of the last successful step. None if no steps were made yet.
    nfev : int
        Number of evaluations of the right-hand side.
    njev : int
        Number of evaluations of the Jacobian.
    nlu : int
        Number of LU decompositions.

    References
    ----------
    .. [1] G. D. Byrne, A. C. Hindmarsh, "A Polyalgorithm for the Numerical
           Solution of Ordinary Differential Equations", ACM Transactions on
           Mathematical Software, Vol. 1, No. 1, pp. 71-96, March 1975.
    .. [2] L. F. Shampine, M. W. Reichelt, "THE MATLAB ODE SUITE", SIAM J. SCI.
           COMPUTE., Vol. 18, No. 1, pp. 1-22, January 1997.
    .. [3] E. Hairer, G. Wanner, "Solving Ordinary Differential Equations I:
           Nonstiff Problems", Sec. III.2.
    .. [4] A. Curtis, M. J. D. Powell, and J. Reid, "On the estimation of
           sparse Jacobian matrices", Journal of the Institute of Mathematics
           and its Applications, 13, pp. 117-120, 1974.
    gMbP?gư>NFc                    s  t | t j|||||
dd t| _t|| j\ _ _ 	 j
 j}|d u r?t j	 j
 j| jd j j _nt||| _d  _d  _tdt | td|d  _d  _ ||	\ _ _t jr fdd}d	d
 }t jd jjd}n fdd}dd
 }tj j jjd}| _| _ | _!t"g d}t#dt$dt%dt&d  f _'d|  j'  _(| j' dt%dt&d    _)tj*t&d  jf jjd} j|d< | j  j |d< | _+d _,d _-d  _.d S )NT)Zsupport_complexr	   r   gQ?      ?c                    s     j d7  _ t| S Nr	   )nlur   Aselfr    r!   lu   s   zBDF.__init__.<locals>.luc                 S   s
   |  |S )N)Zsolver2   br    r    r!   r3      s   
zBDF.__init__.<locals>.solve_luZcsc)formatdtypec                    s     j d7  _ t| ddS )Nr	   T)Zoverwrite_a)r>   r   r?   rA   r    r!   rC      s   c                 S   s   t | |ddS )NT)Zoverwrite_b)r   rD   r    r    r!   r3      s   rG   )r   gGzǿgqqgugsh|?r   r         )/r   super__init__r
   max_stepr   nrtolatolr-   tr6   r   	directionh_absr   Z	h_abs_oldZerror_norm_oldmaxr   min
newton_tol
jac_factor_validate_jacjacr   r   r   rG   r   identityrC   r3   r   arrayZhstackZcumsumr   	MAX_ORDERgammaalphaerror_constemptyr%   r   n_equal_stepsr2   )rB   r-   t0y0t_boundrM   rO   rP   rY   Zjac_sparsityZ
vectorizedZ
first_stepZ
extraneousr9   rC   r3   r   Zkappar%   	__class__rA   r!   rL      sN   

& 

zBDF.__init__c                    sX  j }j d u r.d urtrtt}|ffdd}||}||fS t r| |} jd7  _t|rRt|jd} fdd}ntj	|jd} fdd}|j
jjfkrxtdjjf|j
||fS t rt jd}ntj	 jd}|j
jjfkrtdjjf|j
d }||fS )Nc                    s>     j d7  _  | |}t j| || j j\} _|S r=   )njevZ
fun_singler   Zfun_vectorizedrP   rW   )rQ   r6   r9   r   )rB   sparsityr    r!   jac_wrapped  s   
z&BDF._validate_jac.<locals>.jac_wrappedr	   rH   c                    s"    j d7  _ t | |jdS Nr	   rH   )rg   r   rG   rQ   r6   rY   rB   rc   r    r!   ri     s   c                    s$    j d7  _ tj | |jdS rj   )rg   r   asarrayrG   rk   rl   r    r!   ri     s   z8`jac` is expected to have shape {}, but actually has {}.)rQ   r6   r   r   r   callablerg   rG   r   rm   shaperN   
ValueErrorrF   )rB   rY   rh   rb   groupsri   r   r    )rY   rB   rh   rc   r!   rX      sB   
!
zBDF._validate_jacc           &   
   C   s  | j }| j}| j}dtt|| jtj |  }| j|kr/|}t	|| j
|| j  d| _n| j|k rD|}t	|| j
|| j  d| _n| j}| j}| j}| j
}| j}	| j}
| j}| j}| j}| jd u }d}|sk||k rrd| jfS || j }|| }| j|| j  dkr| j}t	||t|| |  d| _d }|| }t|}tj|d |d  dd}||t|  }t|d|d  j|
d|d  |	|  }d}||	|  }|s|d u r| | j||  }t| j|||||| j|| j	\}}}}|s|rn| ||}d }d}|r|s$d}||9 }t	||| d| _d }qfdd	t d  d	t |  }||t|  }|| | }t || }|dkrgt!t"||d
|d    }||9 }t	||| d| _nd}|ri|  jd7  _|| _ || _#|| _|| _|| _|||d   ||d	 < |||d < t$t%|d D ]}||  ||d  7  < q| j|d k rdS |dkr||d  ||  }t || } ntj} |t&k r||d  ||d	   }!t |!| }"ntj}"t'| ||"g}#tj(dd |#d
t)||d   }$W d    n	1 sw   Y  t*|$d }%||%7 }|| _
t+t,|t!|$ }|  j|9  _t	||| d| _d | _dS )Nr   r   Fr	   r   Tr<   g?rI   )TNignore)ZdividerJ   )-rQ   r%   rM   r   absZ	nextafterrR   infrS   r(   r   ra   rP   rO   r^   r]   r_   r   r2   rY   ZTOO_SMALL_STEPrd   sumr#   r$   rC   r   r:   r-   r3   rV   r+   r   rT   
MIN_FACTORr6   reversedr*   r\   r[   Zerrstater   ZargmaxrU   
MAX_FACTOR)&rB   rQ   r%   rM   Zmin_steprS   rP   rO   r   r^   r]   r_   r   r2   Zcurrent_jacZstep_acceptedhr.   r/   r4   r1   r7   r0   Zn_iterZy_newr5   r   ZsafetyerrorZ
error_normiZerror_mZerror_m_normZerror_pZerror_p_normZerror_normsZfactorsZdelta_orderr    r    r!   
_step_impl,  s   "





.
@

zBDF._step_implc              	   C   s2   t | j| j| j| j | j| jd | jd   S r=   )BdfDenseOutputt_oldrQ   rS   rR   r   r%   r)   rA   r    r    r!   _dense_output_impl  s   zBDF._dense_output_impl)__name__
__module____qualname____doc__r   ru   rL   rX   r}   r   __classcell__r    r    re   r!   r;   H   s    s;5 r;   c                       s$   e Zd Z fddZdd Z  ZS )r~   c                    sL   t  || || _| j|t| j  | _|dt| j  | _|| _d S r=   )	rK   rL   r   rQ   r   r   t_shiftdenomr%   )rB   r   rQ   rz   r   r%   re   r    r!   rL     s
   
zBdfDenseOutput.__init__c                 C   s   |j dkr|| j | j }t|}n|| jd d d f  | jd d d f  }tj|dd}t| jdd  j|}|j dkrH|| jd 7 }|S || jdd d d f 7 }|S )Nr   r   r	   )ndimr   r   r   r   r#   r%   r$   )rB   rQ   xpr6   r    r    r!   
_call_impl  s   
(
zBdfDenseOutput._call_impl)r   r   r   rL   r   r   r    r    re   r!   r~     s    r~   )"Znumpyr   Zscipy.linalgr   r   Zscipy.sparser   r   r   Zscipy.sparse.linalgr   Zscipy.optimize._numdiffr   commonr
   r   r   r   r   r   r   r   baser   r   r\   r+   rw   ry   r"   r(   r:   r;   r~   r    r    r    r!   <module>   s$    (
$  z