passagemath-symbolics 10.8.1a1__cp314-cp314t-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_symbolics/__init__.py +3 -0
- passagemath_symbolics-10.8.1a1.dist-info/METADATA +186 -0
- passagemath_symbolics-10.8.1a1.dist-info/RECORD +181 -0
- passagemath_symbolics-10.8.1a1.dist-info/WHEEL +5 -0
- passagemath_symbolics-10.8.1a1.dist-info/top_level.txt +3 -0
- sage/all__sagemath_symbolics.py +17 -0
- sage/calculus/all.py +14 -0
- sage/calculus/calculus.py +2838 -0
- sage/calculus/desolvers.py +1864 -0
- sage/calculus/predefined.py +51 -0
- sage/calculus/tests.py +225 -0
- sage/calculus/var.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/calculus/var.pyx +401 -0
- sage/dynamics/all__sagemath_symbolics.py +6 -0
- sage/dynamics/complex_dynamics/all.py +5 -0
- sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1034 -0
- sage/ext/all__sagemath_symbolics.py +1 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/ext_data/magma/latex/latex.m +1021 -0
- sage/ext_data/magma/latex/latex.spec +1 -0
- sage/ext_data/magma/sage/basic.m +356 -0
- sage/ext_data/magma/sage/sage.spec +1 -0
- sage/ext_data/magma/spec +9 -0
- sage/geometry/all__sagemath_symbolics.py +8 -0
- sage/geometry/hyperbolic_space/all.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_coercion.py +755 -0
- sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2419 -0
- sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
- sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1083 -0
- sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
- sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
- sage/geometry/riemannian_manifolds/all.py +7 -0
- sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
- sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
- sage/interfaces/all__sagemath_symbolics.py +1 -0
- sage/interfaces/magma.py +2991 -0
- sage/interfaces/magma_free.py +90 -0
- sage/interfaces/maple.py +1402 -0
- sage/interfaces/mathematica.py +1345 -0
- sage/interfaces/mathics.py +1312 -0
- sage/interfaces/sympy.py +1398 -0
- sage/interfaces/sympy_wrapper.py +197 -0
- sage/interfaces/tides.py +938 -0
- sage/libs/all__sagemath_symbolics.py +6 -0
- sage/manifolds/all.py +7 -0
- sage/manifolds/calculus_method.py +553 -0
- sage/manifolds/catalog.py +437 -0
- sage/manifolds/chart.py +4010 -0
- sage/manifolds/chart_func.py +3416 -0
- sage/manifolds/continuous_map.py +2183 -0
- sage/manifolds/continuous_map_image.py +155 -0
- sage/manifolds/differentiable/affine_connection.py +2475 -0
- sage/manifolds/differentiable/all.py +1 -0
- sage/manifolds/differentiable/automorphismfield.py +1383 -0
- sage/manifolds/differentiable/automorphismfield_group.py +604 -0
- sage/manifolds/differentiable/bundle_connection.py +1445 -0
- sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
- sage/manifolds/differentiable/chart.py +1241 -0
- sage/manifolds/differentiable/curve.py +1028 -0
- sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
- sage/manifolds/differentiable/degenerate.py +559 -0
- sage/manifolds/differentiable/degenerate_submanifold.py +1668 -0
- sage/manifolds/differentiable/diff_form.py +1660 -0
- sage/manifolds/differentiable/diff_form_module.py +1062 -0
- sage/manifolds/differentiable/diff_map.py +1315 -0
- sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
- sage/manifolds/differentiable/examples/all.py +1 -0
- sage/manifolds/differentiable/examples/euclidean.py +2517 -0
- sage/manifolds/differentiable/examples/real_line.py +897 -0
- sage/manifolds/differentiable/examples/sphere.py +1186 -0
- sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
- sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
- sage/manifolds/differentiable/integrated_curve.py +4035 -0
- sage/manifolds/differentiable/levi_civita_connection.py +841 -0
- sage/manifolds/differentiable/manifold.py +4254 -0
- sage/manifolds/differentiable/manifold_homset.py +1826 -0
- sage/manifolds/differentiable/metric.py +3032 -0
- sage/manifolds/differentiable/mixed_form.py +1507 -0
- sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
- sage/manifolds/differentiable/multivector_module.py +800 -0
- sage/manifolds/differentiable/multivectorfield.py +1522 -0
- sage/manifolds/differentiable/poisson_tensor.py +268 -0
- sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
- sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
- sage/manifolds/differentiable/scalarfield.py +1343 -0
- sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
- sage/manifolds/differentiable/symplectic_form.py +912 -0
- sage/manifolds/differentiable/symplectic_form_test.py +220 -0
- sage/manifolds/differentiable/tangent_space.py +412 -0
- sage/manifolds/differentiable/tangent_vector.py +616 -0
- sage/manifolds/differentiable/tensorfield.py +4665 -0
- sage/manifolds/differentiable/tensorfield_module.py +963 -0
- sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
- sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
- sage/manifolds/differentiable/vector_bundle.py +1725 -0
- sage/manifolds/differentiable/vectorfield.py +1717 -0
- sage/manifolds/differentiable/vectorfield_module.py +2445 -0
- sage/manifolds/differentiable/vectorframe.py +1832 -0
- sage/manifolds/family.py +270 -0
- sage/manifolds/local_frame.py +1490 -0
- sage/manifolds/manifold.py +3090 -0
- sage/manifolds/manifold_homset.py +452 -0
- sage/manifolds/operators.py +359 -0
- sage/manifolds/point.py +994 -0
- sage/manifolds/scalarfield.py +3718 -0
- sage/manifolds/scalarfield_algebra.py +629 -0
- sage/manifolds/section.py +3111 -0
- sage/manifolds/section_module.py +831 -0
- sage/manifolds/structure.py +229 -0
- sage/manifolds/subset.py +2721 -0
- sage/manifolds/subsets/all.py +1 -0
- sage/manifolds/subsets/closure.py +131 -0
- sage/manifolds/subsets/pullback.py +883 -0
- sage/manifolds/topological_submanifold.py +891 -0
- sage/manifolds/trivialization.py +733 -0
- sage/manifolds/utilities.py +1348 -0
- sage/manifolds/vector_bundle.py +1347 -0
- sage/manifolds/vector_bundle_fiber.py +332 -0
- sage/manifolds/vector_bundle_fiber_element.py +111 -0
- sage/matrix/all__sagemath_symbolics.py +1 -0
- sage/matrix/matrix_symbolic_dense.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_symbolic_dense.pxd +6 -0
- sage/matrix/matrix_symbolic_dense.pyx +1030 -0
- sage/matrix/matrix_symbolic_sparse.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_symbolic_sparse.pxd +6 -0
- sage/matrix/matrix_symbolic_sparse.pyx +1038 -0
- sage/modules/all__sagemath_symbolics.py +1 -0
- sage/modules/vector_callable_symbolic_dense.py +105 -0
- sage/modules/vector_symbolic_dense.py +116 -0
- sage/modules/vector_symbolic_sparse.py +118 -0
- sage/rings/all__sagemath_symbolics.py +4 -0
- sage/rings/asymptotic/all.py +6 -0
- sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
- sage/rings/asymptotic/asymptotic_ring.py +4858 -0
- sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4106 -0
- sage/rings/asymptotic/growth_group.py +5373 -0
- sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
- sage/rings/asymptotic/term_monoid.py +5205 -0
- sage/rings/function_field/all__sagemath_symbolics.py +2 -0
- sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
- sage/symbolic/all.py +15 -0
- sage/symbolic/assumptions.py +987 -0
- sage/symbolic/benchmark.py +93 -0
- sage/symbolic/callable.py +456 -0
- sage/symbolic/callable.pyi +66 -0
- sage/symbolic/comparison_impl.pyi +38 -0
- sage/symbolic/complexity_measures.py +35 -0
- sage/symbolic/constants.py +1286 -0
- sage/symbolic/constants_c_impl.pyi +10 -0
- sage/symbolic/expression_conversion_algebraic.py +310 -0
- sage/symbolic/expression_conversion_sympy.py +317 -0
- sage/symbolic/expression_conversions.py +1727 -0
- sage/symbolic/function_factory.py +355 -0
- sage/symbolic/function_factory.pyi +41 -0
- sage/symbolic/getitem_impl.pyi +24 -0
- sage/symbolic/integration/all.py +1 -0
- sage/symbolic/integration/external.py +271 -0
- sage/symbolic/integration/integral.py +1075 -0
- sage/symbolic/maxima_wrapper.py +162 -0
- sage/symbolic/operators.py +267 -0
- sage/symbolic/operators.pyi +61 -0
- sage/symbolic/pynac_constant_impl.pyi +13 -0
- sage/symbolic/pynac_function_impl.pyi +8 -0
- sage/symbolic/random_tests.py +461 -0
- sage/symbolic/relation.py +2062 -0
- sage/symbolic/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/ring.pxd +5 -0
- sage/symbolic/ring.pyi +110 -0
- sage/symbolic/ring.pyx +1393 -0
- sage/symbolic/series_impl.pyi +10 -0
- sage/symbolic/subring.py +1025 -0
- sage/symbolic/symengine.py +19 -0
- sage/symbolic/tests.py +40 -0
- sage/symbolic/units.py +1468 -0
|
@@ -0,0 +1,1864 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
r"""
|
|
3
|
+
Solving ordinary differential equations
|
|
4
|
+
|
|
5
|
+
This file contains functions useful for solving differential equations
|
|
6
|
+
which occur commonly in a 1st semester differential equations
|
|
7
|
+
course. For another numerical solver see the :meth:`ode_solver` function
|
|
8
|
+
and the optional package Octave.
|
|
9
|
+
|
|
10
|
+
Solutions from the Maxima package can contain the three constants
|
|
11
|
+
``_C``, ``_K1``, and ``_K2`` where the underscore is used to distinguish
|
|
12
|
+
them from symbolic variables that the user might have used. You can
|
|
13
|
+
substitute values for them, and make them into accessible usable
|
|
14
|
+
symbolic variables, for example with ``var("_C")``.
|
|
15
|
+
|
|
16
|
+
Commands:
|
|
17
|
+
|
|
18
|
+
- :func:`desolve` -- compute the "general solution" to a 1st or 2nd order
|
|
19
|
+
ODE via Maxima
|
|
20
|
+
|
|
21
|
+
- :func:`desolve_laplace` -- solve an ODE using Laplace transforms via
|
|
22
|
+
Maxima. Initial conditions are optional
|
|
23
|
+
|
|
24
|
+
- :func:`desolve_rk4` -- solve numerically an IVP for one first order
|
|
25
|
+
equation, return list of points or plot
|
|
26
|
+
|
|
27
|
+
- :func:`desolve_system_rk4` -- solve numerically an IVP for a system of first
|
|
28
|
+
order equations, return list of points
|
|
29
|
+
|
|
30
|
+
- :func:`desolve_odeint` -- solve numerically a system of first-order ordinary
|
|
31
|
+
differential equations using :func:`~scipy:scipy.integrate.odeint` from
|
|
32
|
+
the module :mod:`scipy:scipy.integrate`.
|
|
33
|
+
|
|
34
|
+
- :func:`desolve_system` -- solve a system of 1st order ODEs of any size using
|
|
35
|
+
Maxima. Initial conditions are optional
|
|
36
|
+
|
|
37
|
+
- :func:`eulers_method` -- approximate solution to a 1st order DE,
|
|
38
|
+
presented as a table
|
|
39
|
+
|
|
40
|
+
- :func:`eulers_method_2x2` -- approximate solution to a 1st order system
|
|
41
|
+
of DEs, presented as a table
|
|
42
|
+
|
|
43
|
+
- :func:`eulers_method_2x2_plot` -- plot the sequence of points obtained
|
|
44
|
+
from Euler's method
|
|
45
|
+
|
|
46
|
+
The following functions require the optional package ``tides``:
|
|
47
|
+
|
|
48
|
+
- :func:`desolve_mintides` -- numerical solution of a system of 1st order ODEs via
|
|
49
|
+
the Taylor series integrator method implemented in TIDES
|
|
50
|
+
|
|
51
|
+
- :func:`desolve_tides_mpfr` -- arbitrary precision Taylor series integrator implemented in TIDES
|
|
52
|
+
|
|
53
|
+
AUTHORS:
|
|
54
|
+
|
|
55
|
+
- David Joyner (3-2006) - Initial version of functions
|
|
56
|
+
|
|
57
|
+
- Marshall Hampton (7-2007) - Creation of Python module and testing
|
|
58
|
+
|
|
59
|
+
- Robert Bradshaw (10-2008) - Some interface cleanup.
|
|
60
|
+
|
|
61
|
+
- Robert Marik (10-2009) - Some bugfixes and enhancements
|
|
62
|
+
|
|
63
|
+
- Miguel Marco (06-2014) - Tides desolvers
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
##########################################################################
|
|
67
|
+
# Copyright (C) 2006 David Joyner <wdjoyner@gmail.com>, Marshall Hampton,
|
|
68
|
+
# Robert Marik <marik@mendelu.cz>
|
|
69
|
+
#
|
|
70
|
+
# Distributed under the terms of the GNU General Public License (GPL):
|
|
71
|
+
#
|
|
72
|
+
# https://www.gnu.org/licenses/
|
|
73
|
+
##########################################################################
|
|
74
|
+
|
|
75
|
+
import os
|
|
76
|
+
import shutil
|
|
77
|
+
|
|
78
|
+
from sage.calculus.functional import diff
|
|
79
|
+
from sage.misc.lazy_import import lazy_import
|
|
80
|
+
lazy_import("sage.interfaces.maxima_lib","maxima")
|
|
81
|
+
from sage.misc.functional import N
|
|
82
|
+
from sage.rings.real_mpfr import RealField
|
|
83
|
+
from sage.structure.element import Expression
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def fricas_desolve(de, dvar, ics, ivar):
|
|
87
|
+
r"""
|
|
88
|
+
Solve an ODE using FriCAS.
|
|
89
|
+
|
|
90
|
+
EXAMPLES::
|
|
91
|
+
|
|
92
|
+
sage: x = var('x')
|
|
93
|
+
sage: y = function('y')(x)
|
|
94
|
+
sage: desolve(diff(y,x) + y - 1, y, algorithm='fricas') # optional - fricas
|
|
95
|
+
_C0*e^(-x) + 1
|
|
96
|
+
|
|
97
|
+
sage: desolve(diff(y, x) + y == y^3*sin(x), y, algorithm='fricas') # optional - fricas
|
|
98
|
+
-1/5*(2*cos(x)*y(x)^2 + 4*sin(x)*y(x)^2 - 5)*e^(-2*x)/y(x)^2
|
|
99
|
+
|
|
100
|
+
TESTS::
|
|
101
|
+
|
|
102
|
+
sage: from sage.calculus.desolvers import fricas_desolve
|
|
103
|
+
sage: Y = fricas_desolve(diff(y,x) + y - 1, y, [42,1783], x) # optional - fricas
|
|
104
|
+
sage: Y.subs(x=42) # optional - fricas
|
|
105
|
+
1783
|
|
106
|
+
"""
|
|
107
|
+
from sage.interfaces.fricas import fricas
|
|
108
|
+
from sage.symbolic.ring import SR
|
|
109
|
+
if ics is None:
|
|
110
|
+
y = fricas(de).solve(dvar.operator(), ivar).sage()
|
|
111
|
+
else:
|
|
112
|
+
eq = fricas.equation(ivar, ics[0])
|
|
113
|
+
y = fricas(de).solve(dvar.operator(), eq, ics[1:]).sage()
|
|
114
|
+
|
|
115
|
+
if isinstance(y, dict):
|
|
116
|
+
basis = y["basis"]
|
|
117
|
+
particular = y["particular"]
|
|
118
|
+
return particular + sum(SR.var("_C" + str(i)) * v
|
|
119
|
+
for i, v in enumerate(basis))
|
|
120
|
+
return y
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def fricas_desolve_system(des, dvars, ics, ivar):
|
|
124
|
+
r"""
|
|
125
|
+
Solve a system of first order ODEs using FriCAS.
|
|
126
|
+
|
|
127
|
+
EXAMPLES::
|
|
128
|
+
|
|
129
|
+
sage: t = var('t')
|
|
130
|
+
sage: x = function('x')(t)
|
|
131
|
+
sage: y = function('y')(t)
|
|
132
|
+
sage: de1 = diff(x,t) + y - 1 == 0
|
|
133
|
+
sage: de2 = diff(y,t) - x + 1 == 0
|
|
134
|
+
sage: desolve_system([de1, de2], [x, y], algorithm='fricas') # optional - fricas
|
|
135
|
+
[x(t) == _C0*cos(t) + cos(t)^2 + _C1*sin(t) + sin(t)^2,
|
|
136
|
+
y(t) == -_C1*cos(t) + _C0*sin(t) + 1]
|
|
137
|
+
|
|
138
|
+
sage: desolve_system([de1, de2], [x,y], [0,1,2], algorithm='fricas') # optional - fricas
|
|
139
|
+
[x(t) == cos(t)^2 + sin(t)^2 - sin(t), y(t) == cos(t) + 1]
|
|
140
|
+
|
|
141
|
+
TESTS::
|
|
142
|
+
|
|
143
|
+
sage: from sage.calculus.desolvers import fricas_desolve_system
|
|
144
|
+
sage: t = var('t')
|
|
145
|
+
sage: x = function('x')(t)
|
|
146
|
+
sage: fricas_desolve_system([diff(x,t) + 1 == 0], [x], None, t) # optional - fricas
|
|
147
|
+
[x(t) == _C0 - t]
|
|
148
|
+
|
|
149
|
+
sage: y = function('y')(t)
|
|
150
|
+
sage: de1 = diff(x,t) + y - 1 == 0
|
|
151
|
+
sage: de2 = diff(y,t) - x + 1 == 0
|
|
152
|
+
sage: sol = fricas_desolve_system([de1,de2], [x,y], [0,1,-1], t) # optional - fricas
|
|
153
|
+
sage: sol # optional - fricas
|
|
154
|
+
[x(t) == cos(t)^2 + sin(t)^2 + 2*sin(t), y(t) == -2*cos(t) + 1]
|
|
155
|
+
"""
|
|
156
|
+
from sage.interfaces.fricas import fricas
|
|
157
|
+
from sage.symbolic.relation import solve
|
|
158
|
+
from sage.symbolic.ring import SR
|
|
159
|
+
ops = [dvar.operator() for dvar in dvars]
|
|
160
|
+
y = fricas(des).solve(ops, ivar).sage()
|
|
161
|
+
basis = y["basis"]
|
|
162
|
+
particular = y["particular"]
|
|
163
|
+
pars = [SR.var("_C" + str(i)) for i in range(len(basis))]
|
|
164
|
+
solv = particular + sum(p * v for p, v in zip(pars, basis))
|
|
165
|
+
|
|
166
|
+
if ics is None:
|
|
167
|
+
sols = solv
|
|
168
|
+
else:
|
|
169
|
+
ics0 = ics[0]
|
|
170
|
+
eqs = [val == sol.subs({ivar: ics0}) for val, sol in zip(ics[1:], solv)]
|
|
171
|
+
pars_values = solve(eqs, pars, solution_dict=True)
|
|
172
|
+
sols = [sol.subs(pars_values[0]) for sol in solv]
|
|
173
|
+
|
|
174
|
+
return [dvar == sol for dvar, sol in zip(dvars, sols)]
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def desolve(de, dvar, ics=None, ivar=None, show_method=False, contrib_ode=False,
|
|
178
|
+
algorithm='maxima'):
|
|
179
|
+
r"""
|
|
180
|
+
Solve a 1st or 2nd order linear ODE, including IVP and BVP.
|
|
181
|
+
|
|
182
|
+
INPUT:
|
|
183
|
+
|
|
184
|
+
- ``de`` -- an expression or equation representing the ODE
|
|
185
|
+
|
|
186
|
+
- ``dvar`` -- the dependent variable (hereafter called `y`)
|
|
187
|
+
|
|
188
|
+
- ``ics`` -- (optional) the initial or boundary conditions
|
|
189
|
+
|
|
190
|
+
- for a first-order equation, specify the initial `x` and `y`
|
|
191
|
+
|
|
192
|
+
- for a second-order equation, specify the initial `x`, `y`,
|
|
193
|
+
and `dy/dx`, i.e. write `[x_0, y(x_0), y'(x_0)]`
|
|
194
|
+
|
|
195
|
+
- for a second-order boundary solution, specify initial and
|
|
196
|
+
final `x` and `y` boundary conditions, i.e. write `[x_0, y(x_0), x_1, y(x_1)]`.
|
|
197
|
+
|
|
198
|
+
- gives an error if the solution is not SymbolicEquation (as happens for
|
|
199
|
+
example for a Clairaut equation)
|
|
200
|
+
|
|
201
|
+
- ``ivar`` -- (optional) the independent variable (hereafter called
|
|
202
|
+
`x`), which must be specified if there is more than one
|
|
203
|
+
independent variable in the equation
|
|
204
|
+
|
|
205
|
+
- ``show_method`` -- (optional) if ``True``, then Sage returns pair
|
|
206
|
+
``[solution, method]``, where method is the string describing
|
|
207
|
+
the method which has been used to get a solution (Maxima uses the
|
|
208
|
+
following order for first order equations: linear, separable,
|
|
209
|
+
exact (including exact with integrating factor), homogeneous,
|
|
210
|
+
bernoulli, generalized homogeneous) - use carefully in class,
|
|
211
|
+
see below the example of an equation which is separable but
|
|
212
|
+
this property is not recognized by Maxima and the equation is solved
|
|
213
|
+
as exact.
|
|
214
|
+
|
|
215
|
+
- ``contrib_ode`` -- (optional) if ``True``, ``desolve`` allows to solve
|
|
216
|
+
Clairaut, Lagrange, Riccati and some other equations. This may take
|
|
217
|
+
a long time and is thus turned off by default. Initial conditions
|
|
218
|
+
can be used only if the result is one SymbolicEquation (does not
|
|
219
|
+
contain a singular solution, for example).
|
|
220
|
+
|
|
221
|
+
- ``algorithm`` -- (default: ``'maxima'``) one of
|
|
222
|
+
|
|
223
|
+
* ``'maxima'`` -- use maxima
|
|
224
|
+
* ``'fricas'`` -- use FriCAS (the optional fricas spkg has to be installed)
|
|
225
|
+
|
|
226
|
+
OUTPUT:
|
|
227
|
+
|
|
228
|
+
In most cases return a SymbolicEquation which defines the solution
|
|
229
|
+
implicitly. If the result is in the form `y(x)=\ldots` (happens for
|
|
230
|
+
linear eqs.), return the right-hand side only. The possible
|
|
231
|
+
constant solutions of separable ODEs are omitted.
|
|
232
|
+
|
|
233
|
+
.. NOTE::
|
|
234
|
+
|
|
235
|
+
Use ``desolve? <tab>`` if the output in the Sage notebook is truncated.
|
|
236
|
+
|
|
237
|
+
EXAMPLES::
|
|
238
|
+
|
|
239
|
+
sage: x = var('x')
|
|
240
|
+
sage: y = function('y')(x)
|
|
241
|
+
sage: desolve(diff(y,x) + y - 1, y)
|
|
242
|
+
(_C + e^x)*e^(-x)
|
|
243
|
+
|
|
244
|
+
::
|
|
245
|
+
|
|
246
|
+
sage: f = desolve(diff(y,x) + y - 1, y, ics=[10,2]); f
|
|
247
|
+
(e^10 + e^x)*e^(-x)
|
|
248
|
+
|
|
249
|
+
::
|
|
250
|
+
|
|
251
|
+
sage: plot(f) # needs sage.plot
|
|
252
|
+
Graphics object consisting of 1 graphics primitive
|
|
253
|
+
|
|
254
|
+
We can also solve second-order differential equations::
|
|
255
|
+
|
|
256
|
+
sage: x = var('x')
|
|
257
|
+
sage: y = function('y')(x)
|
|
258
|
+
sage: de = diff(y,x,2) - y == x
|
|
259
|
+
sage: desolve(de, y)
|
|
260
|
+
_K2*e^(-x) + _K1*e^x - x
|
|
261
|
+
|
|
262
|
+
::
|
|
263
|
+
|
|
264
|
+
sage: f = desolve(de, y, [10,2,1]); f
|
|
265
|
+
-x + 7*e^(x - 10) + 5*e^(-x + 10)
|
|
266
|
+
|
|
267
|
+
::
|
|
268
|
+
|
|
269
|
+
sage: f(x=10)
|
|
270
|
+
2
|
|
271
|
+
|
|
272
|
+
::
|
|
273
|
+
|
|
274
|
+
sage: diff(f,x)(x=10)
|
|
275
|
+
1
|
|
276
|
+
|
|
277
|
+
::
|
|
278
|
+
|
|
279
|
+
sage: de = diff(y,x,2) + y == 0
|
|
280
|
+
sage: desolve(de, y)
|
|
281
|
+
_K2*cos(x) + _K1*sin(x)
|
|
282
|
+
|
|
283
|
+
::
|
|
284
|
+
|
|
285
|
+
sage: desolve(de, y, [0,1,pi/2,4])
|
|
286
|
+
cos(x) + 4*sin(x)
|
|
287
|
+
|
|
288
|
+
::
|
|
289
|
+
|
|
290
|
+
sage: desolve(y*diff(y,x)+sin(x)==0,y)
|
|
291
|
+
-1/2*y(x)^2 == _C - cos(x)
|
|
292
|
+
|
|
293
|
+
Clairaut equation: general and singular solutions::
|
|
294
|
+
|
|
295
|
+
sage: desolve(diff(y,x)^2+x*diff(y,x)-y==0,y,contrib_ode=True,show_method=True)
|
|
296
|
+
[[y(x) == _C^2 + _C*x, y(x) == -1/4*x^2], 'clairau...']
|
|
297
|
+
|
|
298
|
+
For equations involving more variables we specify an independent variable::
|
|
299
|
+
|
|
300
|
+
sage: a,b,c,n=var('a b c n')
|
|
301
|
+
sage: desolve(x^2*diff(y,x)==a+b*x^n+c*x^2*y^2,y,ivar=x,contrib_ode=True)
|
|
302
|
+
[[y(x) == 0, (b*x^(n - 2) + a/x^2)*c^2*u == 0]]
|
|
303
|
+
|
|
304
|
+
::
|
|
305
|
+
|
|
306
|
+
sage: desolve(x^2*diff(y,x)==a+b*x^n+c*x^2*y^2,y,ivar=x,contrib_ode=True,show_method=True)
|
|
307
|
+
[[[y(x) == 0, (b*x^(n - 2) + a/x^2)*c^2*u == 0]], 'riccati']
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
Higher order equations, not involving independent variable::
|
|
311
|
+
|
|
312
|
+
sage: desolve(diff(y,x,2)+y*(diff(y,x,1))^3==0,y).expand()
|
|
313
|
+
1/6*y(x)^3 + _K1*y(x) == _K2 + x
|
|
314
|
+
|
|
315
|
+
::
|
|
316
|
+
|
|
317
|
+
sage: desolve(diff(y,x,2)+y*(diff(y,x,1))^3==0,y,[0,1,1,3]).expand()
|
|
318
|
+
1/6*y(x)^3 - 5/3*y(x) == x - 3/2
|
|
319
|
+
|
|
320
|
+
::
|
|
321
|
+
|
|
322
|
+
sage: desolve(diff(y,x,2)+y*(diff(y,x,1))^3==0,y,[0,1,1,3],show_method=True)
|
|
323
|
+
[1/6*y(x)^3 - 5/3*y(x) == x - 3/2, 'freeofx']
|
|
324
|
+
|
|
325
|
+
Separable equations - Sage returns solution in implicit form::
|
|
326
|
+
|
|
327
|
+
sage: desolve(diff(y,x)*sin(y) == cos(x),y)
|
|
328
|
+
-cos(y(x)) == _C + sin(x)
|
|
329
|
+
|
|
330
|
+
::
|
|
331
|
+
|
|
332
|
+
sage: desolve(diff(y,x)*sin(y) == cos(x),y,show_method=True)
|
|
333
|
+
[-cos(y(x)) == _C + sin(x), 'separable']
|
|
334
|
+
|
|
335
|
+
::
|
|
336
|
+
|
|
337
|
+
sage: desolve(diff(y,x)*sin(y) == cos(x),y,[pi/2,1])
|
|
338
|
+
-cos(y(x)) == -cos(1) + sin(x) - 1
|
|
339
|
+
|
|
340
|
+
Linear equation - Sage returns the expression on the right hand side only::
|
|
341
|
+
|
|
342
|
+
sage: desolve(diff(y,x)+(y) == cos(x),y)
|
|
343
|
+
1/2*((cos(x) + sin(x))*e^x + 2*_C)*e^(-x)
|
|
344
|
+
|
|
345
|
+
::
|
|
346
|
+
|
|
347
|
+
sage: desolve(diff(y,x)+(y) == cos(x),y,show_method=True)
|
|
348
|
+
[1/2*((cos(x) + sin(x))*e^x + 2*_C)*e^(-x), 'linear']
|
|
349
|
+
|
|
350
|
+
::
|
|
351
|
+
|
|
352
|
+
sage: desolve(diff(y,x)+(y) == cos(x),y,[0,1])
|
|
353
|
+
1/2*(cos(x)*e^x + e^x*sin(x) + 1)*e^(-x)
|
|
354
|
+
|
|
355
|
+
This ODE with separated variables is solved as
|
|
356
|
+
exact. Explanation - factor does not split `e^{x-y}` in Maxima
|
|
357
|
+
into `e^{x}e^{y}`::
|
|
358
|
+
|
|
359
|
+
sage: desolve(diff(y,x)==exp(x-y),y,show_method=True)
|
|
360
|
+
[-e^x + e^y(x) == _C, 'exact']
|
|
361
|
+
|
|
362
|
+
You can solve Bessel equations, also using initial
|
|
363
|
+
conditions, but you cannot put (sometimes desired) the initial
|
|
364
|
+
condition at `x=0`, since this point is a singular point of the
|
|
365
|
+
equation. Anyway, if the solution should be bounded at `x=0`, then
|
|
366
|
+
``_K2=0``. ::
|
|
367
|
+
|
|
368
|
+
sage: desolve(x^2*diff(y,x,x)+x*diff(y,x)+(x^2-4)*y==0,y)
|
|
369
|
+
_K1*bessel_J(2, x) + _K2*bessel_Y(2, x)
|
|
370
|
+
|
|
371
|
+
Example of difficult ODE producing an error::
|
|
372
|
+
|
|
373
|
+
sage: desolve(sqrt(y)*diff(y,x)+e^(y)+cos(x)-sin(x+y)==0,y) # not tested
|
|
374
|
+
Traceback (click to the left for traceback)
|
|
375
|
+
...
|
|
376
|
+
NotImplementedError, "Maxima was unable to solve this ODE. Consider to set option contrib_ode to True."
|
|
377
|
+
|
|
378
|
+
Another difficult ODE with error - moreover, it takes a long time::
|
|
379
|
+
|
|
380
|
+
sage: desolve(sqrt(y)*diff(y,x)+e^(y)+cos(x)-sin(x+y)==0,y,contrib_ode=True) # not tested
|
|
381
|
+
|
|
382
|
+
Some more types of ODEs::
|
|
383
|
+
|
|
384
|
+
sage: desolve(x*diff(y,x)^2-(1+x*y)*diff(y,x)+y==0,y,contrib_ode=True,show_method=True)
|
|
385
|
+
[[y(x) == _C + log(x), y(x) == _C*e^x], 'factor']
|
|
386
|
+
|
|
387
|
+
::
|
|
388
|
+
|
|
389
|
+
sage: desolve(diff(y,x)==(x+y)^2,y,contrib_ode=True,show_method=True)
|
|
390
|
+
[[[x == _C - arctan(sqrt(t)), y(x) == -x - sqrt(t)], [x == _C + arctan(sqrt(t)), y(x) == -x + sqrt(t)]], 'lagrange']
|
|
391
|
+
|
|
392
|
+
These two examples produce an error (as expected, Maxima 5.18 cannot
|
|
393
|
+
solve equations from initial conditions). Maxima 5.18
|
|
394
|
+
returns false answer in this case! ::
|
|
395
|
+
|
|
396
|
+
sage: desolve(diff(y,x,2)+y*(diff(y,x,1))^3==0,y,[0,1,2]).expand() # not tested
|
|
397
|
+
Traceback (click to the left for traceback)
|
|
398
|
+
...
|
|
399
|
+
NotImplementedError, "Maxima was unable to solve this ODE. Consider to set option contrib_ode to True."
|
|
400
|
+
|
|
401
|
+
::
|
|
402
|
+
|
|
403
|
+
sage: desolve(diff(y,x,2)+y*(diff(y,x,1))^3==0,y,[0,1,2],show_method=True) # not tested
|
|
404
|
+
Traceback (click to the left for traceback)
|
|
405
|
+
...
|
|
406
|
+
NotImplementedError, "Maxima was unable to solve this ODE. Consider to set option contrib_ode to True."
|
|
407
|
+
|
|
408
|
+
Second order linear ODE::
|
|
409
|
+
|
|
410
|
+
sage: desolve(diff(y,x,2)+2*diff(y,x)+y == cos(x),y)
|
|
411
|
+
(_K2*x + _K1)*e^(-x) + 1/2*sin(x)
|
|
412
|
+
|
|
413
|
+
::
|
|
414
|
+
|
|
415
|
+
sage: desolve(diff(y,x,2)+2*diff(y,x)+y == cos(x),y,show_method=True)
|
|
416
|
+
[(_K2*x + _K1)*e^(-x) + 1/2*sin(x), 'variationofparameters']
|
|
417
|
+
|
|
418
|
+
::
|
|
419
|
+
|
|
420
|
+
sage: desolve(diff(y,x,2)+2*diff(y,x)+y == cos(x),y,[0,3,1])
|
|
421
|
+
1/2*(7*x + 6)*e^(-x) + 1/2*sin(x)
|
|
422
|
+
|
|
423
|
+
::
|
|
424
|
+
|
|
425
|
+
sage: desolve(diff(y,x,2)+2*diff(y,x)+y == cos(x),y,[0,3,1],show_method=True)
|
|
426
|
+
[1/2*(7*x + 6)*e^(-x) + 1/2*sin(x), 'variationofparameters']
|
|
427
|
+
|
|
428
|
+
::
|
|
429
|
+
|
|
430
|
+
sage: desolve(diff(y,x,2)+2*diff(y,x)+y == cos(x),y,[0,3,pi/2,2])
|
|
431
|
+
3*(x*(e^(1/2*pi) - 2)/pi + 1)*e^(-x) + 1/2*sin(x)
|
|
432
|
+
|
|
433
|
+
::
|
|
434
|
+
|
|
435
|
+
sage: desolve(diff(y,x,2)+2*diff(y,x)+y == cos(x),y,[0,3,pi/2,2],show_method=True)
|
|
436
|
+
[3*(x*(e^(1/2*pi) - 2)/pi + 1)*e^(-x) + 1/2*sin(x), 'variationofparameters']
|
|
437
|
+
|
|
438
|
+
::
|
|
439
|
+
|
|
440
|
+
sage: desolve(diff(y,x,2)+2*diff(y,x)+y == 0,y)
|
|
441
|
+
(_K2*x + _K1)*e^(-x)
|
|
442
|
+
|
|
443
|
+
::
|
|
444
|
+
|
|
445
|
+
sage: desolve(diff(y,x,2)+2*diff(y,x)+y == 0,y,show_method=True)
|
|
446
|
+
[(_K2*x + _K1)*e^(-x), 'constcoeff']
|
|
447
|
+
|
|
448
|
+
::
|
|
449
|
+
|
|
450
|
+
sage: desolve(diff(y,x,2)+2*diff(y,x)+y == 0,y,[0,3,1])
|
|
451
|
+
(4*x + 3)*e^(-x)
|
|
452
|
+
|
|
453
|
+
::
|
|
454
|
+
|
|
455
|
+
sage: desolve(diff(y,x,2)+2*diff(y,x)+y == 0,y,[0,3,1],show_method=True)
|
|
456
|
+
[(4*x + 3)*e^(-x), 'constcoeff']
|
|
457
|
+
|
|
458
|
+
::
|
|
459
|
+
|
|
460
|
+
sage: desolve(diff(y,x,2)+2*diff(y,x)+y == 0,y,[0,3,pi/2,2])
|
|
461
|
+
(2*x*(2*e^(1/2*pi) - 3)/pi + 3)*e^(-x)
|
|
462
|
+
|
|
463
|
+
::
|
|
464
|
+
|
|
465
|
+
sage: desolve(diff(y,x,2)+2*diff(y,x)+y == 0,y,[0,3,pi/2,2],show_method=True)
|
|
466
|
+
[(2*x*(2*e^(1/2*pi) - 3)/pi + 3)*e^(-x), 'constcoeff']
|
|
467
|
+
|
|
468
|
+
Using ``algorithm='fricas'`` we can invoke the differential
|
|
469
|
+
equation solver from FriCAS. For example, it can solve higher
|
|
470
|
+
order linear equations::
|
|
471
|
+
|
|
472
|
+
sage: de = x^3*diff(y, x, 3) + x^2*diff(y, x, 2) - 2*x*diff(y, x) + 2*y - 2*x^4
|
|
473
|
+
sage: Y = desolve(de, y, algorithm='fricas'); Y # optional - fricas
|
|
474
|
+
(2*x^3 - 3*x^2 + 1)*_C0/x + (x^3 - 1)*_C1/x
|
|
475
|
+
+ (x^3 - 3*x^2 - 1)*_C2/x + 1/15*(x^5 - 10*x^3 + 20*x^2 + 4)/x
|
|
476
|
+
|
|
477
|
+
The initial conditions are then interpreted as `[x_0, y(x_0),
|
|
478
|
+
y'(x_0), \ldots, y^(n)(x_0)]`::
|
|
479
|
+
|
|
480
|
+
sage: Y = desolve(de, y, ics=[1,3,7], algorithm='fricas'); Y # optional - fricas
|
|
481
|
+
1/15*(x^5 + 15*x^3 + 50*x^2 - 21)/x
|
|
482
|
+
|
|
483
|
+
FriCAS can also solve some non-linear equations::
|
|
484
|
+
|
|
485
|
+
sage: de = diff(y, x) == y / (x+y*log(y))
|
|
486
|
+
sage: Y = desolve(de, y, algorithm='fricas'); Y # optional - fricas
|
|
487
|
+
1/2*(log(y(x))^2*y(x) - 2*x)/y(x)
|
|
488
|
+
|
|
489
|
+
TESTS:
|
|
490
|
+
|
|
491
|
+
:issue:`9961` fixed (allow assumptions on the dependent variable in desolve)::
|
|
492
|
+
|
|
493
|
+
sage: y=function('y')(x); assume(x>0); assume(y>0)
|
|
494
|
+
sage: sage.calculus.calculus.maxima('domain:real') # needed since Maxima 5.26.0 to get the answer as below
|
|
495
|
+
real
|
|
496
|
+
sage: desolve(x*diff(y,x)-x*sqrt(y^2+x^2)-y == 0, y, contrib_ode=True)
|
|
497
|
+
[x - arcsinh(y(x)/x) == _C]
|
|
498
|
+
|
|
499
|
+
:issue:`10682` updated Maxima to 5.26, and it started to show a different
|
|
500
|
+
solution in the complex domain for the ODE above::
|
|
501
|
+
|
|
502
|
+
sage: forget()
|
|
503
|
+
sage: sage.calculus.calculus.maxima('domain:complex') # back to the default complex domain
|
|
504
|
+
complex
|
|
505
|
+
sage: assume(x>0)
|
|
506
|
+
sage: assume(y>0)
|
|
507
|
+
sage: desolve(x*diff(y,x)-x*sqrt(y^2+x^2)-y == 0, y, contrib_ode=True)
|
|
508
|
+
[x - arcsinh(y(x)^2/(x*sqrt(y(x)^2))) - arcsinh(y(x)/x) + 1/2*log(4*(x^2 + 2*y(x)^2 + 2*sqrt(x^2*y(x)^2 + y(x)^4))/x^2) == _C]
|
|
509
|
+
|
|
510
|
+
:issue:`6479` fixed::
|
|
511
|
+
|
|
512
|
+
sage: x = var('x')
|
|
513
|
+
sage: y = function('y')(x)
|
|
514
|
+
sage: desolve( diff(y,x,x) == 0, y, [0,0,1])
|
|
515
|
+
x
|
|
516
|
+
|
|
517
|
+
::
|
|
518
|
+
|
|
519
|
+
sage: desolve( diff(y,x,x) == 0, y, [0,1,1])
|
|
520
|
+
x + 1
|
|
521
|
+
|
|
522
|
+
:issue:`9835` fixed::
|
|
523
|
+
|
|
524
|
+
sage: x = var('x')
|
|
525
|
+
sage: y = function('y')(x)
|
|
526
|
+
sage: desolve(diff(y,x,2)+y*(1-y^2)==0,y,[0,-1,1,1])
|
|
527
|
+
Traceback (most recent call last):
|
|
528
|
+
...
|
|
529
|
+
NotImplementedError: Unable to use initial condition for this equation (freeofx).
|
|
530
|
+
|
|
531
|
+
:issue:`8931` fixed::
|
|
532
|
+
|
|
533
|
+
sage: x=var('x'); f=function('f')(x); k=var('k'); assume(k>0)
|
|
534
|
+
sage: desolve(diff(f,x,2)/f==k,f,ivar=x)
|
|
535
|
+
_K1*e^(sqrt(k)*x) + _K2*e^(-sqrt(k)*x)
|
|
536
|
+
|
|
537
|
+
:issue:`15775` fixed::
|
|
538
|
+
|
|
539
|
+
sage: forget()
|
|
540
|
+
sage: y = function('y')(x)
|
|
541
|
+
sage: desolve(diff(y, x) == sqrt(abs(y)), dvar=y, ivar=x)
|
|
542
|
+
sqrt(-y(x))*(sgn(y(x)) - 1) + (sgn(y(x)) + 1)*sqrt(y(x)) == _C + x
|
|
543
|
+
|
|
544
|
+
AUTHORS:
|
|
545
|
+
|
|
546
|
+
- David Joyner (1-2006)
|
|
547
|
+
- Robert Bradshaw (10-2008)
|
|
548
|
+
- Robert Marik (10-2009)
|
|
549
|
+
"""
|
|
550
|
+
if isinstance(de, Expression) and de.is_relational():
|
|
551
|
+
de = de.lhs() - de.rhs()
|
|
552
|
+
if isinstance(dvar, Expression) and dvar.is_symbol():
|
|
553
|
+
raise ValueError("You have to declare dependent variable as a function evaluated at the independent variable, eg. y=function('y')(x)")
|
|
554
|
+
# for backwards compatibility
|
|
555
|
+
if isinstance(dvar, list):
|
|
556
|
+
dvar, ivar = dvar
|
|
557
|
+
elif ivar is None:
|
|
558
|
+
ivars = de.variables()
|
|
559
|
+
ivars = [t for t in ivars if t is not dvar]
|
|
560
|
+
if len(ivars) != 1:
|
|
561
|
+
raise ValueError("Unable to determine independent variable, please specify.")
|
|
562
|
+
ivar = ivars[0]
|
|
563
|
+
|
|
564
|
+
if algorithm == "fricas":
|
|
565
|
+
return fricas_desolve(de, dvar, ics, ivar)
|
|
566
|
+
elif algorithm != "maxima":
|
|
567
|
+
raise ValueError("unknown algorithm %s" % algorithm)
|
|
568
|
+
|
|
569
|
+
de00 = de._maxima_()
|
|
570
|
+
P = de00.parent()
|
|
571
|
+
dvar_str = P(dvar.operator()).str()
|
|
572
|
+
ivar_str = P(ivar).str()
|
|
573
|
+
de00 = de00.str()
|
|
574
|
+
|
|
575
|
+
def sanitize_var(exprs):
|
|
576
|
+
return exprs.replace("'" + dvar_str + "(" + ivar_str + ")", dvar_str)
|
|
577
|
+
de0 = sanitize_var(de00)
|
|
578
|
+
ode_solver = "ode2"
|
|
579
|
+
cmd = "(TEMP:%s(%s,%s,%s), if TEMP=false then TEMP else substitute(%s=%s(%s),TEMP))" % (ode_solver, de0, dvar_str, ivar_str, dvar_str, dvar_str, ivar_str)
|
|
580
|
+
# we produce string like this
|
|
581
|
+
# ode2('diff(y,x,2)+2*'diff(y,x,1)+y-cos(x),y(x),x)
|
|
582
|
+
soln = P(cmd)
|
|
583
|
+
|
|
584
|
+
if str(soln).strip() == 'false':
|
|
585
|
+
if contrib_ode:
|
|
586
|
+
ode_solver = "contrib_ode"
|
|
587
|
+
P("load('contrib_ode)")
|
|
588
|
+
cmd = "(TEMP:%s(%s,%s,%s), if TEMP=false then TEMP else substitute(%s=%s(%s),TEMP))" % (ode_solver, de0, dvar_str, ivar_str, dvar_str, dvar_str, ivar_str)
|
|
589
|
+
# we produce string like this
|
|
590
|
+
# (TEMP:contrib_ode(x*('diff(y,x,1))^2-(x*y+1)*'diff(y,x,1)+y,y,x), if TEMP=false then TEMP else substitute(y=y(x),TEMP))
|
|
591
|
+
soln = P(cmd)
|
|
592
|
+
if str(soln).strip() == 'false':
|
|
593
|
+
raise NotImplementedError("Maxima was unable to solve this ODE.")
|
|
594
|
+
else:
|
|
595
|
+
raise NotImplementedError("Maxima was unable to solve this ODE. Consider to set option contrib_ode to True.")
|
|
596
|
+
|
|
597
|
+
if show_method:
|
|
598
|
+
maxima_method = P("method")
|
|
599
|
+
|
|
600
|
+
if ics is not None:
|
|
601
|
+
if not (isinstance(soln.sage(), Expression) and soln.sage().is_relational()):
|
|
602
|
+
if not show_method:
|
|
603
|
+
maxima_method = P("method")
|
|
604
|
+
raise NotImplementedError("Unable to use initial condition for this equation (%s)." % (str(maxima_method).strip()))
|
|
605
|
+
if len(ics) == 2:
|
|
606
|
+
tempic = (ivar == ics[0])._maxima_().str()
|
|
607
|
+
tempic = tempic + "," + (dvar == ics[1])._maxima_().str()
|
|
608
|
+
cmd = "(TEMP:ic1(%s(%s,%s,%s),%s),substitute(%s=%s(%s),TEMP))" % (ode_solver, de00, dvar_str, ivar_str, tempic, dvar_str, dvar_str, ivar_str)
|
|
609
|
+
cmd = sanitize_var(cmd)
|
|
610
|
+
# we produce string like this
|
|
611
|
+
# (TEMP:ic2(ode2('diff(y,x,2)+2*'diff(y,x,1)+y-cos(x),y,x),x=0,y=3,'diff(y,x)=1),substitute(y=y(x),TEMP))
|
|
612
|
+
soln = P(cmd)
|
|
613
|
+
if len(ics) == 3:
|
|
614
|
+
# fixed ic2 command from Maxima - we have to ensure that %k1, %k2 do not depend on variables, should be removed when fixed in Maxima
|
|
615
|
+
P("ic2_sage(soln,xa,ya,dya):=block([programmode:true,backsubst:true,singsolve:true,temp,%k2,%k1,TEMP_k], \
|
|
616
|
+
noteqn(xa), noteqn(ya), noteqn(dya), boundtest('%k1,%k1), boundtest('%k2,%k2), \
|
|
617
|
+
temp: lhs(soln) - rhs(soln), \
|
|
618
|
+
TEMP_k:solve([subst([xa,ya],soln), subst([dya,xa], lhs(dya)=-subst(0,lhs(dya),diff(temp,lhs(xa)))/diff(temp,lhs(ya)))],[%k1,%k2]), \
|
|
619
|
+
if not freeof(lhs(ya),TEMP_k) or not freeof(lhs(xa),TEMP_k) then return (false), \
|
|
620
|
+
temp: maplist(lambda([zz], subst(zz,soln)), TEMP_k), \
|
|
621
|
+
if length(temp)=1 then return(first(temp)) else return(temp))")
|
|
622
|
+
tempic = P(ivar == ics[0]).str()
|
|
623
|
+
tempic += "," + P(dvar == ics[1]).str()
|
|
624
|
+
tempic += ",'diff(" + dvar_str + "," + ivar_str + ")=" + P(ics[2]).str()
|
|
625
|
+
cmd = "(TEMP:ic2_sage(%s(%s,%s,%s),%s),substitute(%s=%s(%s),TEMP))" % (ode_solver, de00, dvar_str, ivar_str, tempic, dvar_str, dvar_str, ivar_str)
|
|
626
|
+
cmd = sanitize_var(cmd)
|
|
627
|
+
# we produce string like this
|
|
628
|
+
# (TEMP:ic2(ode2('diff(y,x,2)+2*'diff(y,x,1)+y-cos(x),y,x),x=0,y=3,'diff(y,x)=1),substitute(y=y(x),TEMP))
|
|
629
|
+
soln = P(cmd)
|
|
630
|
+
if str(soln).strip() == 'false':
|
|
631
|
+
raise NotImplementedError("Maxima was unable to solve this IVP. Remove the initial condition to get the general solution.")
|
|
632
|
+
if len(ics) == 4:
|
|
633
|
+
# fixed bc2 command from Maxima - we have to ensure that %k1, %k2 do not depend on variables, should be removed when fixed in Maxima
|
|
634
|
+
P("bc2_sage(soln,xa,ya,xb,yb):=block([programmode:true,backsubst:true,singsolve:true,temp,%k1,%k2,TEMP_k], \
|
|
635
|
+
noteqn(xa), noteqn(ya), noteqn(xb), noteqn(yb), boundtest('%k1,%k1), boundtest('%k2,%k2), \
|
|
636
|
+
TEMP_k:solve([subst([xa,ya],soln), subst([xb,yb],soln)], [%k1,%k2]), \
|
|
637
|
+
if not freeof(lhs(ya),TEMP_k) or not freeof(lhs(xa),TEMP_k) then return (false), \
|
|
638
|
+
temp: maplist(lambda([zz], subst(zz,soln)),TEMP_k), \
|
|
639
|
+
if length(temp)=1 then return(first(temp)) else return(temp))")
|
|
640
|
+
cmd = "bc2_sage(%s(%s,%s,%s),%s,%s=%s,%s,%s=%s)" % (ode_solver, de00, dvar_str, ivar_str, P(ivar == ics[0]).str(), dvar_str, P(ics[1]).str(), P(ivar == ics[2]).str(), dvar_str, P(ics[3]).str())
|
|
641
|
+
cmd = "(TEMP:%s,substitute(%s=%s(%s),TEMP))" % (cmd, dvar_str, dvar_str, ivar_str)
|
|
642
|
+
cmd = sanitize_var(cmd)
|
|
643
|
+
# we produce string like this
|
|
644
|
+
# (TEMP:bc2(ode2('diff(y,x,2)+2*'diff(y,x,1)+y-cos(x),y,x),x=0,y=3,x=%pi/2,y=2),substitute(y=y(x),TEMP))
|
|
645
|
+
soln = P(cmd)
|
|
646
|
+
if str(soln).strip() == 'false':
|
|
647
|
+
raise NotImplementedError("Maxima was unable to solve this BVP. Remove the initial condition to get the general solution.")
|
|
648
|
+
|
|
649
|
+
soln = soln.sage()
|
|
650
|
+
if isinstance(soln, Expression) and soln.is_relational() and soln.lhs() == dvar:
|
|
651
|
+
# Remark: Here we do not check that the right hand side does not depend on dvar.
|
|
652
|
+
# This probably will not happen for solutions obtained via ode2, anyway.
|
|
653
|
+
soln = soln.rhs()
|
|
654
|
+
if show_method:
|
|
655
|
+
return [soln, maxima_method.str()]
|
|
656
|
+
return soln
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
def desolve_laplace(de, dvar, ics=None, ivar=None):
|
|
660
|
+
"""
|
|
661
|
+
Solve an ODE using Laplace transforms. Initial conditions are optional.
|
|
662
|
+
|
|
663
|
+
INPUT:
|
|
664
|
+
|
|
665
|
+
- ``de`` -- a lambda expression representing the ODE (e.g. ``de =
|
|
666
|
+
diff(y,x,2) == diff(y,x)+sin(x)``)
|
|
667
|
+
|
|
668
|
+
- ``dvar`` -- the dependent variable (e.g. ``y``)
|
|
669
|
+
|
|
670
|
+
- ``ivar`` -- (optional) the independent variable (hereafter called
|
|
671
|
+
`x`), which must be specified if there is more than one
|
|
672
|
+
independent variable in the equation.
|
|
673
|
+
|
|
674
|
+
- ``ics`` -- list of numbers representing initial conditions, (e.g.
|
|
675
|
+
``f(0)=1``, ``f'(0)=2`` corresponds to ``ics = [0,1,2]``)
|
|
676
|
+
|
|
677
|
+
OUTPUT: solution of the ODE as symbolic expression
|
|
678
|
+
|
|
679
|
+
EXAMPLES::
|
|
680
|
+
|
|
681
|
+
sage: u=function('u')(x)
|
|
682
|
+
sage: eq = diff(u,x) - exp(-x) - u == 0
|
|
683
|
+
sage: desolve_laplace(eq,u)
|
|
684
|
+
1/2*(2*u(0) + 1)*e^x - 1/2*e^(-x)
|
|
685
|
+
|
|
686
|
+
We can use initial conditions::
|
|
687
|
+
|
|
688
|
+
sage: desolve_laplace(eq,u,ics=[0,3])
|
|
689
|
+
-1/2*e^(-x) + 7/2*e^x
|
|
690
|
+
|
|
691
|
+
The initial conditions do not persist in the system (as they persisted
|
|
692
|
+
in previous versions)::
|
|
693
|
+
|
|
694
|
+
sage: desolve_laplace(eq,u)
|
|
695
|
+
1/2*(2*u(0) + 1)*e^x - 1/2*e^(-x)
|
|
696
|
+
|
|
697
|
+
::
|
|
698
|
+
|
|
699
|
+
sage: f=function('f')(x)
|
|
700
|
+
sage: eq = diff(f,x) + f == 0
|
|
701
|
+
sage: desolve_laplace(eq,f,[0,1])
|
|
702
|
+
e^(-x)
|
|
703
|
+
|
|
704
|
+
::
|
|
705
|
+
|
|
706
|
+
sage: x = var('x')
|
|
707
|
+
sage: f = function('f')(x)
|
|
708
|
+
sage: de = diff(f,x,x) - 2*diff(f,x) + f
|
|
709
|
+
sage: desolve_laplace(de,f)
|
|
710
|
+
-x*e^x*f(0) + x*e^x*D[0](f)(0) + e^x*f(0)
|
|
711
|
+
|
|
712
|
+
::
|
|
713
|
+
|
|
714
|
+
sage: desolve_laplace(de,f,ics=[0,1,2])
|
|
715
|
+
x*e^x + e^x
|
|
716
|
+
|
|
717
|
+
TESTS:
|
|
718
|
+
|
|
719
|
+
Check that :issue:`4839` is fixed::
|
|
720
|
+
|
|
721
|
+
sage: t = var('t')
|
|
722
|
+
sage: x = function('x')(t)
|
|
723
|
+
sage: soln = desolve_laplace(diff(x,t)+x==1, x, ics=[0,2])
|
|
724
|
+
sage: soln
|
|
725
|
+
e^(-t) + 1
|
|
726
|
+
|
|
727
|
+
::
|
|
728
|
+
|
|
729
|
+
sage: soln(t=3)
|
|
730
|
+
e^(-3) + 1
|
|
731
|
+
|
|
732
|
+
AUTHORS:
|
|
733
|
+
|
|
734
|
+
- David Joyner (1-2006,8-2007)
|
|
735
|
+
|
|
736
|
+
- Robert Marik (10-2009)
|
|
737
|
+
"""
|
|
738
|
+
# This is the original code from David Joyner (inputs and outputs strings)
|
|
739
|
+
# maxima("de:"+de._repr_()+"=0;")
|
|
740
|
+
# if ics is not None:
|
|
741
|
+
# d = len(ics)
|
|
742
|
+
# for i in range(d-1):
|
|
743
|
+
# ic = "atvalue(diff("+vars[1]+"("+vars[0]+"),"+str(vars[0])+","+str(i)+"),"+str(vars[0])+"="+str(ics[0])+","+str(ics[1+i])+")"
|
|
744
|
+
# maxima(ic)
|
|
745
|
+
#
|
|
746
|
+
# cmd = "desolve("+de._repr_()+","+vars[1]+"("+vars[0]+"));"
|
|
747
|
+
# return maxima(cmd).rhs()._maxima_init_()
|
|
748
|
+
|
|
749
|
+
# verbatim copy from desolve - begin
|
|
750
|
+
if isinstance(de, Expression) and de.is_relational():
|
|
751
|
+
de = de.lhs() - de.rhs()
|
|
752
|
+
if isinstance(dvar, Expression) and dvar.is_symbol():
|
|
753
|
+
raise ValueError("You have to declare dependent variable as a function evaluated at the independent variable, eg. y=function('y')(x)")
|
|
754
|
+
# for backwards compatibility
|
|
755
|
+
if isinstance(dvar, list):
|
|
756
|
+
dvar, ivar = dvar
|
|
757
|
+
elif ivar is None:
|
|
758
|
+
ivars = de.variables()
|
|
759
|
+
ivars = [t for t in ivars if t is not dvar]
|
|
760
|
+
if len(ivars) != 1:
|
|
761
|
+
raise ValueError("Unable to determine independent variable, please specify.")
|
|
762
|
+
ivar = ivars[0]
|
|
763
|
+
# verbatim copy from desolve - end
|
|
764
|
+
|
|
765
|
+
dvar_str = str(dvar)
|
|
766
|
+
|
|
767
|
+
def sanitize_var(exprs):
|
|
768
|
+
# 'y(x) -> y(x)
|
|
769
|
+
return exprs.replace("'" + dvar_str, dvar_str)
|
|
770
|
+
|
|
771
|
+
de0 = de._maxima_()
|
|
772
|
+
P = de0.parent()
|
|
773
|
+
i = dvar_str.find('(')
|
|
774
|
+
dvar_str = dvar_str[:i + 1] + '_SAGE_VAR_' + dvar_str[i + 1:]
|
|
775
|
+
cmd = sanitize_var("desolve(" + de0.str() + "," + dvar_str + ")")
|
|
776
|
+
soln = P(cmd).rhs()
|
|
777
|
+
if str(soln).strip() == 'false':
|
|
778
|
+
raise NotImplementedError("Maxima was unable to solve this ODE.")
|
|
779
|
+
soln = soln.sage()
|
|
780
|
+
if ics is not None:
|
|
781
|
+
d = len(ics)
|
|
782
|
+
for i in range(d - 1):
|
|
783
|
+
soln = eval('soln.substitute(diff(dvar,ivar,i)(' + str(ivar) + '=ics[0])==ics[i+1])')
|
|
784
|
+
return soln
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
def desolve_system(des, vars, ics=None, ivar=None, algorithm='maxima'):
|
|
788
|
+
r"""
|
|
789
|
+
Solve a system of any size of 1st order ODEs. Initial conditions
|
|
790
|
+
are optional.
|
|
791
|
+
|
|
792
|
+
One dimensional systems are passed to :meth:`desolve_laplace`.
|
|
793
|
+
|
|
794
|
+
INPUT:
|
|
795
|
+
|
|
796
|
+
- ``des`` -- list of ODEs
|
|
797
|
+
|
|
798
|
+
- ``vars`` -- list of dependent variables
|
|
799
|
+
|
|
800
|
+
- ``ics`` -- (optional) list of initial values for ``ivar`` and ``vars``;
|
|
801
|
+
if ``ics`` is defined, it should provide initial conditions for each
|
|
802
|
+
variable, otherwise an exception would be raised
|
|
803
|
+
|
|
804
|
+
- ``ivar`` -- (optional) the independent variable, which must be
|
|
805
|
+
specified if there is more than one independent variable in the
|
|
806
|
+
equation
|
|
807
|
+
|
|
808
|
+
- ``algorithm`` -- (default: ``'maxima'``) one of
|
|
809
|
+
|
|
810
|
+
* ``'maxima'`` -- use maxima
|
|
811
|
+
* ``'fricas'`` -- use FriCAS (the optional fricas spkg has to be installed)
|
|
812
|
+
|
|
813
|
+
EXAMPLES::
|
|
814
|
+
|
|
815
|
+
sage: t = var('t')
|
|
816
|
+
sage: x = function('x')(t)
|
|
817
|
+
sage: y = function('y')(t)
|
|
818
|
+
sage: de1 = diff(x,t) + y - 1 == 0
|
|
819
|
+
sage: de2 = diff(y,t) - x + 1 == 0
|
|
820
|
+
sage: desolve_system([de1, de2], [x,y])
|
|
821
|
+
[x(t) == (x(0) - 1)*cos(t) - (y(0) - 1)*sin(t) + 1,
|
|
822
|
+
y(t) == (y(0) - 1)*cos(t) + (x(0) - 1)*sin(t) + 1]
|
|
823
|
+
|
|
824
|
+
The same system solved using FriCAS::
|
|
825
|
+
|
|
826
|
+
sage: desolve_system([de1, de2], [x,y], algorithm='fricas') # optional - fricas
|
|
827
|
+
[x(t) == _C0*cos(t) + cos(t)^2 + _C1*sin(t) + sin(t)^2,
|
|
828
|
+
y(t) == -_C1*cos(t) + _C0*sin(t) + 1]
|
|
829
|
+
|
|
830
|
+
Now we give some initial conditions::
|
|
831
|
+
|
|
832
|
+
sage: sol = desolve_system([de1, de2], [x,y], ics=[0,1,2]); sol
|
|
833
|
+
[x(t) == -sin(t) + 1, y(t) == cos(t) + 1]
|
|
834
|
+
|
|
835
|
+
::
|
|
836
|
+
|
|
837
|
+
sage: solnx, solny = sol[0].rhs(), sol[1].rhs()
|
|
838
|
+
sage: plot([solnx,solny],(0,1)) # not tested
|
|
839
|
+
sage: parametric_plot((solnx,solny),(0,1)) # not tested
|
|
840
|
+
|
|
841
|
+
TESTS:
|
|
842
|
+
|
|
843
|
+
Check that :issue:`9823` is fixed::
|
|
844
|
+
|
|
845
|
+
sage: t = var('t')
|
|
846
|
+
sage: x = function('x')(t)
|
|
847
|
+
sage: de1 = diff(x,t) + 1 == 0
|
|
848
|
+
sage: desolve_system([de1], [x])
|
|
849
|
+
-t + x(0)
|
|
850
|
+
|
|
851
|
+
Check that :issue:`16568` is fixed::
|
|
852
|
+
|
|
853
|
+
sage: t = var('t')
|
|
854
|
+
sage: x = function('x')(t)
|
|
855
|
+
sage: y = function('y')(t)
|
|
856
|
+
sage: de1 = diff(x,t) + y - 1 == 0
|
|
857
|
+
sage: de2 = diff(y,t) - x + 1 == 0
|
|
858
|
+
sage: des = [de1,de2]
|
|
859
|
+
sage: ics = [0,1,-1]
|
|
860
|
+
sage: vars = [x,y]
|
|
861
|
+
sage: sol = desolve_system(des, vars, ics); sol
|
|
862
|
+
[x(t) == 2*sin(t) + 1, y(t) == -2*cos(t) + 1]
|
|
863
|
+
|
|
864
|
+
::
|
|
865
|
+
|
|
866
|
+
sage: solx, soly = sol[0].rhs(), sol[1].rhs()
|
|
867
|
+
sage: RR(solx(t=3))
|
|
868
|
+
1.28224001611973
|
|
869
|
+
|
|
870
|
+
::
|
|
871
|
+
|
|
872
|
+
sage: P1 = plot([solx,soly], (0,1)) # needs sage.plot
|
|
873
|
+
sage: P2 = parametric_plot((solx,soly), (0,1)) # needs sage.plot
|
|
874
|
+
|
|
875
|
+
Now type ``show(P1)``, ``show(P2)`` to view these plots.
|
|
876
|
+
|
|
877
|
+
Check that :issue:`9824` is fixed::
|
|
878
|
+
|
|
879
|
+
sage: t = var('t')
|
|
880
|
+
sage: epsilon = var('epsilon')
|
|
881
|
+
sage: x1 = function('x1')(t)
|
|
882
|
+
sage: x2 = function('x2')(t)
|
|
883
|
+
sage: de1 = diff(x1,t) == epsilon
|
|
884
|
+
sage: de2 = diff(x2,t) == -2
|
|
885
|
+
sage: desolve_system([de1, de2], [x1, x2], ivar=t)
|
|
886
|
+
[x1(t) == epsilon*t + x1(0), x2(t) == -2*t + x2(0)]
|
|
887
|
+
sage: desolve_system([de1, de2], [x1, x2], ics=[1,1], ivar=t)
|
|
888
|
+
Traceback (most recent call last):
|
|
889
|
+
...
|
|
890
|
+
ValueError: Initial conditions aren't complete: number of vars is different
|
|
891
|
+
from number of dependent variables. Got ics = [1, 1], vars = [x1(t), x2(t)]
|
|
892
|
+
|
|
893
|
+
Check that :issue:`9825` is fixed::
|
|
894
|
+
|
|
895
|
+
sage: t = var('t')
|
|
896
|
+
sage: x1, x2=function("x1, x2")
|
|
897
|
+
sage: de1=x1(t).diff(t)==-3*(x2(t)-1)
|
|
898
|
+
sage: de2=x2(t).diff(t)==1
|
|
899
|
+
sage: Sol=desolve_system([de1, de2],[x1(t),x2(t)],ivar=t) ; Sol
|
|
900
|
+
[x1(t) == -3/2*t^2 - 3*t*x2(0) + 3*t + x1(0), x2(t) == t + x2(0)]
|
|
901
|
+
|
|
902
|
+
|
|
903
|
+
AUTHORS:
|
|
904
|
+
|
|
905
|
+
- Robert Bradshaw (10-2008)
|
|
906
|
+
- Sergey Bykov (10-2014)
|
|
907
|
+
"""
|
|
908
|
+
if ics is not None:
|
|
909
|
+
if len(ics) != (len(vars) + 1):
|
|
910
|
+
raise ValueError("Initial conditions aren't complete: number of vars is different from number of dependent variables. Got ics = {0}, vars = {1}".format(ics, vars))
|
|
911
|
+
|
|
912
|
+
if len(des) == 1 and algorithm == "maxima":
|
|
913
|
+
return desolve_laplace(des[0], vars[0], ics=ics, ivar=ivar)
|
|
914
|
+
ivars = set()
|
|
915
|
+
for i, de in enumerate(des):
|
|
916
|
+
if not (isinstance(de, Expression) and de.is_relational()):
|
|
917
|
+
des[i] = de == 0
|
|
918
|
+
ivars = ivars.union(set(de.variables()))
|
|
919
|
+
if ivar is None:
|
|
920
|
+
ivars = ivars - set(vars)
|
|
921
|
+
if len(ivars) != 1:
|
|
922
|
+
raise ValueError("Unable to determine independent variable, please specify.")
|
|
923
|
+
ivar = list(ivars)[0]
|
|
924
|
+
|
|
925
|
+
if algorithm == "fricas":
|
|
926
|
+
return fricas_desolve_system(des, vars, ics, ivar)
|
|
927
|
+
elif algorithm != "maxima":
|
|
928
|
+
raise ValueError("unknown algorithm %s" % algorithm)
|
|
929
|
+
|
|
930
|
+
dvars = [v._maxima_() for v in vars]
|
|
931
|
+
if ics is not None:
|
|
932
|
+
ivar_ic = ics[0]
|
|
933
|
+
for dvar, ic in zip(dvars, ics[1:]):
|
|
934
|
+
dvar.atvalue(ivar == ivar_ic, ic)
|
|
935
|
+
soln = dvars[0].parent().desolve(des, dvars)
|
|
936
|
+
if str(soln).strip() == 'false':
|
|
937
|
+
raise NotImplementedError("Maxima was unable to solve this system.")
|
|
938
|
+
soln = list(soln)
|
|
939
|
+
for i, sol in enumerate(soln):
|
|
940
|
+
soln[i] = sol.sage()
|
|
941
|
+
if ics is not None:
|
|
942
|
+
ivar_ic = ics[0]
|
|
943
|
+
for dvar, ic in zip(dvars, ics[:1]):
|
|
944
|
+
dvar.atvalue(ivar == ivar_ic, dvar)
|
|
945
|
+
return soln
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
def eulers_method(f, x0, y0, h, x1, algorithm='table'):
|
|
949
|
+
r"""
|
|
950
|
+
This implements Euler's method for finding numerically the
|
|
951
|
+
solution of the 1st order ODE `y' = f(x,y)`, `y(a)=c`. The ``x``
|
|
952
|
+
column of the table increments from `x_0` to `x_1` by `h` (so
|
|
953
|
+
`(x_1-x_0)/h` must be an integer). In the ``y`` column, the new
|
|
954
|
+
`y`-value equals the old `y`-value plus the corresponding entry in the
|
|
955
|
+
last column.
|
|
956
|
+
|
|
957
|
+
.. NOTE::
|
|
958
|
+
|
|
959
|
+
This function is for pedagogical purposes only.
|
|
960
|
+
|
|
961
|
+
EXAMPLES::
|
|
962
|
+
|
|
963
|
+
sage: from sage.calculus.desolvers import eulers_method
|
|
964
|
+
sage: x,y = PolynomialRing(QQ,2,"xy").gens()
|
|
965
|
+
sage: eulers_method(5*x+y-5,0,1,1/2,1)
|
|
966
|
+
x y h*f(x,y)
|
|
967
|
+
0 1 -2
|
|
968
|
+
1/2 -1 -7/4
|
|
969
|
+
1 -11/4 -11/8
|
|
970
|
+
|
|
971
|
+
::
|
|
972
|
+
|
|
973
|
+
sage: x,y = PolynomialRing(QQ,2,"xy").gens()
|
|
974
|
+
sage: eulers_method(5*x+y-5,0,1,1/2,1,algorithm='none')
|
|
975
|
+
[[0, 1], [1/2, -1], [1, -11/4], [3/2, -33/8]]
|
|
976
|
+
|
|
977
|
+
::
|
|
978
|
+
|
|
979
|
+
sage: RR = RealField(sci_not=0, prec=4, rnd='RNDU')
|
|
980
|
+
sage: x,y = PolynomialRing(RR,2,"xy").gens()
|
|
981
|
+
sage: eulers_method(5*x+y-5,0,1,1/2,1,algorithm="None")
|
|
982
|
+
[[0, 1], [1/2, -1.0], [1, -2.7], [3/2, -4.0]]
|
|
983
|
+
|
|
984
|
+
::
|
|
985
|
+
|
|
986
|
+
sage: RR = RealField(sci_not=0, prec=4, rnd='RNDU')
|
|
987
|
+
sage: x,y=PolynomialRing(RR,2,"xy").gens()
|
|
988
|
+
sage: eulers_method(5*x+y-5,0,1,1/2,1)
|
|
989
|
+
x y h*f(x,y)
|
|
990
|
+
0 1 -2.0
|
|
991
|
+
1/2 -1.0 -1.7
|
|
992
|
+
1 -2.7 -1.3
|
|
993
|
+
|
|
994
|
+
::
|
|
995
|
+
|
|
996
|
+
sage: x,y=PolynomialRing(QQ,2,"xy").gens()
|
|
997
|
+
sage: eulers_method(5*x+y-5,1,1,1/3,2)
|
|
998
|
+
x y h*f(x,y)
|
|
999
|
+
1 1 1/3
|
|
1000
|
+
4/3 4/3 1
|
|
1001
|
+
5/3 7/3 17/9
|
|
1002
|
+
2 38/9 83/27
|
|
1003
|
+
|
|
1004
|
+
::
|
|
1005
|
+
|
|
1006
|
+
sage: eulers_method(5*x+y-5,0,1,1/2,1,algorithm='none')
|
|
1007
|
+
[[0, 1], [1/2, -1], [1, -11/4], [3/2, -33/8]]
|
|
1008
|
+
|
|
1009
|
+
::
|
|
1010
|
+
|
|
1011
|
+
sage: pts = eulers_method(5*x+y-5,0,1,1/2,1,algorithm='none')
|
|
1012
|
+
sage: P1 = list_plot(pts) # needs sage.plot
|
|
1013
|
+
sage: P2 = line(pts) # needs sage.plot
|
|
1014
|
+
sage: (P1 + P2).show() # needs sage.plot
|
|
1015
|
+
|
|
1016
|
+
AUTHORS:
|
|
1017
|
+
|
|
1018
|
+
- David Joyner
|
|
1019
|
+
"""
|
|
1020
|
+
if algorithm == "table":
|
|
1021
|
+
print("%10s %20s %25s" % ("x", "y", "h*f(x,y)"))
|
|
1022
|
+
n = int((1.0) * (x1 - x0) / h)
|
|
1023
|
+
x00 = x0
|
|
1024
|
+
y00 = y0
|
|
1025
|
+
soln = [[x00, y00]]
|
|
1026
|
+
for i in range(n + 1):
|
|
1027
|
+
if algorithm == "table":
|
|
1028
|
+
print("%10r %20r %20r" % (x00, y00, h * f(x00, y00)))
|
|
1029
|
+
y00 = y00 + h * f(x00, y00)
|
|
1030
|
+
x00 = x00 + h
|
|
1031
|
+
soln.append([x00, y00])
|
|
1032
|
+
if algorithm != "table":
|
|
1033
|
+
return soln
|
|
1034
|
+
|
|
1035
|
+
|
|
1036
|
+
def eulers_method_2x2(f, g, t0, x0, y0, h, t1, algorithm='table'):
|
|
1037
|
+
r"""
|
|
1038
|
+
This implements Euler's method for finding numerically the
|
|
1039
|
+
solution of the 1st order system of two ODEs
|
|
1040
|
+
|
|
1041
|
+
.. MATH::
|
|
1042
|
+
|
|
1043
|
+
\begin{aligned}
|
|
1044
|
+
x' &= f(t, x, y), x(t_0)=x_0 \\
|
|
1045
|
+
y' &= g(t, x, y), y(t_0)=y_0.
|
|
1046
|
+
\end{aligned}
|
|
1047
|
+
|
|
1048
|
+
The ``t`` column of the table increments from `t_0` to `t_1` by `h`
|
|
1049
|
+
(so `\frac{t_1-t_0}{h}` must be an integer). In the ``x`` column,
|
|
1050
|
+
the new `x`-value equals the old `x`-value plus the corresponding
|
|
1051
|
+
entry in the next (third) column. In the ``y`` column, the new
|
|
1052
|
+
`y`-value equals the old `y`-value plus the corresponding entry in the
|
|
1053
|
+
next (last) column.
|
|
1054
|
+
|
|
1055
|
+
.. NOTE::
|
|
1056
|
+
|
|
1057
|
+
This function is for pedagogical purposes only.
|
|
1058
|
+
|
|
1059
|
+
EXAMPLES::
|
|
1060
|
+
|
|
1061
|
+
sage: from sage.calculus.desolvers import eulers_method_2x2
|
|
1062
|
+
sage: t, x, y = PolynomialRing(QQ,3,"txy").gens()
|
|
1063
|
+
sage: f = x+y+t; g = x-y
|
|
1064
|
+
sage: eulers_method_2x2(f,g, 0, 0, 0, 1/3, 1,algorithm='none')
|
|
1065
|
+
[[0, 0, 0], [1/3, 0, 0], [2/3, 1/9, 0], [1, 10/27, 1/27], [4/3, 68/81, 4/27]]
|
|
1066
|
+
|
|
1067
|
+
::
|
|
1068
|
+
|
|
1069
|
+
sage: eulers_method_2x2(f,g, 0, 0, 0, 1/3, 1)
|
|
1070
|
+
t x h*f(t,x,y) y h*g(t,x,y)
|
|
1071
|
+
0 0 0 0 0
|
|
1072
|
+
1/3 0 1/9 0 0
|
|
1073
|
+
2/3 1/9 7/27 0 1/27
|
|
1074
|
+
1 10/27 38/81 1/27 1/9
|
|
1075
|
+
|
|
1076
|
+
::
|
|
1077
|
+
|
|
1078
|
+
sage: RR = RealField(sci_not=0, prec=4, rnd='RNDU')
|
|
1079
|
+
sage: t,x,y=PolynomialRing(RR,3,"txy").gens()
|
|
1080
|
+
sage: f = x+y+t; g = x-y
|
|
1081
|
+
sage: eulers_method_2x2(f,g, 0, 0, 0, 1/3, 1)
|
|
1082
|
+
t x h*f(t,x,y) y h*g(t,x,y)
|
|
1083
|
+
0 0 0.00 0 0.00
|
|
1084
|
+
1/3 0.00 0.13 0.00 0.00
|
|
1085
|
+
2/3 0.13 0.29 0.00 0.043
|
|
1086
|
+
1 0.41 0.57 0.043 0.15
|
|
1087
|
+
|
|
1088
|
+
To numerically approximate `y(1)`, where `(1+t^2)y''+y'-y=0`,
|
|
1089
|
+
`y(0)=1`, `y'(0)=-1`, using 4 steps of Euler's method, first
|
|
1090
|
+
convert to a system: `y_1' = y_2`, `y_1(0)=1`; `y_2' =
|
|
1091
|
+
\frac{y_1-y_2}{1+t^2}`, `y_2(0)=-1`.::
|
|
1092
|
+
|
|
1093
|
+
sage: RR = RealField(sci_not=0, prec=4, rnd='RNDU')
|
|
1094
|
+
sage: t, x, y=PolynomialRing(RR,3,"txy").gens()
|
|
1095
|
+
sage: f = y; g = (x-y)/(1+t^2)
|
|
1096
|
+
sage: eulers_method_2x2(f,g, 0, 1, -1, 1/4, 1)
|
|
1097
|
+
t x h*f(t,x,y) y h*g(t,x,y)
|
|
1098
|
+
0 1 -0.25 -1 0.50
|
|
1099
|
+
1/4 0.75 -0.12 -0.50 0.29
|
|
1100
|
+
1/2 0.63 -0.054 -0.21 0.19
|
|
1101
|
+
3/4 0.63 -0.0078 -0.031 0.11
|
|
1102
|
+
1 0.63 0.020 0.079 0.071
|
|
1103
|
+
|
|
1104
|
+
To numerically approximate `y(1)`, where `y''+ty'+y=0`, `y(0)=1`, `y'(0)=0`::
|
|
1105
|
+
|
|
1106
|
+
sage: t,x,y=PolynomialRing(RR,3,"txy").gens()
|
|
1107
|
+
sage: f = y; g = -x-y*t
|
|
1108
|
+
sage: eulers_method_2x2(f,g, 0, 1, 0, 1/4, 1)
|
|
1109
|
+
t x h*f(t,x,y) y h*g(t,x,y)
|
|
1110
|
+
0 1 0.00 0 -0.25
|
|
1111
|
+
1/4 1.0 -0.062 -0.25 -0.23
|
|
1112
|
+
1/2 0.94 -0.11 -0.46 -0.17
|
|
1113
|
+
3/4 0.88 -0.15 -0.62 -0.10
|
|
1114
|
+
1 0.75 -0.17 -0.68 -0.015
|
|
1115
|
+
|
|
1116
|
+
AUTHORS:
|
|
1117
|
+
|
|
1118
|
+
- David Joyner
|
|
1119
|
+
"""
|
|
1120
|
+
if algorithm == "table":
|
|
1121
|
+
print("%10s %20s %25s %20s %20s" % ("t", "x", "h*f(t,x,y)", "y", "h*g(t,x,y)"))
|
|
1122
|
+
n = int((1.0) * (t1 - t0) / h)
|
|
1123
|
+
t00 = t0
|
|
1124
|
+
x00 = x0
|
|
1125
|
+
y00 = y0
|
|
1126
|
+
soln = [[t00, x00, y00]]
|
|
1127
|
+
for i in range(n + 1):
|
|
1128
|
+
if algorithm == "table":
|
|
1129
|
+
print("%10r %20r %25r %20r %20r" % (t00, x00, h * f(t00, x00, y00), y00, h * g(t00, x00, y00)))
|
|
1130
|
+
x01 = x00 + h * f(t00, x00, y00)
|
|
1131
|
+
y00 = y00 + h * g(t00, x00, y00)
|
|
1132
|
+
x00 = x01
|
|
1133
|
+
t00 = t00 + h
|
|
1134
|
+
soln.append([t00, x00, y00])
|
|
1135
|
+
if algorithm != "table":
|
|
1136
|
+
return soln
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
def eulers_method_2x2_plot(f, g, t0, x0, y0, h, t1):
|
|
1140
|
+
r"""
|
|
1141
|
+
Plot solution of ODE.
|
|
1142
|
+
|
|
1143
|
+
This plots the solution in the rectangle with sides ``(xrange[0],xrange[1])`` and
|
|
1144
|
+
``(yrange[0],yrange[1])``, and plots using Euler's method the
|
|
1145
|
+
numerical solution of the 1st order ODEs `x' = f(t,x,y)`,
|
|
1146
|
+
`x(a)=x_0`, `y' = g(t,x,y)`, `y(a) = y_0`.
|
|
1147
|
+
|
|
1148
|
+
.. NOTE::
|
|
1149
|
+
|
|
1150
|
+
This function is for pedagogical purposes only.
|
|
1151
|
+
|
|
1152
|
+
EXAMPLES:
|
|
1153
|
+
|
|
1154
|
+
The following example plots the solution to
|
|
1155
|
+
`\theta''+\sin(\theta)=0`, `\theta(0)=\frac 34`, `\theta'(0) =
|
|
1156
|
+
0`. Type ``P[0].show()`` to plot the solution,
|
|
1157
|
+
``(P[0]+P[1]).show()`` to plot `(t,\theta(t))` and
|
|
1158
|
+
`(t,\theta'(t))`::
|
|
1159
|
+
|
|
1160
|
+
sage: from sage.calculus.desolvers import eulers_method_2x2_plot
|
|
1161
|
+
sage: f = lambda z : z[2]; g = lambda z : -sin(z[1])
|
|
1162
|
+
sage: P = eulers_method_2x2_plot(f,g, 0.0, 0.75, 0.0, 0.1, 1.0) # needs sage.plot
|
|
1163
|
+
"""
|
|
1164
|
+
from sage.plot.line import line
|
|
1165
|
+
|
|
1166
|
+
n = int((1.0) * (t1 - t0) / h)
|
|
1167
|
+
t00 = t0
|
|
1168
|
+
x00 = x0
|
|
1169
|
+
y00 = y0
|
|
1170
|
+
soln = [[t00, x00, y00]]
|
|
1171
|
+
for i in range(n + 1):
|
|
1172
|
+
x01 = x00 + h * f([t00, x00, y00])
|
|
1173
|
+
y00 = y00 + h * g([t00, x00, y00])
|
|
1174
|
+
x00 = x01
|
|
1175
|
+
t00 = t00 + h
|
|
1176
|
+
soln.append([t00, x00, y00])
|
|
1177
|
+
Q1 = line([[x[0], x[1]] for x in soln], rgbcolor=(.25, .125, .75))
|
|
1178
|
+
Q2 = line([[x[0], x[2]] for x in soln], rgbcolor=(.5, .125, .25))
|
|
1179
|
+
return [Q1, Q2]
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
def desolve_rk4_determine_bounds(ics, end_points=None):
|
|
1183
|
+
"""
|
|
1184
|
+
Used to determine bounds for numerical integration.
|
|
1185
|
+
|
|
1186
|
+
- If ``end_points`` is None, the interval for integration is from ``ics[0]``
|
|
1187
|
+
to ``ics[0]+10``
|
|
1188
|
+
|
|
1189
|
+
- If ``end_points`` is ``a`` or ``[a]``, the interval for integration is from ``min(ics[0],a)``
|
|
1190
|
+
to ``max(ics[0],a)``
|
|
1191
|
+
|
|
1192
|
+
- If ``end_points`` is ``[a,b]``, the interval for integration is from ``min(ics[0],a)``
|
|
1193
|
+
to ``max(ics[0],b)``
|
|
1194
|
+
|
|
1195
|
+
EXAMPLES::
|
|
1196
|
+
|
|
1197
|
+
sage: from sage.calculus.desolvers import desolve_rk4_determine_bounds
|
|
1198
|
+
sage: desolve_rk4_determine_bounds([0,2],1)
|
|
1199
|
+
(0, 1)
|
|
1200
|
+
|
|
1201
|
+
::
|
|
1202
|
+
|
|
1203
|
+
sage: desolve_rk4_determine_bounds([0,2])
|
|
1204
|
+
(0, 10)
|
|
1205
|
+
|
|
1206
|
+
::
|
|
1207
|
+
|
|
1208
|
+
sage: desolve_rk4_determine_bounds([0,2],[-2])
|
|
1209
|
+
(-2, 0)
|
|
1210
|
+
|
|
1211
|
+
::
|
|
1212
|
+
|
|
1213
|
+
sage: desolve_rk4_determine_bounds([0,2],[-2,4])
|
|
1214
|
+
(-2, 4)
|
|
1215
|
+
"""
|
|
1216
|
+
if end_points is None:
|
|
1217
|
+
return ics[0], ics[0] + 10
|
|
1218
|
+
if not isinstance(end_points, list):
|
|
1219
|
+
end_points = [end_points]
|
|
1220
|
+
if len(end_points) == 1:
|
|
1221
|
+
return min(ics[0], end_points[0]), max(ics[0], end_points[0])
|
|
1222
|
+
else:
|
|
1223
|
+
return min(ics[0], end_points[0]), max(ics[0], end_points[1])
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
def desolve_rk4(de, dvar, ics=None, ivar=None, end_points=None, step=0.1, output='list', **kwds):
|
|
1227
|
+
"""
|
|
1228
|
+
Solve numerically one first-order ordinary differential
|
|
1229
|
+
equation.
|
|
1230
|
+
|
|
1231
|
+
INPUT:
|
|
1232
|
+
|
|
1233
|
+
Input is similar to ``desolve`` command. The differential equation can be
|
|
1234
|
+
written in a form close to the ``plot_slope_field`` or ``desolve`` command.
|
|
1235
|
+
|
|
1236
|
+
- Variant 1 (function in two variables)
|
|
1237
|
+
|
|
1238
|
+
- ``de`` -- right hand side, i.e. the function `f(x,y)` from ODE `y'=f(x,y)`
|
|
1239
|
+
|
|
1240
|
+
- ``dvar`` -- dependent variable (symbolic variable declared by var)
|
|
1241
|
+
|
|
1242
|
+
- Variant 2 (symbolic equation)
|
|
1243
|
+
|
|
1244
|
+
- ``de`` -- equation, including term with ``diff(y,x)``
|
|
1245
|
+
|
|
1246
|
+
- ``dvar`` -- dependent variable (declared as function of independent variable)
|
|
1247
|
+
|
|
1248
|
+
- Other parameters
|
|
1249
|
+
|
|
1250
|
+
- ``ivar`` -- should be specified, if there are more variables or if the equation is autonomous
|
|
1251
|
+
|
|
1252
|
+
- ``ics`` -- initial conditions in the form ``[x0,y0]``
|
|
1253
|
+
|
|
1254
|
+
- ``end_points`` -- the end points of the interval
|
|
1255
|
+
|
|
1256
|
+
- if ``end_points`` is a or [a], we integrate between ``min(ics[0],a)`` and ``max(ics[0],a)``
|
|
1257
|
+
- if ``end_points`` is None, we use ``end_points=ics[0]+10``
|
|
1258
|
+
|
|
1259
|
+
- if end_points is [a,b] we integrate between ``min(ics[0], a)`` and ``max(ics[0], b)``
|
|
1260
|
+
|
|
1261
|
+
- ``step`` -- (default: 0.1) the length of the step (positive number)
|
|
1262
|
+
|
|
1263
|
+
- ``output`` -- (default: ``'list'``) one of ``'list'``,
|
|
1264
|
+
``'plot'``, ``'slope_field'`` (graph of the solution with slope field)
|
|
1265
|
+
|
|
1266
|
+
OUTPUT:
|
|
1267
|
+
|
|
1268
|
+
Return a list of points, or plot produced by ``list_plot``,
|
|
1269
|
+
optionally with slope field.
|
|
1270
|
+
|
|
1271
|
+
.. SEEALSO::
|
|
1272
|
+
|
|
1273
|
+
:func:`ode_solver`.
|
|
1274
|
+
|
|
1275
|
+
EXAMPLES::
|
|
1276
|
+
|
|
1277
|
+
sage: from sage.calculus.desolvers import desolve_rk4
|
|
1278
|
+
|
|
1279
|
+
Variant 2 for input - more common in numerics::
|
|
1280
|
+
|
|
1281
|
+
sage: x,y = var('x,y')
|
|
1282
|
+
sage: desolve_rk4(x*y*(2-y),y,ics=[0,1],end_points=1,step=0.5)
|
|
1283
|
+
[[0, 1], [0.5, 1.12419127424558], [1.0, 1.46159016228882...]]
|
|
1284
|
+
|
|
1285
|
+
Variant 1 for input - we can pass ODE in the form used by
|
|
1286
|
+
desolve function In this example we integrate backwards, since
|
|
1287
|
+
``end_points < ics[0]``::
|
|
1288
|
+
|
|
1289
|
+
sage: y = function('y')(x)
|
|
1290
|
+
sage: desolve_rk4(diff(y,x)+y*(y-1) == x-2,y,ics=[1,1],step=0.5, end_points=0)
|
|
1291
|
+
[[0.0, 8.904257108962112], [0.5, 1.90932794536153...], [1, 1]]
|
|
1292
|
+
|
|
1293
|
+
Here we show how to plot simple pictures. For more advanced
|
|
1294
|
+
applications use list_plot instead. To see the resulting picture
|
|
1295
|
+
use ``show(P)`` in Sage notebook. ::
|
|
1296
|
+
|
|
1297
|
+
sage: x,y = var('x,y')
|
|
1298
|
+
sage: P = desolve_rk4(y*(2-y), y, ics=[0,.1], ivar=x, # needs sage.plot
|
|
1299
|
+
....: output='slope_field', end_points=[-4,6], thickness=3)
|
|
1300
|
+
|
|
1301
|
+
ALGORITHM:
|
|
1302
|
+
|
|
1303
|
+
`4`-th order Runge-Kutta method. Wrapper for command ``rk`` in
|
|
1304
|
+
Maxima's dynamics package. Perhaps could be faster by using
|
|
1305
|
+
fast_float instead.
|
|
1306
|
+
|
|
1307
|
+
AUTHORS:
|
|
1308
|
+
|
|
1309
|
+
- Robert Marik (10-2009)
|
|
1310
|
+
"""
|
|
1311
|
+
if ics is None:
|
|
1312
|
+
raise ValueError("No initial conditions, specify with ics=[x0,y0].")
|
|
1313
|
+
|
|
1314
|
+
if output not in ['list', 'plot', 'slope_field']:
|
|
1315
|
+
raise ValueError("Option output should be 'list', 'plot' or 'slope_field'.")
|
|
1316
|
+
|
|
1317
|
+
if ivar is None:
|
|
1318
|
+
ivars = de.variables()
|
|
1319
|
+
ivars = [t for t in ivars if t != dvar]
|
|
1320
|
+
if len(ivars) != 1:
|
|
1321
|
+
raise ValueError("Unable to determine independent variable, please specify.")
|
|
1322
|
+
ivar = ivars[0]
|
|
1323
|
+
|
|
1324
|
+
step = abs(step)
|
|
1325
|
+
|
|
1326
|
+
def desolve_rk4_inner(de, dvar):
|
|
1327
|
+
de0 = de._maxima_()
|
|
1328
|
+
maxima("load('dynamics)")
|
|
1329
|
+
lower_bound, upper_bound = desolve_rk4_determine_bounds(ics, end_points)
|
|
1330
|
+
sol_1, sol_2 = [], []
|
|
1331
|
+
if lower_bound < ics[0]:
|
|
1332
|
+
cmd = "rk(%s,%s,%s,[%s,%s,%s,%s])\
|
|
1333
|
+
" % (de0.str(), '_SAGE_VAR_' + str(dvar), str(ics[1]), '_SAGE_VAR_' + str(ivar), str(ics[0]), lower_bound, -step)
|
|
1334
|
+
sol_1 = maxima(cmd).sage()
|
|
1335
|
+
sol_1.pop(0)
|
|
1336
|
+
sol_1.reverse()
|
|
1337
|
+
if upper_bound > ics[0]:
|
|
1338
|
+
cmd = "rk(%s,%s,%s,[%s,%s,%s,%s])\
|
|
1339
|
+
" % (de0.str(), '_SAGE_VAR_' + str(dvar), str(ics[1]), '_SAGE_VAR_' + str(ivar), str(ics[0]), upper_bound, step)
|
|
1340
|
+
sol_2 = maxima(cmd).sage()
|
|
1341
|
+
sol_2.pop(0)
|
|
1342
|
+
sol = sol_1
|
|
1343
|
+
sol.extend([[ics[0], ics[1]]])
|
|
1344
|
+
sol.extend(sol_2)
|
|
1345
|
+
|
|
1346
|
+
if output == 'list':
|
|
1347
|
+
return sol
|
|
1348
|
+
from sage.plot.plot import list_plot
|
|
1349
|
+
from sage.plot.plot_field import plot_slope_field
|
|
1350
|
+
R = list_plot(sol, plotjoined=True, **kwds)
|
|
1351
|
+
if output == 'plot':
|
|
1352
|
+
return R
|
|
1353
|
+
if output == 'slope_field':
|
|
1354
|
+
XMIN = sol[0][0]
|
|
1355
|
+
YMIN = sol[0][1]
|
|
1356
|
+
XMAX = XMIN
|
|
1357
|
+
YMAX = YMIN
|
|
1358
|
+
for s, t in sol:
|
|
1359
|
+
XMAX = max(s, XMAX)
|
|
1360
|
+
XMIN = min(s, XMIN)
|
|
1361
|
+
YMAX = max(t, YMAX)
|
|
1362
|
+
YMIN = min(t, YMIN)
|
|
1363
|
+
return plot_slope_field(de, (ivar, XMIN, XMAX), (dvar, YMIN, YMAX)) + R
|
|
1364
|
+
|
|
1365
|
+
if not (isinstance(dvar, Expression) and dvar.is_symbol()):
|
|
1366
|
+
from sage.calculus.functional import diff
|
|
1367
|
+
from sage.symbolic.relation import solve
|
|
1368
|
+
from sage.symbolic.ring import SR
|
|
1369
|
+
if isinstance(de, Expression) and de.is_relational():
|
|
1370
|
+
de = de.lhs() - de.rhs()
|
|
1371
|
+
# consider to add warning if the solution is not unique
|
|
1372
|
+
de = solve(de, diff(dvar, ivar), solution_dict=True)
|
|
1373
|
+
if len(de) != 1:
|
|
1374
|
+
raise NotImplementedError("Sorry, cannot find explicit formula for right-hand side of the ODE.")
|
|
1375
|
+
with SR.temp_var() as dummy_dvar:
|
|
1376
|
+
return desolve_rk4_inner(de[0][diff(dvar, ivar)].subs({dvar: dummy_dvar}), dummy_dvar)
|
|
1377
|
+
else:
|
|
1378
|
+
return desolve_rk4_inner(de, dvar)
|
|
1379
|
+
|
|
1380
|
+
|
|
1381
|
+
def desolve_system_rk4(des, vars, ics=None, ivar=None, end_points=None, step=0.1):
|
|
1382
|
+
r"""
|
|
1383
|
+
Solve numerically a system of first-order ordinary differential
|
|
1384
|
+
equations using the `4`-th order Runge-Kutta method. Wrapper for
|
|
1385
|
+
Maxima command ``rk``.
|
|
1386
|
+
|
|
1387
|
+
INPUT:
|
|
1388
|
+
|
|
1389
|
+
Input is similar to ``desolve_system`` and ``desolve_rk4`` commands
|
|
1390
|
+
|
|
1391
|
+
- ``des`` -- right hand sides of the system
|
|
1392
|
+
|
|
1393
|
+
- ``vars`` -- dependent variables
|
|
1394
|
+
|
|
1395
|
+
- ``ivar`` -- (optional) should be specified, if there are more variables or
|
|
1396
|
+
if the equation is autonomous and the independent variable is
|
|
1397
|
+
missing
|
|
1398
|
+
|
|
1399
|
+
- ``ics`` -- initial conditions in the form ``[x0,y01,y02,y03,....]``
|
|
1400
|
+
|
|
1401
|
+
- ``end_points`` -- the end points of the interval
|
|
1402
|
+
|
|
1403
|
+
- if ``end_points`` is a or [a], we integrate on between ``min(ics[0], a)`` and ``max(ics[0], a)``
|
|
1404
|
+
- if ``end_points`` is None, we use ``end_points=ics[0]+10``
|
|
1405
|
+
|
|
1406
|
+
- if ``end_points`` is [a,b] we integrate on between ``min(ics[0], a)`` and ``max(ics[0], b)``
|
|
1407
|
+
|
|
1408
|
+
- ``step`` -- (default: 0.1) the length of the step
|
|
1409
|
+
|
|
1410
|
+
OUTPUT: a list of points
|
|
1411
|
+
|
|
1412
|
+
.. SEEALSO::
|
|
1413
|
+
|
|
1414
|
+
:func:`ode_solver`.
|
|
1415
|
+
|
|
1416
|
+
EXAMPLES::
|
|
1417
|
+
|
|
1418
|
+
sage: from sage.calculus.desolvers import desolve_system_rk4
|
|
1419
|
+
|
|
1420
|
+
Lotka Volterra system::
|
|
1421
|
+
|
|
1422
|
+
sage: from sage.calculus.desolvers import desolve_system_rk4
|
|
1423
|
+
sage: x,y,t = var('x y t')
|
|
1424
|
+
sage: P = desolve_system_rk4([x*(1-y),-y*(1-x)], [x,y], ics=[0,0.5,2],
|
|
1425
|
+
....: ivar=t, end_points=20)
|
|
1426
|
+
sage: Q = [[i,j] for i,j,k in P]
|
|
1427
|
+
sage: LP = list_plot(Q) # needs sage.plot
|
|
1428
|
+
|
|
1429
|
+
sage: Q = [[j,k] for i,j,k in P]
|
|
1430
|
+
sage: LP = list_plot(Q) # needs sage.plot
|
|
1431
|
+
|
|
1432
|
+
ALGORITHM:
|
|
1433
|
+
|
|
1434
|
+
`4`-th order Runge-Kutta method. Wrapper for command ``rk`` in Maxima's
|
|
1435
|
+
dynamics package. Perhaps could be faster by using ``fast_float``
|
|
1436
|
+
instead.
|
|
1437
|
+
|
|
1438
|
+
AUTHOR:
|
|
1439
|
+
|
|
1440
|
+
- Robert Marik (10-2009)
|
|
1441
|
+
"""
|
|
1442
|
+
if ics is None:
|
|
1443
|
+
raise ValueError("No initial conditions, specify with ics=[x0,y01,y02,...].")
|
|
1444
|
+
|
|
1445
|
+
ivars = set()
|
|
1446
|
+
|
|
1447
|
+
for de in des:
|
|
1448
|
+
ivars = ivars.union(set(de.variables()))
|
|
1449
|
+
if ivar is None:
|
|
1450
|
+
ivars = ivars - set(vars)
|
|
1451
|
+
if len(ivars) != 1:
|
|
1452
|
+
raise ValueError("Unable to determine independent variable, please specify.")
|
|
1453
|
+
ivar = list(ivars)[0]
|
|
1454
|
+
|
|
1455
|
+
dess = [de._maxima_().str() for de in des]
|
|
1456
|
+
desstr = "[" + ",".join(dess) + "]"
|
|
1457
|
+
varss = [varsi._maxima_().str() for varsi in vars]
|
|
1458
|
+
varstr = "[" + ",".join(varss) + "]"
|
|
1459
|
+
x0 = ics[0]
|
|
1460
|
+
icss = [ics[i]._maxima_().str() for i in range(1, len(ics))]
|
|
1461
|
+
icstr = "[" + ",".join(icss) + "]"
|
|
1462
|
+
step = abs(step)
|
|
1463
|
+
|
|
1464
|
+
maxima("load('dynamics)")
|
|
1465
|
+
lower_bound, upper_bound = desolve_rk4_determine_bounds(ics, end_points)
|
|
1466
|
+
sol_1, sol_2 = [], []
|
|
1467
|
+
if lower_bound < ics[0]:
|
|
1468
|
+
cmd = "rk(%s,%s,%s,[%s,%s,%s,%s])\
|
|
1469
|
+
" % (desstr, varstr, icstr, '_SAGE_VAR_' + str(ivar), str(x0), lower_bound, -step)
|
|
1470
|
+
sol_1 = maxima(cmd).sage()
|
|
1471
|
+
sol_1.pop(0)
|
|
1472
|
+
sol_1.reverse()
|
|
1473
|
+
if upper_bound > ics[0]:
|
|
1474
|
+
cmd = "rk(%s,%s,%s,[%s,%s,%s,%s])\
|
|
1475
|
+
" % (desstr, varstr, icstr, '_SAGE_VAR_' + str(ivar), str(x0), upper_bound, step)
|
|
1476
|
+
sol_2 = maxima(cmd).sage()
|
|
1477
|
+
sol_2.pop(0)
|
|
1478
|
+
sol = sol_1
|
|
1479
|
+
sol.append(ics)
|
|
1480
|
+
sol.extend(sol_2)
|
|
1481
|
+
|
|
1482
|
+
return sol
|
|
1483
|
+
|
|
1484
|
+
|
|
1485
|
+
def desolve_odeint(des, ics, times, dvars, ivar=None, compute_jac=False, args=(),
|
|
1486
|
+
rtol=None, atol=None, tcrit=None, h0=0.0, hmax=0.0, hmin=0.0, ixpr=0,
|
|
1487
|
+
mxstep=0, mxhnil=0, mxordn=12, mxords=5, printmessg=0):
|
|
1488
|
+
r"""
|
|
1489
|
+
Solve numerically a system of first-order ordinary differential equations
|
|
1490
|
+
using :func:`scipy:scipy.integrate.odeint`.
|
|
1491
|
+
|
|
1492
|
+
INPUT:
|
|
1493
|
+
|
|
1494
|
+
- ``des`` -- right hand sides of the system
|
|
1495
|
+
|
|
1496
|
+
- ``ics`` -- initial conditions
|
|
1497
|
+
|
|
1498
|
+
- ``times`` -- a sequence of time points in which the solution must be found
|
|
1499
|
+
|
|
1500
|
+
- ``dvars`` -- dependent variables. ATTENTION: the order must be the same as
|
|
1501
|
+
in ``des``, that means: ``d(dvars[i])/dt=des[i]``
|
|
1502
|
+
|
|
1503
|
+
- ``ivar`` -- independent variable, optional
|
|
1504
|
+
|
|
1505
|
+
- ``compute_jac`` -- boolean (default: ``False``); if ``True``, the
|
|
1506
|
+
Jacobian of ``des`` is computed and used during the integration of stiff
|
|
1507
|
+
systems
|
|
1508
|
+
|
|
1509
|
+
Other Parameters (taken from the documentation of the
|
|
1510
|
+
:func:`~scipy:scipy.integrate.odeint` function from
|
|
1511
|
+
:mod:`scipy:scipy.integrate`):
|
|
1512
|
+
|
|
1513
|
+
- ``rtol``, ``atol`` : float
|
|
1514
|
+
The input parameters ``rtol`` and ``atol`` determine the error
|
|
1515
|
+
control performed by the solver. The solver will control the
|
|
1516
|
+
vector, `e`, of estimated local errors in `y`, according to an
|
|
1517
|
+
inequality of the form:
|
|
1518
|
+
|
|
1519
|
+
max-norm of (e / ewt) <= 1
|
|
1520
|
+
|
|
1521
|
+
where ewt is a vector of positive error weights computed as:
|
|
1522
|
+
|
|
1523
|
+
ewt = rtol * abs(y) + atol
|
|
1524
|
+
|
|
1525
|
+
``rtol`` and ``atol`` can be either vectors the same length as `y` or scalars.
|
|
1526
|
+
|
|
1527
|
+
- ``tcrit`` : array
|
|
1528
|
+
Vector of critical points (e.g. singularities) where integration
|
|
1529
|
+
care should be taken.
|
|
1530
|
+
|
|
1531
|
+
- ``h0`` : float, (0: solver-determined)
|
|
1532
|
+
The step size to be attempted on the first step.
|
|
1533
|
+
|
|
1534
|
+
- ``hmax`` : float, (0: solver-determined)
|
|
1535
|
+
The maximum absolute step size allowed.
|
|
1536
|
+
|
|
1537
|
+
- ``hmin`` : float, (0: solver-determined)
|
|
1538
|
+
The minimum absolute step size allowed.
|
|
1539
|
+
|
|
1540
|
+
- ``ixpr`` : boolean.
|
|
1541
|
+
Whether to generate extra printing at method switches.
|
|
1542
|
+
|
|
1543
|
+
- ``mxstep`` : integer, (0: solver-determined)
|
|
1544
|
+
Maximum number of (internally defined) steps allowed for each
|
|
1545
|
+
integration point in t.
|
|
1546
|
+
|
|
1547
|
+
- ``mxhnil`` : integer, (0: solver-determined)
|
|
1548
|
+
Maximum number of messages printed.
|
|
1549
|
+
|
|
1550
|
+
- ``mxordn`` : integer, (0: solver-determined)
|
|
1551
|
+
Maximum order to be allowed for the nonstiff (Adams) method.
|
|
1552
|
+
|
|
1553
|
+
- ``mxords`` : integer, (0: solver-determined)
|
|
1554
|
+
Maximum order to be allowed for the stiff (BDF) method.
|
|
1555
|
+
|
|
1556
|
+
OUTPUT: a list with the solution of the system at each time in ``times``
|
|
1557
|
+
|
|
1558
|
+
EXAMPLES:
|
|
1559
|
+
|
|
1560
|
+
Lotka Volterra Equations::
|
|
1561
|
+
|
|
1562
|
+
sage: from sage.calculus.desolvers import desolve_odeint
|
|
1563
|
+
sage: x,y = var('x,y')
|
|
1564
|
+
sage: f = [x*(1-y), -y*(1-x)]
|
|
1565
|
+
sage: sol = desolve_odeint(f, [0.5,2], srange(0,10,0.1), [x,y]) # needs scipy
|
|
1566
|
+
sage: p = line(zip(sol[:,0],sol[:,1])) # needs scipy sage.plot
|
|
1567
|
+
sage: p.show() # needs scipy sage.plot
|
|
1568
|
+
|
|
1569
|
+
Lorenz Equations::
|
|
1570
|
+
|
|
1571
|
+
sage: x,y,z = var('x,y,z')
|
|
1572
|
+
sage: # Next we define the parameters
|
|
1573
|
+
sage: sigma = 10
|
|
1574
|
+
sage: rho = 28
|
|
1575
|
+
sage: beta = 8/3
|
|
1576
|
+
sage: # The Lorenz equations
|
|
1577
|
+
sage: lorenz = [sigma*(y-x),x*(rho-z)-y,x*y-beta*z]
|
|
1578
|
+
sage: # Time and initial conditions
|
|
1579
|
+
sage: times = srange(0,50.05,0.05)
|
|
1580
|
+
sage: ics = [0,1,1]
|
|
1581
|
+
sage: sol = desolve_odeint(lorenz, ics, times, [x,y,z], # needs scipy
|
|
1582
|
+
....: rtol=1e-13, atol=1e-14)
|
|
1583
|
+
|
|
1584
|
+
One-dimensional stiff system::
|
|
1585
|
+
|
|
1586
|
+
sage: y = var('y')
|
|
1587
|
+
sage: epsilon = 0.01
|
|
1588
|
+
sage: f = y^2*(1-y)
|
|
1589
|
+
sage: ic = epsilon
|
|
1590
|
+
sage: t = srange(0,2/epsilon,1)
|
|
1591
|
+
sage: sol = desolve_odeint(f, ic, t, y, # needs scipy
|
|
1592
|
+
....: rtol=1e-9, atol=1e-10, compute_jac=True)
|
|
1593
|
+
sage: p = points(zip(t,sol[:,0])) # needs scipy sage.plot
|
|
1594
|
+
sage: p.show() # needs scipy sage.plot
|
|
1595
|
+
|
|
1596
|
+
Another stiff system with some optional parameters with no
|
|
1597
|
+
default value::
|
|
1598
|
+
|
|
1599
|
+
sage: y1,y2,y3 = var('y1,y2,y3')
|
|
1600
|
+
sage: f1 = 77.27*(y2+y1*(1-8.375*1e-6*y1-y2))
|
|
1601
|
+
sage: f2 = 1/77.27*(y3-(1+y1)*y2)
|
|
1602
|
+
sage: f3 = 0.16*(y1-y3)
|
|
1603
|
+
sage: f = [f1,f2,f3]
|
|
1604
|
+
sage: ci = [0.2,0.4,0.7]
|
|
1605
|
+
sage: t = srange(0,10,0.01)
|
|
1606
|
+
sage: v = [y1,y2,y3]
|
|
1607
|
+
sage: sol = desolve_odeint(f, ci, t, v, rtol=1e-3, atol=1e-4, # needs scipy
|
|
1608
|
+
....: h0=0.1, hmax=1, hmin=1e-4, mxstep=1000, mxords=17)
|
|
1609
|
+
|
|
1610
|
+
AUTHOR:
|
|
1611
|
+
|
|
1612
|
+
- Oriol Castejon (05-2010)
|
|
1613
|
+
"""
|
|
1614
|
+
|
|
1615
|
+
from scipy.integrate import odeint
|
|
1616
|
+
|
|
1617
|
+
from sage.calculus.functions import jacobian
|
|
1618
|
+
from sage.ext.fast_eval import fast_float
|
|
1619
|
+
|
|
1620
|
+
def desolve_odeint_inner(ivar):
|
|
1621
|
+
# one-dimensional systems:
|
|
1622
|
+
if len(dvars) == 1:
|
|
1623
|
+
assert len(des) == 1
|
|
1624
|
+
dvar = dvars[0]
|
|
1625
|
+
de = des[0]
|
|
1626
|
+
func = lambda y, t: fast_float(de, dvar, ivar)(y.item(), t)
|
|
1627
|
+
if not compute_jac:
|
|
1628
|
+
Dfun = None
|
|
1629
|
+
else:
|
|
1630
|
+
J = diff(de, dvar)
|
|
1631
|
+
J = fast_float(J, dvar, ivar)
|
|
1632
|
+
|
|
1633
|
+
def Dfun(y, t):
|
|
1634
|
+
return [J(y.item(), t)]
|
|
1635
|
+
|
|
1636
|
+
# n-dimensional systems:
|
|
1637
|
+
else:
|
|
1638
|
+
variabs = dvars[:]
|
|
1639
|
+
variabs.append(ivar)
|
|
1640
|
+
desc = [fast_float(de, *variabs) for de in des]
|
|
1641
|
+
|
|
1642
|
+
def func(y, t):
|
|
1643
|
+
v = list(y[:])
|
|
1644
|
+
v.append(t)
|
|
1645
|
+
return [dec(*v) for dec in desc]
|
|
1646
|
+
|
|
1647
|
+
if not compute_jac:
|
|
1648
|
+
Dfun = None
|
|
1649
|
+
else:
|
|
1650
|
+
J = jacobian(des, dvars)
|
|
1651
|
+
J = [list(v) for v in J]
|
|
1652
|
+
J = fast_float(J, *variabs)
|
|
1653
|
+
|
|
1654
|
+
def Dfun(y, t):
|
|
1655
|
+
v = list(y[:])
|
|
1656
|
+
v.append(t)
|
|
1657
|
+
return [[element(*v) for element in row] for row in J]
|
|
1658
|
+
|
|
1659
|
+
return odeint(func, ics, times, args=args, Dfun=Dfun, rtol=rtol, atol=atol,
|
|
1660
|
+
tcrit=tcrit, h0=h0, hmax=hmax, hmin=hmin, ixpr=ixpr, mxstep=mxstep,
|
|
1661
|
+
mxhnil=mxhnil, mxordn=mxordn, mxords=mxords, printmessg=printmessg)
|
|
1662
|
+
|
|
1663
|
+
if isinstance(dvars, Expression) and dvars.is_symbol():
|
|
1664
|
+
dvars = [dvars]
|
|
1665
|
+
|
|
1666
|
+
if not isinstance(des, (list, tuple)):
|
|
1667
|
+
des = [des]
|
|
1668
|
+
|
|
1669
|
+
if ivar is None:
|
|
1670
|
+
all_vars = set().union(*[de.variables() for de in des])
|
|
1671
|
+
ivars = all_vars - set(dvars)
|
|
1672
|
+
|
|
1673
|
+
if len(ivars) == 1:
|
|
1674
|
+
return desolve_odeint_inner(next(iter(ivars)))
|
|
1675
|
+
elif not ivars:
|
|
1676
|
+
from sage.symbolic.ring import SR
|
|
1677
|
+
with SR.temp_var() as ivar:
|
|
1678
|
+
return desolve_odeint_inner(ivar)
|
|
1679
|
+
else:
|
|
1680
|
+
raise ValueError("Unable to determine independent variable, please specify.")
|
|
1681
|
+
return desolve_odeint_inner(ivar)
|
|
1682
|
+
|
|
1683
|
+
|
|
1684
|
+
def desolve_mintides(f, ics, initial, final, delta, tolrel=1e-16, tolabs=1e-16):
|
|
1685
|
+
r"""
|
|
1686
|
+
Solve numerically a system of first order differential equations using the
|
|
1687
|
+
taylor series integrator implemented in mintides.
|
|
1688
|
+
|
|
1689
|
+
INPUT:
|
|
1690
|
+
|
|
1691
|
+
- ``f`` -- symbolic function; its first argument will be the independent
|
|
1692
|
+
variable, . Its output should be de derivatives of the dependent variables.
|
|
1693
|
+
|
|
1694
|
+
- ``ics`` -- list or tuple with the initial conditions
|
|
1695
|
+
|
|
1696
|
+
- ``initial`` -- the starting value for the independent variable
|
|
1697
|
+
|
|
1698
|
+
- ``final`` -- the final value for the independent value
|
|
1699
|
+
|
|
1700
|
+
- ``delta`` -- the size of the steps in the output
|
|
1701
|
+
|
|
1702
|
+
- ``tolrel`` -- the relative tolerance for the method
|
|
1703
|
+
|
|
1704
|
+
- ``tolabs`` -- the absolute tolerance for the method
|
|
1705
|
+
|
|
1706
|
+
OUTPUT: list with the positions of the IVP
|
|
1707
|
+
|
|
1708
|
+
EXAMPLES:
|
|
1709
|
+
|
|
1710
|
+
We integrate a periodic orbit of the Kepler problem along 50 periods::
|
|
1711
|
+
|
|
1712
|
+
sage: var('t,x,y,X,Y')
|
|
1713
|
+
(t, x, y, X, Y)
|
|
1714
|
+
sage: f(t,x,y,X,Y)=[X, Y, -x/(x^2+y^2)^(3/2), -y/(x^2+y^2)^(3/2)]
|
|
1715
|
+
sage: ics = [0.8, 0, 0, 1.22474487139159]
|
|
1716
|
+
sage: t = 100*pi
|
|
1717
|
+
sage: sol = desolve_mintides(f, ics, 0, t, t, 1e-12, 1e-12) # optional -tides
|
|
1718
|
+
sage: sol # optional -tides # abs tol 1e-5
|
|
1719
|
+
[[0.000000000000000,
|
|
1720
|
+
0.800000000000000,
|
|
1721
|
+
0.000000000000000,
|
|
1722
|
+
0.000000000000000,
|
|
1723
|
+
1.22474487139159],
|
|
1724
|
+
[314.159265358979,
|
|
1725
|
+
0.800000000028622,
|
|
1726
|
+
-5.91973525754241e-9,
|
|
1727
|
+
7.56887091890590e-9,
|
|
1728
|
+
1.22474487136329]]
|
|
1729
|
+
|
|
1730
|
+
|
|
1731
|
+
ALGORITHM:
|
|
1732
|
+
|
|
1733
|
+
Uses TIDES.
|
|
1734
|
+
|
|
1735
|
+
REFERENCES:
|
|
1736
|
+
|
|
1737
|
+
- A. Abad, R. Barrio, F. Blesa, M. Rodriguez. Algorithm 924. *ACM
|
|
1738
|
+
Transactions on Mathematical Software* , *39* (1), 1-28.
|
|
1739
|
+
|
|
1740
|
+
- A. Abad, R. Barrio, F. Blesa, M. Rodriguez.
|
|
1741
|
+
`TIDES tutorial: Integrating ODEs by using the Taylor Series Method.
|
|
1742
|
+
<https://web.archive.org/web/20120206041615/http://www.unizar.es/acz/05Publicaciones/Monografias/MonografiasPublicadas/Monografia36/IndMonogr36.htm>`_
|
|
1743
|
+
"""
|
|
1744
|
+
import subprocess
|
|
1745
|
+
if subprocess.call('command -v gcc', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE):
|
|
1746
|
+
raise RuntimeError('Unable to run because gcc cannot be found')
|
|
1747
|
+
from sage.interfaces.tides import genfiles_mintides
|
|
1748
|
+
from sage.misc.temporary_file import tmp_dir
|
|
1749
|
+
tempdir = tmp_dir()
|
|
1750
|
+
intfile = os.path.join(tempdir, 'integrator.c')
|
|
1751
|
+
drfile = os.path.join(tempdir, 'driver.c')
|
|
1752
|
+
fileoutput = os.path.join(tempdir, 'output')
|
|
1753
|
+
runmefile = os.path.join(tempdir, 'runme')
|
|
1754
|
+
genfiles_mintides(intfile, drfile, f, [N(_) for _ in ics],
|
|
1755
|
+
N(initial), N(final), N(delta), N(tolrel),
|
|
1756
|
+
N(tolabs), fileoutput)
|
|
1757
|
+
subprocess.check_call('gcc -o ' + runmefile + ' ' + os.path.join(tempdir, '*.c ') +
|
|
1758
|
+
os.path.join('$SAGE_LOCAL', 'lib', 'libTIDES.a') + ' $LDFLAGS '
|
|
1759
|
+
+ os.path.join('-L$SAGE_LOCAL', 'lib ') + ' -lm -O2 ' +
|
|
1760
|
+
os.path.join('-I$SAGE_LOCAL', 'include '),
|
|
1761
|
+
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
1762
|
+
subprocess.check_call(os.path.join(tempdir, 'runme'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
1763
|
+
with open(fileoutput) as outfile:
|
|
1764
|
+
res = outfile.readlines()
|
|
1765
|
+
for i in range(len(res)):
|
|
1766
|
+
res[i] = [RealField()(_) for _ in res[i].split(' ') if len(_) > 2]
|
|
1767
|
+
shutil.rmtree(tempdir)
|
|
1768
|
+
return res
|
|
1769
|
+
|
|
1770
|
+
|
|
1771
|
+
def desolve_tides_mpfr(f, ics, initial, final, delta, tolrel=1e-16, tolabs=1e-16, digits=50):
|
|
1772
|
+
r"""
|
|
1773
|
+
Solve numerically a system of first order differential equations using the
|
|
1774
|
+
taylor series integrator in arbitrary precision implemented in tides.
|
|
1775
|
+
|
|
1776
|
+
INPUT:
|
|
1777
|
+
|
|
1778
|
+
- ``f`` -- symbolic function; its first argument will be the independent
|
|
1779
|
+
variable. Its output should be de derivatives of the dependent variables.
|
|
1780
|
+
|
|
1781
|
+
- ``ics`` -- list or tuple with the initial conditions
|
|
1782
|
+
|
|
1783
|
+
- ``initial`` -- the starting value for the independent variable
|
|
1784
|
+
|
|
1785
|
+
- ``final`` -- the final value for the independent value
|
|
1786
|
+
|
|
1787
|
+
- ``delta`` -- the size of the steps in the output
|
|
1788
|
+
|
|
1789
|
+
- ``tolrel`` -- the relative tolerance for the method
|
|
1790
|
+
|
|
1791
|
+
- ``tolabs`` -- the absolute tolerance for the method
|
|
1792
|
+
|
|
1793
|
+
- ``digits`` -- the digits of precision used in the computation
|
|
1794
|
+
|
|
1795
|
+
OUTPUT: list with the positions of the IVP
|
|
1796
|
+
|
|
1797
|
+
EXAMPLES:
|
|
1798
|
+
|
|
1799
|
+
We integrate the Lorenz equations with Saltzman values for the parameters
|
|
1800
|
+
along 10 periodic orbits with 100 digits of precision::
|
|
1801
|
+
|
|
1802
|
+
sage: var('t,x,y,z')
|
|
1803
|
+
(t, x, y, z)
|
|
1804
|
+
sage: s = 10
|
|
1805
|
+
sage: r = 28
|
|
1806
|
+
sage: b = 8/3
|
|
1807
|
+
sage: f(t,x,y,z)= [s*(y-x),x*(r-z)-y,x*y-b*z]
|
|
1808
|
+
sage: x0 = -13.7636106821342005250144010543616538641008648540923684535378642921202827747268115852940239346395038284
|
|
1809
|
+
sage: y0 = -19.5787519424517955388380414460095588661142400534276438649791334295426354746147526415973165506704676171
|
|
1810
|
+
sage: z0 = 27
|
|
1811
|
+
sage: T = 15.586522107161747275678702092126960705284805489972439358895215783190198756258880854355851082660142374
|
|
1812
|
+
sage: sol = desolve_tides_mpfr(f, [x0, y0, z0], 0, T, T, 1e-100, 1e-100, 100) # optional - tides
|
|
1813
|
+
sage: sol # optional -tides # abs tol 1e-50
|
|
1814
|
+
[[0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,
|
|
1815
|
+
-13.7636106821342005250144010543616538641008648540923684535378642921202827747268115852940239346395038,
|
|
1816
|
+
-19.5787519424517955388380414460095588661142400534276438649791334295426354746147526415973165506704676,
|
|
1817
|
+
27.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000],
|
|
1818
|
+
[15.5865221071617472756787020921269607052848054899724393588952157831901987562588808543558510826601424,
|
|
1819
|
+
-13.7636106821342005250144010543616538641008648540923684535378642921202827747268115852940239346315658,
|
|
1820
|
+
-19.5787519424517955388380414460095588661142400534276438649791334295426354746147526415973165506778440,
|
|
1821
|
+
26.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999636628]]
|
|
1822
|
+
|
|
1823
|
+
|
|
1824
|
+
ALGORITHM:
|
|
1825
|
+
|
|
1826
|
+
Uses TIDES.
|
|
1827
|
+
|
|
1828
|
+
|
|
1829
|
+
.. WARNING::
|
|
1830
|
+
|
|
1831
|
+
This requires the package tides.
|
|
1832
|
+
|
|
1833
|
+
REFERENCES:
|
|
1834
|
+
|
|
1835
|
+
- [ABBR2011]_
|
|
1836
|
+
- [ABBR2012]_
|
|
1837
|
+
"""
|
|
1838
|
+
import subprocess
|
|
1839
|
+
if subprocess.call('command -v gcc', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE):
|
|
1840
|
+
raise RuntimeError('Unable to run because gcc cannot be found')
|
|
1841
|
+
from sage.functions.log import log
|
|
1842
|
+
from sage.functions.other import ceil
|
|
1843
|
+
from sage.interfaces.tides import genfiles_mpfr
|
|
1844
|
+
from sage.misc.temporary_file import tmp_dir
|
|
1845
|
+
tempdir = tmp_dir()
|
|
1846
|
+
intfile = os.path.join(tempdir, 'integrator.c')
|
|
1847
|
+
drfile = os.path.join(tempdir, 'driver.c')
|
|
1848
|
+
fileoutput = os.path.join(tempdir, 'output')
|
|
1849
|
+
runmefile = os.path.join(tempdir, 'runme')
|
|
1850
|
+
genfiles_mpfr(intfile, drfile, f, ics, initial, final, delta, [], [],
|
|
1851
|
+
digits, tolrel, tolabs, fileoutput)
|
|
1852
|
+
subprocess.check_call('gcc -o ' + runmefile + ' ' + os.path.join(tempdir, '*.c ') +
|
|
1853
|
+
os.path.join('$SAGE_LOCAL', 'lib', 'libTIDES.a') + ' $LDFLAGS '
|
|
1854
|
+
+ os.path.join('-L$SAGE_LOCAL', 'lib ') + '-lmpfr -lgmp -lm -O2 -w ' +
|
|
1855
|
+
os.path.join('-I$SAGE_LOCAL', 'include '),
|
|
1856
|
+
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
1857
|
+
subprocess.check_call(os.path.join(tempdir, 'runme'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
1858
|
+
with open(fileoutput) as outfile:
|
|
1859
|
+
res = outfile.readlines()
|
|
1860
|
+
for i in range(len(res)):
|
|
1861
|
+
res[i] = [RealField(ceil(digits * log(10, 2)))(piece)
|
|
1862
|
+
for piece in res[i].split(' ') if len(piece) > 2]
|
|
1863
|
+
shutil.rmtree(tempdir)
|
|
1864
|
+
return res
|