o
    Nii?                     @   s   d dl Z d dlZd dlZddlm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 edd	Zed
dZG dd dejjZdd ZdZdZdZd ddZd ddZd!ddZd!ddZG dd deZdd ZdS )"    N   )
find_event)_interp_evaluate_interp_fit)_compute_error_ratio_select_initial_step_optimal_step_size)Perturb)AdaptiveStepsizeEventODESolver_ButcherTableauzalpha, beta, c_sol, c_error_RungeKuttaStatez y1, f1, t0, t1, dt, interp_coeffc                   @   s$   e Zd Zedd Zedd ZdS )_UncheckedAssignc                 C   s   || _ ||j|< |S N)indexdata)ctxscratchvaluer    r   O/home/ubuntu/.local/lib/python3.10/site-packages/torchdiffeq/_impl/rk_common.pyforward   s   
z_UncheckedAssign.forwardc                 C   s   ||| j  d fS r   )r   )r   grad_scratchr   r   r   backward$   s   z_UncheckedAssign.backwardN)__name__
__module____qualname__staticmethodr   r   r   r   r   r   r      s
    
r   c                 C   sx  |  j}||}||}||}tjg |jt|jd R |j|jd}t	
||d}tt|j|jD ]C\}	\}
}|
dkrJ|}tj}n	||
|  }tj}|tj|dd|	d f ||  dd| }| |||d	}t	
||d|	d f}q:|jd d
kr|jdd |jd k s|tj|||j  dd| }|}|d }tj|||j  dd}||||fS )a  Take an arbitrary Runge-Kutta step and estimate error.
    Args:
        func: Function to evaluate like `func(t, y)` to compute the time derivative of `y`.
        y0: Tensor initial value for the state.
        f0: Tensor initial value for the derivative, computed from `func(t0, y0)`.
        t0: float64 scalar Tensor giving the initial time.
        dt: float64 scalar Tensor giving the size of the desired time step.
        t1: float64 scalar Tensor giving the end time; equal to t0 + dt. This is used (rather than t0 + dt) to ensure
            floating point accuracy when needed.
        tableau: _ButcherTableau describing how to take the Runge-Kutta step.
    Returns:
        Tuple `(y1, f1, y1_error, k)` giving the estimated function value after
        the Runge-Kutta step at `t1 = t0 + dt`, the derivative of the state at `t1`,
        estimated error at `t1`, and a list of Runge-Kutta coefficients `k` used for
        calculating these terms.
    r   dtypedevice.r   g      ?.Ndimperturbr   .r!   )absr   totorchemptyshapelenalphar   r   apply	enumeratezipbetar	   PREVNONEsumview_asc_solallc_error)funcy0f0t0dtt1tableaut_dtypekialpha_ibeta_itir%   yify1f1y1_errorr   r   r   _runge_kutta_step)   s*   



,0*"rK   gUUUUUU?gUUUUUU?gUUUUUU?Fc                 C   s   |}|d u r| |||rt jnt jd}|d }| || |||  }	| || |||	  }
| ||||
  |r9t jnt jd}|d|	|
   | | t S )Nr$   g      ?   )r	   NEXTr3   r2   
_one_sixth)r9   r<   r=   r>   r:   r;   r%   k1half_dtk2k3k4r   r   r   rk4_step_funca   s   "rT   c                 C   s   |}|du r| |||rt jnt jd}| ||t  ||| t  }| ||t  ||||t    }	| ||||| |	   |rCt jnt jd}
|d||	   |
 | d S )z)Smaller error with slightly more compute.Nr$      g      ?)r	   rM   r3   
_one_third_two_thirdsr2   )r9   r<   r=   r>   r:   r;   r%   rO   rQ   rR   rS   r   r   r   rk4_alt_step_funcl   s   "*rX   c                 C   s   |}|du r| |||rt jnt jd}| |||d d   ||| |d d   }	| |||d d   ||||d d  |	|d d     }
|||d d  |	|d d   |
|d d    S )a	  butcher_tableu should be of the form
    
    [
        [0  , 0     , 0     ,   0],
        [c_2, a_{21}, 0     ,   0],
        [c_3, a_{31}, a_{32},   0],
        [0  , b_1   , b_2   , b_3],
    ]

    https://en.wikipedia.org/wiki/List_of_Runge-Kutta_methods
    Nr$   r   r   rL   rU   )r	   rM   r3   )r9   r<   r=   r>   r:   butcher_tableur;   r%   rO   rQ   rR   r   r   r   rk3_step_funcw   s   .>4rZ   c           
      C   s   |}|du r| |||rt jnt jd}| |||d d   ||| |d d   |r-t jnt jd}	|||d d  |	|d d    S )zbutcher_tableu should be of the form

    [
        [0  , 0     , 0     ],
        [c_2, a_{21}, 0     ],
        [0  , b_1   , b_2   ],
    ]

    https://en.wikipedia.org/wiki/List_of_Runge-Kutta_methods
    Nr$   r   r   rL   )r	   rM   r3   r2   )
