You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/src/tutorials/perturbation.md
+48-35Lines changed: 48 additions & 35 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -47,52 +47,55 @@ quintic = x^5 + ϵ*x ~ 1
47
47
```
48
48
If $ϵ = 1$, we get our original problem. With $ϵ = 0$, the problem transforms to the easy quintic equation $x^5 = 1$ with the trivial real solution $x = 1$ (and four complex solutions which we ignore). Next, expand $x$ as a power series in $ϵ$:
49
49
```@example perturb
50
-
x_taylor = series(x, ϵ, 0:3) # expand x to third order
50
+
x_taylor = series(x, ϵ, 0:7) # expand x in a power series in ϵ
51
+
x_coeffs = taylor_coeff(x_taylor, ϵ) # TODO: get coefficients at series creation
52
+
x_taylor
51
53
```
52
54
Then insert this into the quintic equation and expand it, too, to the same order:
53
55
```@example perturb
54
56
quintic_taylor = substitute(quintic, x => x_taylor)
55
-
quintic_taylor = taylor(quintic_taylor, ϵ, 0:3)
57
+
quintic_taylor = taylor(quintic_taylor, ϵ, 0:7)
56
58
```
57
-
This equation must hold for each power of $ϵ$, so we can separate it into one equation per order:
59
+
This messy equation must hold for each power of $ϵ$, so we can separate it into one nicer equation per order:
58
60
```@example perturb
59
61
quintic_eqs = taylor_coeff(quintic_taylor, ϵ)
62
+
quintic_eqs[1:5] # for readability, show only 5 shortest equations
60
63
```
61
64
These equations show three important features of perturbation theory:
62
65
1. The $0$-th order equation is *trivial* in $x_0$: here $x_0^5 = 1$ has the trivial real solution $x_0 = 1$.
63
66
2. The $n$-th order equation is *linear* in $x_n$ (except the trivial $0$-th order equation).
64
67
3. The equations are *triangular* in $x_n$: the $n$-th order equation can be solved for $x_n$ given only $x_m$ for $m<n$.
65
-
This structure is what makes the perturbation theory so attractive: we can start with the trivial solution $x_0 = 1$, then linearly solve for $x_n$ order-by-order and substitute in the solutions of $x_m$ for $m<n$ obtained so far. Let us write a function that solves a general equation `eq` for the variable `x` perturbatively with this *cascading* process:
68
+
This structure is what makes the perturbation theory so attractive: we can start with the trivial solution $x_0 = 1$, then linearly solve for $x_n$ order-by-order and substitute in the solutions of $x_m$ for $m<n$ obtained so far.
69
+
70
+
Here is a simple function that uses this *cascading* strategy to solve such a set of equations `eqs` for the variables `xs`, given a solution `x₀` of the first equation `eqs[begin]`:
66
71
```@example perturb
67
-
function solve_perturbed(eq, x, x₀, ϵ, order)
68
-
x_taylor = series(x, ϵ, 0:order) # expand unknown in a taylor series
69
-
x_coeffs = taylor_coeff(x_taylor, ϵ, 0:order) # array of coefficients
70
-
eq_taylor = substitute(eq, x => x_taylor) # expand equation in taylor series
71
-
eqs = taylor_coeff(eq_taylor, ϵ, 0:order) # separate into order-by-order equations
72
-
sol = Dict(x_coeffs[1] => x₀) # store solutions in a symbolic-numeric map
72
+
function solve_cascade(eqs, xs, x₀, ϵ)
73
+
sol = Dict(xs[begin] => x₀) # store solutions in a map
73
74
74
-
# verify that x₀ is a solution of the 0-th order equation
75
+
# verify that x₀ is a solution of the first equation
75
76
eq0 = substitute(eqs[1], sol)
76
-
if !isequal(eq0.lhs, eq0.rhs)
77
-
error("$sol is not a 0-th order solution of $(eqs[1])")
78
-
end
77
+
isequal(eq0.lhs, eq0.rhs) || error("$sol does not solve $(eqs[1])")
println("$n-th order solution: x = $x_pert_sol = $(x_pert_sol * 1.0)")
96
99
end
97
100
```
98
101
This is close to the solution from Newton's method!
@@ -112,30 +115,40 @@ E_newton = solve_newton(substitute(kepler, vals_earth), E, π/2)
112
115
println("Newton's method solution: E = ", E_newton)
113
116
```
114
117
115
-
Next, let us solve the same problem with our perturbative solver. It is most common to expand Kepler's equation in $M$ (the trivial solution when $M=0$ is $E=0$):
118
+
Next, let us solve the same problem with the perturbative method. It is most common to expand $E$ as a series in $M$. Repeating the procedure from the quintic example, we get these equations:
116
119
```@example perturb
117
-
E_pert = solve_perturbed(kepler, E, 0, M, 5)
120
+
E_taylor = series(E, M, 0:5)
121
+
E_coeffs = taylor_coeff(E_taylor, M) # TODO: get coefficients at series creation
122
+
kepler_eqs = taylor_coeff(substitute(kepler, E => E_taylor), M, 0:5)
123
+
kepler_eqs[1:4] # for readability
118
124
```
119
-
Numerically, this gives almost the same answer as Newton's method:
125
+
The trivial $0$-th order solution (when $M=0$) is $E_0=0$. This gives this full perturbative solution:
126
+
```@example perturb
127
+
E_coeffs_sol = solve_cascade(kepler_eqs, E_coeffs, 0, M)
128
+
E_pert = substitute(E_taylor, E_coeffs_sol)
129
+
```
130
+
131
+
Numerically, the result again converges to that from Newton's method:
120
132
```@example perturb
121
133
for n in 0:5
122
134
println("$n-th order solution: E = ", substitute(taylor(E_pert, M, 0:n), vals_earth))
123
135
end
124
136
```
125
-
But unlike Newtons method, perturbation theory also gives us the power to work with the full*symbolic* series solution for $E$ (*before* numbers for $e$ and $M$ are inserted). Our series matches [this result from Wikipedia](https://en.wikipedia.org/wiki/Kepler%27s_equation#Inverse_Kepler_equation):
137
+
But unlike Newtons method, this example shows how perturbation theory also gives us the powerful*symbolic* series solution for $E$ (*before* numbers for $e$ and $M$ are inserted). Our series matches [this result from Wikipedia](https://en.wikipedia.org/wiki/Kepler%27s_equation#Inverse_Kepler_equation):
Alternatively, we can expand Kepler's equation in $e$ instead of $M$ (the trivial solution when $e = 0$ is $E=M$):
131
-
```@example perturb
132
-
E_pert′ = solve_perturbed(kepler, E, M, e, 5)
133
-
```
134
-
We can expand the trigonometric functions in $M$:
142
+
Alternatively, we can expand $E$ in $e$ instead of $M$, giving the solution (the trivial solution when $e = 0$ is $E_0=M$):
135
143
```@example perturb
136
-
E_pert′ = taylor(E_pert′, M, 0:5)
144
+
E_taylor′ = series(E, e, 0:5)
145
+
E_coeffs′ = taylor_coeff(E_taylor′, e) # TODO: get at creation
146
+
kepler_eqs′ = taylor_coeff(substitute(kepler, E => E_taylor′), e, 0:5)
147
+
E_coeffs_sol′ = solve_cascade(kepler_eqs′, E_coeffs′, M, e)
148
+
E_pert′ = substitute(E_taylor′, E_coeffs_sol′)
137
149
```
138
-
Up to order $e^5 M^5$, we see that this two-variable $(e,M)$-series also matches the result from Wikipedia:
150
+
This looks very different from our first series `E_pert`. If they are the same, we should get $0$ if we subtract and expand both as multivariate Taylor series in $(e,M)$. Indeed:
139
151
```@example perturb
140
-
E_wiki′ = taylor(taylor(E_wiki, e, 0:5), M, 0:5)
152
+
@assert taylor(taylor(E_pert′ - E_pert, e, 0:4), M, 0:4) == 0 # use this as a test # hide
0 commit comments