passagemath-symbolics 10.8.1a1__cp311-cp311-macosx_13_0_arm64.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.
Files changed (182) hide show
  1. passagemath_symbolics/.dylibs/libgmp.10.dylib +0 -0
  2. passagemath_symbolics/__init__.py +3 -0
  3. passagemath_symbolics-10.8.1a1.dist-info/METADATA +186 -0
  4. passagemath_symbolics-10.8.1a1.dist-info/RECORD +182 -0
  5. passagemath_symbolics-10.8.1a1.dist-info/WHEEL +6 -0
  6. passagemath_symbolics-10.8.1a1.dist-info/top_level.txt +3 -0
  7. sage/all__sagemath_symbolics.py +17 -0
  8. sage/calculus/all.py +14 -0
  9. sage/calculus/calculus.py +2838 -0
  10. sage/calculus/desolvers.py +1864 -0
  11. sage/calculus/predefined.py +51 -0
  12. sage/calculus/tests.py +225 -0
  13. sage/calculus/var.cpython-311-darwin.so +0 -0
  14. sage/calculus/var.pyx +401 -0
  15. sage/dynamics/all__sagemath_symbolics.py +6 -0
  16. sage/dynamics/complex_dynamics/all.py +5 -0
  17. sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
  18. sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-311-darwin.so +0 -0
  19. sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1034 -0
  20. sage/ext/all__sagemath_symbolics.py +1 -0
  21. sage/ext_data/kenzo/CP2.txt +45 -0
  22. sage/ext_data/kenzo/CP3.txt +349 -0
  23. sage/ext_data/kenzo/CP4.txt +4774 -0
  24. sage/ext_data/kenzo/README.txt +49 -0
  25. sage/ext_data/kenzo/S4.txt +20 -0
  26. sage/ext_data/magma/latex/latex.m +1021 -0
  27. sage/ext_data/magma/latex/latex.spec +1 -0
  28. sage/ext_data/magma/sage/basic.m +356 -0
  29. sage/ext_data/magma/sage/sage.spec +1 -0
  30. sage/ext_data/magma/spec +9 -0
  31. sage/geometry/all__sagemath_symbolics.py +8 -0
  32. sage/geometry/hyperbolic_space/all.py +5 -0
  33. sage/geometry/hyperbolic_space/hyperbolic_coercion.py +755 -0
  34. sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
  35. sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2419 -0
  36. sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
  37. sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1083 -0
  38. sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
  39. sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
  40. sage/geometry/riemannian_manifolds/all.py +7 -0
  41. sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
  42. sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
  43. sage/interfaces/all__sagemath_symbolics.py +1 -0
  44. sage/interfaces/magma.py +2991 -0
  45. sage/interfaces/magma_free.py +90 -0
  46. sage/interfaces/maple.py +1402 -0
  47. sage/interfaces/mathematica.py +1345 -0
  48. sage/interfaces/mathics.py +1312 -0
  49. sage/interfaces/sympy.py +1398 -0
  50. sage/interfaces/sympy_wrapper.py +197 -0
  51. sage/interfaces/tides.py +938 -0
  52. sage/libs/all__sagemath_symbolics.py +6 -0
  53. sage/manifolds/all.py +7 -0
  54. sage/manifolds/calculus_method.py +553 -0
  55. sage/manifolds/catalog.py +437 -0
  56. sage/manifolds/chart.py +4010 -0
  57. sage/manifolds/chart_func.py +3416 -0
  58. sage/manifolds/continuous_map.py +2183 -0
  59. sage/manifolds/continuous_map_image.py +155 -0
  60. sage/manifolds/differentiable/affine_connection.py +2475 -0
  61. sage/manifolds/differentiable/all.py +1 -0
  62. sage/manifolds/differentiable/automorphismfield.py +1383 -0
  63. sage/manifolds/differentiable/automorphismfield_group.py +604 -0
  64. sage/manifolds/differentiable/bundle_connection.py +1445 -0
  65. sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
  66. sage/manifolds/differentiable/chart.py +1241 -0
  67. sage/manifolds/differentiable/curve.py +1028 -0
  68. sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
  69. sage/manifolds/differentiable/degenerate.py +559 -0
  70. sage/manifolds/differentiable/degenerate_submanifold.py +1668 -0
  71. sage/manifolds/differentiable/diff_form.py +1660 -0
  72. sage/manifolds/differentiable/diff_form_module.py +1062 -0
  73. sage/manifolds/differentiable/diff_map.py +1315 -0
  74. sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
  75. sage/manifolds/differentiable/examples/all.py +1 -0
  76. sage/manifolds/differentiable/examples/euclidean.py +2517 -0
  77. sage/manifolds/differentiable/examples/real_line.py +897 -0
  78. sage/manifolds/differentiable/examples/sphere.py +1186 -0
  79. sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
  80. sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
  81. sage/manifolds/differentiable/integrated_curve.py +4035 -0
  82. sage/manifolds/differentiable/levi_civita_connection.py +841 -0
  83. sage/manifolds/differentiable/manifold.py +4254 -0
  84. sage/manifolds/differentiable/manifold_homset.py +1826 -0
  85. sage/manifolds/differentiable/metric.py +3032 -0
  86. sage/manifolds/differentiable/mixed_form.py +1507 -0
  87. sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
  88. sage/manifolds/differentiable/multivector_module.py +800 -0
  89. sage/manifolds/differentiable/multivectorfield.py +1522 -0
  90. sage/manifolds/differentiable/poisson_tensor.py +268 -0
  91. sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
  92. sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
  93. sage/manifolds/differentiable/scalarfield.py +1343 -0
  94. sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
  95. sage/manifolds/differentiable/symplectic_form.py +912 -0
  96. sage/manifolds/differentiable/symplectic_form_test.py +220 -0
  97. sage/manifolds/differentiable/tangent_space.py +412 -0
  98. sage/manifolds/differentiable/tangent_vector.py +616 -0
  99. sage/manifolds/differentiable/tensorfield.py +4665 -0
  100. sage/manifolds/differentiable/tensorfield_module.py +963 -0
  101. sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
  102. sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
  103. sage/manifolds/differentiable/vector_bundle.py +1725 -0
  104. sage/manifolds/differentiable/vectorfield.py +1717 -0
  105. sage/manifolds/differentiable/vectorfield_module.py +2445 -0
  106. sage/manifolds/differentiable/vectorframe.py +1832 -0
  107. sage/manifolds/family.py +270 -0
  108. sage/manifolds/local_frame.py +1490 -0
  109. sage/manifolds/manifold.py +3090 -0
  110. sage/manifolds/manifold_homset.py +452 -0
  111. sage/manifolds/operators.py +359 -0
  112. sage/manifolds/point.py +994 -0
  113. sage/manifolds/scalarfield.py +3718 -0
  114. sage/manifolds/scalarfield_algebra.py +629 -0
  115. sage/manifolds/section.py +3111 -0
  116. sage/manifolds/section_module.py +831 -0
  117. sage/manifolds/structure.py +229 -0
  118. sage/manifolds/subset.py +2721 -0
  119. sage/manifolds/subsets/all.py +1 -0
  120. sage/manifolds/subsets/closure.py +131 -0
  121. sage/manifolds/subsets/pullback.py +883 -0
  122. sage/manifolds/topological_submanifold.py +891 -0
  123. sage/manifolds/trivialization.py +733 -0
  124. sage/manifolds/utilities.py +1348 -0
  125. sage/manifolds/vector_bundle.py +1347 -0
  126. sage/manifolds/vector_bundle_fiber.py +332 -0
  127. sage/manifolds/vector_bundle_fiber_element.py +111 -0
  128. sage/matrix/all__sagemath_symbolics.py +1 -0
  129. sage/matrix/matrix_symbolic_dense.cpython-311-darwin.so +0 -0
  130. sage/matrix/matrix_symbolic_dense.pxd +6 -0
  131. sage/matrix/matrix_symbolic_dense.pyx +1030 -0
  132. sage/matrix/matrix_symbolic_sparse.cpython-311-darwin.so +0 -0
  133. sage/matrix/matrix_symbolic_sparse.pxd +6 -0
  134. sage/matrix/matrix_symbolic_sparse.pyx +1038 -0
  135. sage/modules/all__sagemath_symbolics.py +1 -0
  136. sage/modules/vector_callable_symbolic_dense.py +105 -0
  137. sage/modules/vector_symbolic_dense.py +116 -0
  138. sage/modules/vector_symbolic_sparse.py +118 -0
  139. sage/rings/all__sagemath_symbolics.py +4 -0
  140. sage/rings/asymptotic/all.py +6 -0
  141. sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
  142. sage/rings/asymptotic/asymptotic_ring.py +4858 -0
  143. sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4106 -0
  144. sage/rings/asymptotic/growth_group.py +5373 -0
  145. sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
  146. sage/rings/asymptotic/term_monoid.py +5205 -0
  147. sage/rings/function_field/all__sagemath_symbolics.py +2 -0
  148. sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
  149. sage/symbolic/all.py +15 -0
  150. sage/symbolic/assumptions.py +987 -0
  151. sage/symbolic/benchmark.py +93 -0
  152. sage/symbolic/callable.py +456 -0
  153. sage/symbolic/callable.pyi +66 -0
  154. sage/symbolic/comparison_impl.pyi +38 -0
  155. sage/symbolic/complexity_measures.py +35 -0
  156. sage/symbolic/constants.py +1286 -0
  157. sage/symbolic/constants_c_impl.pyi +10 -0
  158. sage/symbolic/expression_conversion_algebraic.py +310 -0
  159. sage/symbolic/expression_conversion_sympy.py +317 -0
  160. sage/symbolic/expression_conversions.py +1727 -0
  161. sage/symbolic/function_factory.py +355 -0
  162. sage/symbolic/function_factory.pyi +41 -0
  163. sage/symbolic/getitem_impl.pyi +24 -0
  164. sage/symbolic/integration/all.py +1 -0
  165. sage/symbolic/integration/external.py +271 -0
  166. sage/symbolic/integration/integral.py +1075 -0
  167. sage/symbolic/maxima_wrapper.py +162 -0
  168. sage/symbolic/operators.py +267 -0
  169. sage/symbolic/operators.pyi +61 -0
  170. sage/symbolic/pynac_constant_impl.pyi +13 -0
  171. sage/symbolic/pynac_function_impl.pyi +8 -0
  172. sage/symbolic/random_tests.py +461 -0
  173. sage/symbolic/relation.py +2062 -0
  174. sage/symbolic/ring.cpython-311-darwin.so +0 -0
  175. sage/symbolic/ring.pxd +5 -0
  176. sage/symbolic/ring.pyi +110 -0
  177. sage/symbolic/ring.pyx +1393 -0
  178. sage/symbolic/series_impl.pyi +10 -0
  179. sage/symbolic/subring.py +1025 -0
  180. sage/symbolic/symengine.py +19 -0
  181. sage/symbolic/tests.py +40 -0
  182. 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