� H�g�&���ddlmZddlmZGd�de��Zd�Zd d �Zee_ed krddlZej ��dSdS) �)�bisect�)�xrangec��eZdZdS)� ODEMethodsN)�__name__� __module__� __qualname__���d/home/asafur/pinokio/api/open-webui.git/app/env/lib/python3.11/site-packages/mpmath/calculus/odes.pyrrs�������Dr rc �L����|�d| ��x�}t|��}|g}|g} |} |�|j} | d|zz|_t|��D]g} || �������fd�t t�����D���| �z } |�| ��| �����hd�t|��D��} t|dz��D]�}dg|z}d|dzz}d}t|dz��D]G} t|��D]!}||xx|| | |zz cc<�"|||z dzz| z}|dz }�H�| z|�|��z }t|��D]1}|||z||<| |�||���2�� | |_n #| |_wxYw|j}| D]D}|dr:t||� |t|d��z |����}�E|dz}| ||zfS)N�c�8��g|]}�|��|zz��Sr r )�.0�i�fxy�h�ys ���r � <listcomp>zode_taylor.<locals>.<listcomp>s)���7�7�7�1��1��a��A��h��7�7�7r c��g|]}g��Sr r )r�ds r rzode_taylor.<locals>.<listcomp>s��&�&�&�a�r�&�&�&r r�����r) �ldexp�len�prec�ranger�append�fac�one�min�nthroot�abs)�ctx�derivs�x0�y0�tol_prec�n�tol�dim�xs�ys�x�origr�ser�j�s�b�kr�scale�radius�tsrrrs @@@r � ode_taylorr8s�������i�i��H�9�%�%�%�A�� �b�'�'�C� ��B� ��B� �A� �A� �8�D����1��:����q��� � �A��&��A�,�,�C�7�7�7�7�7�7��s�1�v�v���7�7�7�A� ��F�A� �I�I�a�L�L�L� �I�I�a�L�L�L�L�&�&�5��:�:�&�&�&���q��s��� $� $�A���C��A���Q���A��A��1�Q�3�Z�Z� � ���s���)�)�A��a�D�D�D�A��1��a��L�(�D�D�D�D��!�A�#�a�%�[�q�b�)���Q�������G�c�g�g�a�j�j�(�E��3�Z�Z� $� $����t�e�|��!���A�� � �a��d�#�#�#�#� $� $������4��������W�F��B�B�� �b�6� B������S��R��V���_�a�!@�!@�A�A�F�� �a�K�F� ��6� �>�s �E9G� G N�taylorFc ������� � � ������|r(t��|d�� ��dz�n �jdz��pdtd�jzdz ��z��jdz� t |��d�n#t $r�� � fd��|g}d�YnwxYwt ���|����\}} �| g�|�| fg��fd �� ���� �����f d �� �� � ��fd �} | S) 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 r� �g@�(Tc�*���||d��gS)Nrr )r.r�F_s �r �<lambda>zodefun.<locals>.<lambda>�s���"�"�Q��!��+�+��r Fc�$�����fd�|D��S)Nc�N��g|]!}��|ddd������"S)Nr)�polyval)rr2�ar$s ��r rz,odefun.<locals>.mpolyval.<locals>.<listcomp>�s1���5�5�5�A�� � �A�d�d��d�G�Q�'�'�5�5�5r r )r0rDr$s `�r �mpolyvalzodefun.<locals>.mpolyval�s!����5�5�5�5�5��5�5�5�5r c�� �|�krt�t� |��}|t� ��kr � |dz S � d\}}}� rtd||fz��� |||z ��}|}t ��||� ���\}}� �|��� �|||f��||kr� dS��)Nrrz$Computing Taylor series for [%f, %f])� ValueErrorrr�printr8r)r.r)r0�xa�xbr�Fr$�degreerE�series_boundaries� series_datar(�verboser&s ���������r � get_serieszodefun.<locals>.get_series�s���� �r�6�6�� � �$�a� (� (�� �s�$�%�%� %� %��q��s�#� #� '�%�b�/�K�C��R�� I��<��B�x�G�H�H�H����b��e�$�$�A��B� ��a��Q��&�A�A�G�C�� � $� $�R� (� (� (� � � ��R��}� -� -� -��B�w�w�"�2��&� 'r c������|��}�j} � �_�|��\}}}�|||z ��}|�_n #|�_wxYw� r d�|D��S|d S)Nc��g|]}| ��Sr r )r�yks r rz/odefun.<locals>.interpolant.<locals>.<listcomp>s��$�$�$�B�R�C�$�$�$r r)�convertr) r.r/r0rIrJrr$rPrE� return_vector�workprecs �����r � interpolantzodefun.<locals>.interpolant s���� �K�K��N�N���x�� ��C�H�$�*�Q�-�-�K�C��R����a��d�#�#�A��C�H�H��t�C�H�O�O�O�O� � �$�$�!�$�$�$� $��a�D�5�Ls �%A � A)�int�logr�dpsr� TypeErrorr8)r$rKr&r'r*rL�methodrOr0rJrWr?rPrErUrMrNr(rVs``` ` ` @@@@@@@@r �odefunr]3s����������������f �������Q���'�(�(��+����8�B�;�� � .��C��#�'� �"� �-�-�-�F��x�"�}�H�� �B����� � �� ���� �� &� &� &� &���T��� � � � ���� ��a��R��6�:�:�G�C���R�����R�=�/�K�6�6�6�6�6�'�'�'�'�'�'�'�'�'�'�'�'�'�$ � � � � � � � � � �s�,A>�>B�B�__main__)NNr9F) r� libmp.backendr�objectrr8r]r�doctest�testmodr r r �<module>rcs���������"�"�"�"�"�"� � � � � �� � � �*�*�*�Xg�g�g�g�R� �� �z����N�N�N��G�O�������r
Memory