Spaces:
Sleeping
Sleeping
File size: 2,736 Bytes
6a86ad5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
"""Numerical Methods for Holonomic Functions"""
from sympy.core.sympify import sympify
from sympy.holonomic.holonomic import DMFsubs
from mpmath import mp
def _evalf(func, points, derivatives=False, method='RK4'):
"""
Numerical methods for numerical integration along a given set of
points in the complex plane.
"""
ann = func.annihilator
a = ann.order
R = ann.parent.base
K = R.get_field()
if method == 'Euler':
meth = _euler
else:
meth = _rk4
dmf = []
for j in ann.listofpoly:
dmf.append(K.new(j.to_list()))
red = [-dmf[i] / dmf[a] for i in range(a)]
y0 = func.y0
if len(y0) < a:
raise TypeError("Not Enough Initial Conditions")
x0 = func.x0
sol = [meth(red, x0, points[0], y0, a)]
for i, j in enumerate(points[1:]):
sol.append(meth(red, points[i], j, sol[-1], a))
if not derivatives:
return [sympify(i[0]) for i in sol]
else:
return sympify(sol)
def _euler(red, x0, x1, y0, a):
"""
Euler's method for numerical integration.
From x0 to x1 with initial values given at x0 as vector y0.
"""
A = sympify(x0)._to_mpmath(mp.prec)
B = sympify(x1)._to_mpmath(mp.prec)
y_0 = [sympify(i)._to_mpmath(mp.prec) for i in y0]
h = B - A
f_0 = y_0[1:]
f_0_n = 0
for i in range(a):
f_0_n += sympify(DMFsubs(red[i], A, mpm=True))._to_mpmath(mp.prec) * y_0[i]
f_0.append(f_0_n)
sol = []
for i in range(a):
sol.append(y_0[i] + h * f_0[i])
return sol
def _rk4(red, x0, x1, y0, a):
"""
Runge-Kutta 4th order numerical method.
"""
A = sympify(x0)._to_mpmath(mp.prec)
B = sympify(x1)._to_mpmath(mp.prec)
y_0 = [sympify(i)._to_mpmath(mp.prec) for i in y0]
h = B - A
f_0_n = 0
f_1_n = 0
f_2_n = 0
f_3_n = 0
f_0 = y_0[1:]
for i in range(a):
f_0_n += sympify(DMFsubs(red[i], A, mpm=True))._to_mpmath(mp.prec) * y_0[i]
f_0.append(f_0_n)
f_1 = [y_0[i] + f_0[i]*h/2 for i in range(1, a)]
for i in range(a):
f_1_n += sympify(DMFsubs(red[i], A + h/2, mpm=True))._to_mpmath(mp.prec) * (y_0[i] + f_0[i]*h/2)
f_1.append(f_1_n)
f_2 = [y_0[i] + f_1[i]*h/2 for i in range(1, a)]
for i in range(a):
f_2_n += sympify(DMFsubs(red[i], A + h/2, mpm=True))._to_mpmath(mp.prec) * (y_0[i] + f_1[i]*h/2)
f_2.append(f_2_n)
f_3 = [y_0[i] + f_2[i]*h for i in range(1, a)]
for i in range(a):
f_3_n += sympify(DMFsubs(red[i], A + h, mpm=True))._to_mpmath(mp.prec) * (y_0[i] + f_2[i]*h)
f_3.append(f_3_n)
sol = []
for i in range(a):
sol.append(y_0[i] + h * (f_0[i]+2*f_1[i]+2*f_2[i]+f_3[i])/6)
return sol
|