+
    ‰°³j´&  ã                   óŽ   € ^ RI H t  ^RIHt  ! R R]4      tR tR	R lt]]n        ]R8X  d   ^ RIt]P                  ! 4        R# R# )
é    )Úbisect)Úxrangec                   ó   € ] tR t^tRtR# )Ú
ODEMethods© N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__static_attributes__r   ó    ÚU/home/luca/screen-checking/.venv/lib/python3.14/site-packages/mpmath/calculus/odes.pyr   r      s   † Ûr   r   c                 ó  € V P                  ^V) 4      ;rg\        V4      pV.p	V.p
TpTpV P                  p V^V,           ,          V n        \        V4       Fr  pV! W¼4      p\	        \        V4      4       Uu. uF  qìV,          WoV,          ,          ,           NK!  	  ppW¶,          pV	P                  V4       V
P                  V4       Kt  	  \        V4       Uu. uF  p. NK  	  pp\        V^,           4       EF   p^ .V,          pRV^,          ,          p^p\        V^,           4       Ff  p\        V4       F,  pVV;;,          VW®,          V,          ,          ,          uu&   K.  	  VVV,
          ^,           ,          V) ,          pV^,          pKh  	  VV) ,          V P                  V4      ,          p\        V4       F5  pVV,          V,          VV&   VV,          P                  VV,          4       K7  	  EK  	  WÐn        V P                  pV FG  pVR,          '       g   K  \        VV P                  V\        VR,          4      ,          V4      4      pKI  	  V^,          pVVV,           3# u upi u upi   YÐn        i ; i)é   éÿÿÿÿ)ÚldexpÚlenÚprecÚranger   ÚappendÚfacÚoneÚminÚnthrootÚabs)ÚctxÚderivsÚx0Úy0Útol_precÚnÚhÚtolÚdimÚxsÚysÚxÚyÚorigÚiÚfxyÚdÚserÚjÚsÚbÚkÚscaleÚradiusÚtss   &&&&&&                   r   Ú
