o
    Ni44                     @   sp  d dl mZ d dlZd dlZd dlZd dlZddlmZ g dZ	dd e	D Z
dd	 Zd
d Zdd Zdd Zdd Zdd Zd<ddZdd Ze dd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% ZG d&d' d'ejjZG d(d) d)ejjZG d*d+ d+ejjZG d,d- d-eZ G d.d/ d/ejjZ!d0d1 Z"G d2d3 d3ej#j$Z%d4d5 Z&d6d7 Z'd8d9 Z(d:d; Z)dS )=    )EnumN   )combine_event_functions)callback_stepcallback_accept_stepcallback_reject_stepc                 C   s   g | ]}|d  qS )_adjoint ).0namer	   r	   J/home/ubuntu/.local/lib/python3.10/site-packages/torchdiffeq/_impl/misc.py
<listcomp>
       r   c                  O   s   d S Nr	   )argskwargsr	   r	   r   <lambda>   s    r   c                 C   s*   t |dkrtd| jj| d S d S )Nr   z{}: Unexpected arguments {})lenwarningswarnformat	__class____name__)solverunused_kwargsr	   r	   r   _handle_unused_kwargs   s   r   c                 C   s   |    S r   )absmaxtensorr	   r	   r   
_linf_norm   s   r    c                 C   s   |   d  S )N   )r   powmeansqrtr   r	   r	   r   	_rms_norm      r%   c                 C   s   dS )N        r	   r   r	   r	   r   
_zero_norm   s   r(   c                 C   s"   t | dkrdS tdd | D S )Nr   r'   c                 S   s   g | ]}t |qS r	   )r%   )r
   r   r	   r	   r   r   !   r   z_mixed_norm.<locals>.<listcomp>)r   r   )tensor_tupler	   r	   r   _mixed_norm   s   r*   c                 C   s4  |j }|j}	|j }
||
}|du r| ||}|t||  }|||  }|||  }|dk s8|dk rAtjd||	d}nd| | }| }|||  }| || |}t||| | | }|dkr||dkr|ttjd||	d|d }ndt|| dt|d	   }| }td
| ||
S )a  Empirically select a good initial step.

    The algorithm is described in [1]_.

    References
    ----------
    .. [1] E. Hairer, S. P. Norsett G. Wanner, "Solving Ordinary Differential
           Equations I: Nonstiff Problems", Sec. II.4, 2nd edition.
    Ngh㈵>gư>dtypedeviceg{Gz?gV瞯<gMbP?      ?r   d   )	r,   r-   totorchr   r   r   floatmin)funct0y0orderrtolatolnormf0r,   r-   t_dtypescaled0d1h0y1f1d2h1r	   r	   r   _select_initial_step$   s*   

rE   c                 C   s,   ||t | |   }|| |  S r   )r1   r   r   )error_estimater8   r9   r6   rA   r:   	error_tolr	   r	   r   _compute_error_ratioP   s   rH   c                 C   sr   |dkr| | S |dk rt jd| j| jd}|| }t j|| j| jd }t |t |||  |}| | S )z-Calculate the optimal size for the next step.r   r   r	   r+   )	r1   onesr,   r-   type_asr   
reciprocalr3   r   )	last_steperror_ratiosafetyifactordfactorr7   exponentfactorr	   r	   r   _optimal_step_sizeU   s   
rS   c                 C   s   | dd  | d d k   S )Nr   )all)tr	   r	   r   _decreasingb   s   rW   c                 C   s   |  dksJ d| d S )Nr   {} must be one dimensional)
ndimensionr   r   rV   r	   r	   r   _assert_one_dimensionalf   s   r[   c                 C   s.   |dd  |d d k  sJ d| d S )Nr   rT   ,{} must be strictly increasing or decreasing)rU   r   rZ   r	   r	   r   _assert_increasingj   s   .r]   c                 C   s"   t |std| | d S )Nz0`{}` must be a floating point Tensor but is a {})r1   is_floating_point	TypeErrorr   typerZ   r	   r	   r   _assert_floatingn   s   
ra   c                 C   sh   zt | W n ty   | Y S w t|}t|t|ks%J d| dd t||D }t|S )Nz?If using tupled {} it must have the same length as the tuple y0c                 S   s$   g | ]\}}t || qS r	   )r1   	as_tensorexpandnumel)r
   tol_shaper	   r	   r   r   z   s   $ z_tuple_tol.<locals>.<listcomp>)iterr_   tupler   r   zipr1   cat)r   tolshapesr	   r	   r   