r9   r<   r=   r>   r:   rY   r;   r%   rO   rQ   r   r   r   rk2_step_func   s
   >$r[   c                
       s   e Zd ZU eed< eed< ejed< deddddddd	d
ej	f
 fdd	Z
e fddZdd Zdd Zdd Zdd Zdd Z  ZS )RKAdaptiveStepsizeODESolverorderr?   midr   infNg?g      $@g?ic                    s  t t| jd|d| t| j}j || _tj	|| d| _
tj	|| d| _tj	|| d| _tj	|| d| _|d u rGd ntj	|| d| _tj	|
| d| _tj	|| d| _tj	|| d| _tj	|tj d| _|| _|d u r~d ntj	|| d| _|	d u rd ntj	|	| d| _t| jjj jd fdd| jjD | jjj jd| jjj jdd| _| jj jd| _d S )N)r   r:   r   r   r   c                    s   g | ]
}|j  jd qS )r`   )r(   r   ).0br   r:   r   r   
<listcomp>   s    z8RKAdaptiveStepsizeODESolver.__init__.<locals>.<listcomp>)r-   r1   r6   r8   r   )superr\   __init__r)   promote_typesr'   r   r   r9   	as_tensorrtolatolmin_stepmax_step
first_stepsafetyifactordfactorint32max_num_stepsstep_tjump_tr   r?   r-   r(   r1   r6   r8   r^   )selfr9   r:   ri   rj   rk   rl   rm   rs   rt   rn   ro   rp   rr   r   kwargs	__class__rc   r   rf      s,   z$RKAdaptiveStepsizeODESolver.__init__c                    s   t t|  h dB S )N>   callback_stepcallback_accept_stepcallback_reject_step)re   r\   valid_callbacks)clsrw   r   r   r|      s   z+RKAdaptiveStepsizeODESolver.valid_callbacksc              
   C   s  |d }|  |d | j}| jd u r)t| j |d | j| jd | j| j| j|d}n| j}t| j||d |d || jgd | _	| j
d u rPtjg | j| jjd}nt| j
|}|| j}| jd u rmtjg | j| jjd}nt| j|}|| j}t||gjddd }|dk rtd|| _
|| _tt| j
 |d t| j
d | _tt| j |d t| jd | _d S )	Nr   r   )r;      r   T)return_countszG`step_t` and `jump_t` must not have any repeated elements between them.)r9   r:   rm   r   r]   ri   rj   normr   rk_staters   r)   tensorr   r   _sort_tvalsr(   rt   catuniqueany
ValueErrorminbisecttolistr,   next_step_indexnext_jump_index)ru   tr<   r;   rm   rs   rt   countsr   r   r   _before_integrate   s.   
 &

(,z-RKAdaptiveStepsizeODESolver._before_integratec                 C   sh   d}|| j jkr'|| jk sJ d|| j| | j | _ |d7 }|| j jkst| j j| j j| j j|S )zBInterpolate through the next time point, integrating as necessary.r   max_num_steps exceeded ({}>={})r   )r   r>   rr   format_adaptive_stepr   interp_coeffr<   )ru   next_tn_stepsr   r   r   _advance   s   z$RKAdaptiveStepsizeODESolver._advancec                    s   | j j j jdkr j j j jfS d}t| j j j j}|t| j j j jkrV| jk s=J d| j  j  _ |d7 }|t| j j j jks/ fdd}t|| j j	 j j| j
S )z9Returns t, state(t) such that event_fn(t, state(t)) == 0.r   r   r   c                    s   t  jj jj jj| S r   )r   r   r   r<   r>   )r   ru   r   r   <lambda>  s    zBRKAdaptiveStepsizeODESolver._advance_until_event.<locals>.<lambda>)r   r>   rH   r)   signrr   r   r   r   r<   rj   )ru   event_fnr   sign0	interp_fnr   r   r   _advance_until_event   s   z0RKAdaptiveStepsizeODESolver._advance_until_eventc              	   C   s^  |\}}}}}}t |s| j}|| j| j}| j||| || }|| |ks3J d| t |	 sAJ d|d}	t
| jrd| j| j }
||
  k oY|| k n  }	|	rd|
}|| }d}t
| jr| j| j }||  k o||| k n  }|rd}	|}|| }t| j|||||| jd\}}}}t|| j| j||| j}|dk}|| jkrd}|| jkrd}|r| j||| |}|}| ||||}|	r| jt
| jd kr|  jd7  _|r| jt
| jd kr|  jd7  _| j||tjd}|}n| j||| |}|}|}t||| j| j| j| j}|| j| j}t||||||}|S )z7Take an adaptive Runge-Kutta step to integrate the ODE.zunderflow in dt {}z"non-finite values in state `y`: {}F)r?   r   Tr$   ) r)   isfiniterk   clamprl   r9   ry   r   itemr7   r,   rs   r   rt   r   rK   r?   r   ri   rj   r   rz   r   r	   rM   r{   r   rn   ro   rp   r]   r   )ru   r   r:   r;   _r<   r=   r   r>   	on_step_tnext_step_t	on_jump_tnext_jump_trH   rI   rJ   rA   error_ratioaccept_stept_nexty_nextf_nextdt_nextr   r   r   r     sf   


"


z*RKAdaptiveStepsizeODESolver._adaptive_stepc                 C   sN   | |}|tj||| j  dd| }|d }|d }t||||||S )zEFit an interpolating polynomial to the results of a Runge-Kutta step.r!   r"   r    r&   )type_asr)   r4   r^   r5   r   )ru   r:   rH   rA   r=   y_midr;   rI   r   r   r   r   i  s
   
"z'RKAdaptiveStepsizeODESolver._interp_fit)r   r   r   int__annotations__r   r)   Tensorfloatfloat64rf   classmethodr|   r   r   r   r   r   __classcell__r   r   rw   r   r\      s,   
 
)	ar\   c                 C   s   | | |k } t | jS r   )r)   sortvalues)tvalsr<   r   r   r   r   r  s   r   )NF)NNF)r   collectionsr)   event_handlingr   interpr   r   miscr   r   r   r	   solversr
   
namedtupler   r   autogradFunctionr   rK   rV   rW   rN   rT   rX   rZ   r[   r\   r   r   r   r   r   <module>   s,    3



 T