ode_taylorr5      s  € Ø�i‰i˜˜H˜9Ó%Ð%€AÜ
ˆb‹'€CØ
ˆ€BØ
ˆ€BØ
€AØ
€AØ�8‰8€DðØ˜˜1�•:ˆŒô �q–ˆAÙ˜“,ˆCÜ(.¬s°1«v¬Ó7© 1�1•�a˜A�•h—�©ˆAÐ7Ø�FˆAØ�I‰I�aŒLØ�I‰I�aŽLñ ô ! œ:Ó&™:�a‹r™:ˆÐ&Ü�q˜•s—ˆAØ��C•ˆAØ˜˜Q�•ˆAØˆAÜ˜1˜Q�3–Z�Ü˜sž�AØ�a—D˜A ¥ a¥�LÕ(•Dñ $à˜!˜A�#˜a�%•[ q bÕ)�Ø�Q•’ñ	  ð
 ˜˜•G˜cŸg™g a›jÕ(ˆEÜ˜3–Z�Ø˜•t˜e•|��!‘Ø�A•—‘˜a �dÖ#ô  ñ ð Œð �W‰W€FÛˆØˆb�6Ž6Ü˜ §¡¨S´°R¸µV³­_¸aÓ!@ÓAŠFñ ð ˆa…K€FØ��6•	ˆ>Ðùò9 8ùò
 'øð �ús+   ·AI; Á8%I1Â=I; ÃI6Ã%DI; É1
I; É;JNc           	     óø  a aaaaaaaaaaaa€ V'       d%   \        S P                  V^4      ) 4      ^
,           oMS P                  ^
,           oS;'       g+    ^\        ^S P                  ,          R,          4      ,           oS P                  ^(,           o \	        V4       Ro\        S SSVSS4      w  r‰SV	.oVSV	3.oV 3R loVV VVVVVVV3	R loV VVVV3R lp
V
#   \
         d    SoT3R loT.pRo LVi ; i)aÇ  
Returns a function `y(x) = [y_0(x), y_1(x), \ldots, y_n(x)]`
that is a numerical solution of the `n+1`-dimensional first-order
ordinary differential equation (ODE) system

.. math ::

    y_0'(x) = F_0(x, [y_0(x), y_1(x), \ldots, y_n(x)])

    y_1'(x) = F_1(x, [y_0(x), y_1(x), \ldots, y_n(x)])

    \vdots

    y_n'(x) = F_n(x, [y_0(x), y_1(x), \ldots, y_n(x)])

The derivatives are specified by the vector-valued function
*F* that evaluates
`[y_0', \ldots, y_n'] = F(x, [y_0, \ldots, y_n])`.
The initial point `x_0` is specified by the scalar argument *x0*,
and the initial value `y(x_0) =  [y_0(x_0), \ldots, y_n(x_0)]` is
specified by the vector argument *y0*.

For convenience, if the system is one-dimensional, you may optionally
provide just a scalar value for *y0*. In this case, *F* should accept
a scalar *y* argument and return a scalar. The solution function
*y* will return scalar values instead of length-1 vectors.

Evaluation of the solution function `y(x)` is permitted
for any `x \ge x_0`.

A high-order ODE can be solved by transforming it into first-order
vector form. This transformation is described in standard texts
on ODEs. Examples will also be given below.

**Options, speed and accuracy**

By default, :func:`~mpmath.odefun` uses a high-order Taylor series
method. For reasonably well-behaved problems, the solution will
be fully accurate to within the working precision. Note that
*F* must be possible to evaluate to very high precision
for the generation of Taylor series to work.

To get a faster but less accurate solution, you can set a large
value for *tol* (which defaults roughly to *eps*). If you just
want to plot the solution or perform a basic simulation,
*tol = 0.01* is likely sufficient.

The *degree* argument controls the degree of the solver (with
*method='taylor'*, this is the degree of the Taylor series
expansion). A higher degree means that a longer step can be taken
before a new local solution must be generated from *F*,
meaning that fewer steps are required to get from `x_0` to a given
`x_1`. On the other hand, a higher degree also means that each
local solution becomes more expensive (i.e., more evaluations of
*F* are required per step, and at higher precision).

The optimal setting therefore involves a tradeoff. Generally,
decreasing the *degree* for Taylor series is likely to give faster
solution at low precision, while increasing is likely to be better
at higher precision.

The function
object returned by :func:`~mpmath.odefun` caches the solutions at all step
points and uses polynomial interpolation between step points.
Therefore, once `y(x_1)` has been evaluated for some `x_1`,
`y(x)` can be evaluated very quickly for any `x_0 \le x \le x_1`.
and continuing the evaluation up to `x_2 > x_1` is also fast.

**Examples of first-order ODEs**

We will solve the standard test problem `y'(x) = y(x), y(0) = 1`
which has explicit solution `y(x) = \exp(x)`::

    >>> from mpmath import *
    >>> mp.dps = 15; mp.pretty = True
    >>> f = odefun(lambda x, y: y, 0, 1)
    >>> for x in [0, 1, 2.5]:
    ...     print((f(x), exp(x)))
    ...
    (1.0, 1.0)
    (2.71828182845905, 2.71828182845905)
    (12.1824939607035, 12.1824939607035)

The solution with high precision::

    >>> mp.dps = 50
    >>> f = odefun(lambda x, y: y, 0, 1)
    >>> f(1)
    2.7182818284590452353602874713526624977572470937
    >>> exp(1)
    2.7182818284590452353602874713526624977572470937

Using the more general vectorized form, the test problem
can be input as (note that *f* returns a 1-element vector)::

    >>> mp.dps = 15
    >>> f = odefun(lambda x, y: [y[0]], 0, [1])
    >>> f(1)
    [2.71828182845905]

:func:`~mpmath.odefun` can solve nonlinear ODEs, which are generally
impossible (and at best difficult) to solve analytically. As
an example of a nonlinear ODE, we will solve `y'(x) = x \sin(y(x))`
for `y(0) = \pi/2`. An exact solution happens to be known
for this problem, and is given by
`y(x) = 2 \tan^{-1}\left(\exp\left(x^2/2\right)\right)`::

    >>> f = odefun(lambda x, y: x*sin(y), 0, pi/2)
    >>> for x in [2, 5, 10]:
    ...     print((f(x), 2*atan(exp(mpf(x)**2/2))))
    ...
    (2.87255666284091, 2.87255666284091)
    (3.14158520028345, 3.14158520028345)
    (3.14159265358979, 3.14159265358979)

If `F` is independent of `y`, an ODE can be solved using direct
integration. We can therefore obtain a reference solution with
:func:`~mpmath.quad`::

    >>> f = lambda x: (1+x**2)/(1+x**3)
    >>> g = odefun(lambda x, y: f(x), pi, 0)
    >>> g(2*pi)
    0.72128263801696
    >>> quad(f, [pi, 2*pi])
    0.72128263801696

**Examples of second-order ODEs**

We will solve the harmonic oscillator equation `y''(x) + y(x) = 0`.
To do this, we introduce the helper functions `y_0 = y, y_1 = y_0'`
whereby the original equation can be written as `y_1' + y_0' = 0`. Put
together, we get the first-order, two-dimensional vector ODE

.. math ::

    \begin{cases}
    y_0' = y_1 \\
    y_1' = -y_0
    \end{cases}

To get a well-defined IVP, we need two initial values. With
`y(0) = y_0(0) = 1` and `-y'(0) = y_1(0) = 0`, the problem will of
course be solved by `y(x) = y_0(x) = \cos(x)` and
`-y'(x) = y_1(x) = \sin(x)`. We check this::

    >>> f = odefun(lambda x, y: [-y[1], y[0]], 0, [1, 0])
    >>> for x in [0, 1, 2.5, 10]:
    ...     nprint(f(x), 15)
    ...     nprint([cos(x), sin(x)], 15)
    ...     print("---")
    ...
    [1.0, 0.0]
    [1.0, 0.0]
    ---
    [0.54030230586814, 0.841470984807897]
    [0.54030230586814, 0.841470984807897]
    ---
    [-0.801143615546934, 0.598472144103957]
    [-0.801143615546934, 0.598472144103957]
    ---
    [-0.839071529076452, -0.54402111088937]
    [-0.839071529076452, -0.54402111088937]
    ---

Note that we get both the sine and the cosine solutions
simultaneously.

**TODO**

* Better automatic choice of degree and step size
* Make determination of Taylor series convergence radius
  more robust
* Allow solution for `x < x_0`
* Allow solution for complex `x`
* Test for difficult (ill-conditioned) problems
* Implement Runge-Kutta and other algorithms

g       @Tc                 ó$   <€ S! W^ ,          4      .# ©r   r   )r'   r(   ÚF_s   &&€r   Ú<lambda>Úodefun.<locals>.<lambda>ñ   s   ø€ ™"˜Q !¥›+™r   Fc           	      óf   <€ V  Uu. uF  pSP                  VR R R1,          V4      NK!  	  up# u upi )Nr   )Úpolyval)r-   Úar/   r   s   && €r   ÚmpolyvalÚodefun.<locals>.mpolyvalø   s.   ø€ Ù14Ó5±¨A�—‘˜A™d ˜d�G QÖ'±Ñ5Ð5ùÒ5s   †%.c                 ót  <	€ V S8  d   \         h\        S
V 4      pV\        S
4      8  d   SV^,
          ,          #  SR,          w  r#pS'       d   \        RW43,          4       S	! W$V,
          4      pTp\	        SSWESS4      w  r$S
P                  V4       SP                  W#V34       W8:  g   Kv  SR,          # )r   z$Computing Taylor series for [%f, %f]r   )Ú
ValueErrorr   r   Úprintr5   r   )r'   r!   r-   ÚxaÚxbr(   ÚFr   Údegreer?   Úseries_boundariesÚseries_datar    Úverboser   s   &     €€€€€€€€€r   Ú
get_seriesÚodefun.<locals>.get_seriesû   s³   ø€ ØˆrŒ6ÜÐÜÐ$ aÓ(ˆØŒsÐ$Ó%Ô%Ø˜q �sÕ#Ð#ØØ% b�/‰KˆC�RßÜÐ<À¸xÕGÔHÙ˜ �eÓ$ˆAØˆBÜ   a¨°¸&ÓA‰GˆCØ×$Ñ$ RÔ(Ø×Ñ ¨˜}Ô-ØŽwØ" 2•Ð&r   c                 óú   <€ SP                  V 4      p SP                  p SSn        S! V 4      w  r#pS	! W V,
          4      pVSn        S
'       d   V Uu. uF  qf5NK  	  up# V^ ,          5#   TSn        i ; iu upi r8   )Úconvertr   )r'   r)   r-   rD   rE   r(   Úykr   rK   r?   Úreturn_vectorÚworkprecs   &      €€€€€r   ÚinterpolantÚodefun.<locals>.interpolant  sw   ø€ Ø�K‰K˜‹NˆØ�x‰xˆð	ØˆCŒHÙ$ Q›-‰KˆC�RÙ˜ �dÓ#ˆAàˆCŒHßÙ"#Ó$¡!˜B“C¡!Ñ$Ð$à�a•D�5ˆLøð	 ˆC�Hüâ$s    !A, ÁA8Á,	A5)ÚintÚlogr   Údpsr   Ú	TypeErrorr5   )r   rF   r   r   r#   rG   ÚmethodrJ   r-   rE   rR   r9   rK   r?   rP   rH   rI   r    rQ   s   fff&&f&f   @@@@@@@@r   ÚodefunrY   3   sì   ÿü€ ÷f Ü˜Ÿ™  Q›Ð'Ó(¨Õ+‰à—8‘8˜B•;ˆØ×.Ð.˜œC  #§'¡'¥	¨"¥Ó-Õ-€FØ�x‰x˜"�}€HðÜˆBŒØˆô ˜˜a  R¨°6Ó:�G€CØ˜R˜ÐØ˜˜R�=�/€Kõ6÷'õ '÷$ñ ð ÐøôW ô ØˆÜ&ˆØˆTˆØŠð	ús   ÂC ÃC9Ã8C9Ú__main__)NNÚtaylorF)
r   Úlibmp.backendr   Úobjectr   r5   rY   r   ÚdoctestÚtestmodr   r   r   Ú<module>r`      sH   ðÝ Ý "ô	�ô 	ò*ôXgðR €
Ô àˆzÔÛØ‡O‚OÖñ r   