_tuple_tols   s   
rm   c                 C   sP   g }d}|D ]}||   }|| d||f g ||R  |}qt|S )Nr   .)rd   appendviewrh   )r   lengthrl   tensor_listtotalrf   
next_totalr	   r	   r   _flat_to_shape~   s   &rt   c                       $   e Zd Z fddZdd Z  ZS )
_TupleFuncc                       t t|   || _|| _d S r   )superrv   __init__	base_funcrl   selfrz   rl   r   r	   r   ry         
z_TupleFunc.__init__c                 C   s*   |  |t|d| j}tdd |D S )Nr	   c                 S      g | ]}| d qS rT   reshape)r
   f_r	   r	   r   r          z&_TupleFunc.forward.<locals>.<listcomp>)rz   rt   rl   r1   rj   )r|   rV   yfr	   r	   r   forward   s   z_TupleFunc.forwardr   
__module____qualname__ry   r   __classcell__r	   r	   r}   r   rv          rv   c                       ru   )_TupleInputOnlyFuncc                    rw   r   )rx   r   ry   rz   rl   r{   r}   r	   r   ry      r~   z_TupleInputOnlyFunc.__init__c                 C   s   |  |t|d| jS Nr	   )rz   rt   rl   r|   rV   r   r	   r	   r   r      r&   z_TupleInputOnlyFunc.forwardr   r	   r	   r}   r   r      r   r   c                       s&   e Zd Zd fdd	Zdd Z  ZS )_ReverseFuncr.   c                    rw   r   )rx   r   ry   rz   mul)r|   rz   r   r}   r	   r   ry      r~   z_ReverseFunc.__init__c                 C   s   | j | | | S r   )r   rz   r   r	   r	   r   r      s   z_ReverseFunc.forward)r.   r   r	   r	   r}   r   r      s    r   c                   @   s   e Zd ZdZdZdZdS )Perturbr   r   r!   N)r   r   r   NONEPREVNEXTr	   r	   r	   r   r      s    r   c                       s,   e Zd Z fddZejdddZ  ZS )_PerturbFuncc                    s   t t|   || _d S r   )rx   r   ry   rz   )r|   rz   r}   r	   r   ry      s   
z_PerturbFunc.__init__)perturbc                C   st   t |ts	J dt|r|j}|| j}|tju r&t	||d }n|tj
u r3t	||d }n	 | ||S )Nz-perturb argument must be of type Perturb enumr   )
isinstancer   r1   
is_complexrealr0   r   r,   r   
_nextafterr   rz   )r|   rV   r   r   r	   r	   r   r      s   


z_PerturbFunc.forward)r   r   r   ry   r   r   r   r   r	   r	   r}   r   r      s    r   c	              
      sd  |d urt |dkrtdt | dt||d |}| }	d t|tj }
|
r]t|ts2J ddd |D td|}td	|}td
d |D }t	| } |d ur]t
|}|d u rdi }n| }|d u rnd}||vrtd|dd|  d |
rd|v r|d ntfdd}||d< n	d|v rnt|d< td|d d}t |dkr|d |d krd}|r| }t| dd} |d urt|}z|d  W n	 ty   Y n	w  fdd|d< t|d t|d td| t|r|jrJ dt|r|jrJ d|j|jkr%td  ||j}t| } t }tD ]@}zt|	|}W n t yH   t!| |t" Y q.w |t"urg|#| |
r^|ffd!d"	}|rg|fd#d"}t!| || q.t$D ]}zt|	|}W n t y   Y qqw t!| || qq||| %  }t |dkrtd$|| | ||||||||f
S )%Nr!   zCWe require len(t) == 2 when in event handling mode, but got len(t)=.r   z+y0 must be either a torch.Tensor or a tuplec                 S   s   g | ]}|j qS r	   )rf   r
   y0_r	   r	   r   r      s    z!_check_inputs.<locals>.<listcomp>r8   r9   c                 S   r   r   r   r   r	   r	   r   r      r   dopri5z&Invalid method "{}". Must be one of {}z{"z", "z"}.r:   c                    s   t | d} |S r   rt   )r   r   )r:   rl   r	   r   _norm   s   z_check_inputs.<locals>._normrV   TFr   g      )r   grid_constructorc                    s    | ||  S r   r	   )r4   r6   rV   )_grid_constructorr	   r   r   !  s    z_check_inputs.<locals>.<lambda>step_tjump_tzrtol cannot require gradientzatol cannot require gradientz9t is not on the same device as y0. Coercing to y0.device.c                    s   t |d }|| ||S r   r   r5   r6   dt	_callback)rl   r	   r   callbackF  s   z_check_inputs.<locals>.callbackc                 S   s   ||  ||S r   r	   r   r	   r	   r   r   J  s   z)Solver '{}' does not support callbacks {})&r   
ValueErrorr   r   r1   Tensorrh   rm   rj   rv   r   copyr   joinkeysr*   r%   _check_timeliker   KeyError_flip_optionr]   	is_tensorrequires_gradr-   r   r   r0   r   set_all_callback_namesgetattrAttributeErrorsetattr_null_callbackadd_all_adjoint_callback_namesvalid_callbacks)r4   r6   rV   r8   r9   methodoptionsevent_fnSOLVERSoriginal_funcis_tupler   t_is_reversedcallback_namescallback_namer   invalid_callbacksr	   )r   r:   rl   r   _check_inputs   s   









r   c                   @   s$   e Zd Zedd Zedd ZdS )_StitchGradientc                 C   s   |S r   r	   )ctxx1outr	   r	   r   r   ]  s   z_StitchGradient.forwardc                 C   s   |d fS r   r	   )r   grad_outr	   r	   r   backwarda  s   z_StitchGradient.backwardN)r   r   r   staticmethodr   r   r	   r	   r	   r   r   \  s
    
r   c                 C   sV   t   tt drt | |}nt| |}W d    n1 s w   Y  t| |S )N	nextafter)r1   no_gradhasattrr   np_nextafterr   apply)r   x2r   r	   r	   r   r   f  s   


r   c                 C   sF   t d |    }|   }tt||	| }|S )Nztorch.nextafter is only available in PyTorch 1.7 or newer.Falling back to numpy.nextafter. Upgrade PyTorch to remove this warning.)
r   r   detachcpunumpyr1   r   npr   r0   )r   r   x1_npx2_npr   r	   r	   r   r   o  s
   
r   c                 C   s   t |tjsJ d| t| | | dksJ d| |s+|jr+J d| |dd  |d d k}| sG|  sIJ d| d S d S )Nz{} must be a torch.Tensorr   rX   z{} cannot require gradientrT   r\   )r   r1   r   r   ra   rY   r   rU   )r   timelikecan_graddiffr	   r	   r   r   x  s   
(r   c                 C   s@   z| | }W n
 t y   Y d S w t|tjr| | |< d S d S r   )r   r   r1   r   )r   option_nameoption_valuer	   r	   r   r     s   r   r   )*enumr   mathr   r   r1   r   event_handlingr   r   r   r   r   r    r%   r(   r*   rE   rH   r   rS   rW   r[   r]   ra   rm   rt   nnModulerv   r   r   r   r   r   autogradFunctionr   r   r   r   r   r	   r	   r	   r   <module>   sH    
,


 
		
