Skip to content

Commit fb93224

Browse files
committed
Improve recurrence module documentation with LaTeX equations and clearer notation
1 parent a423046 commit fb93224

1 file changed

Lines changed: 62 additions & 25 deletions

File tree

sumpy/recurrence.py

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,13 @@
2727
Computing derivatives
2828
^^^^^^^^^^^^^^^^^^^^^
2929
30-
Given a PDE and its Green's function, we want to compute the :math:`n`-th
31-
derivative :math:`\partial^n G / \partial x_1^n` at a point
32-
:math:`(x_1, x_2, \dots)`. Here :math:`x_1` is the first coordinate
33-
(called ``x0`` in the 0-indexed code variables).
30+
Given a PDE and its Green's function
31+
:math:`G(\boldsymbol x, \boldsymbol t)` where
32+
:math:`\boldsymbol x = (x_1, x_2, \dots)`, we want to compute the
33+
:math:`n`-th derivative :math:`\partial^n G / \partial x_1^n` with
34+
respect to the first coordinate :math:`x_1` of :math:`\boldsymbol x`
35+
(called ``x0`` in the 0-indexed code variables), with
36+
:math:`\boldsymbol t` fixed.
3437
3538
There are two regimes, selected based on the relative magnitude of
3639
:math:`|x_1|`:
@@ -77,8 +80,27 @@
7780
Example: large-:math:`|x_1|` recurrence
7881
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7982
83+
We compute
84+
85+
.. math::
86+
87+
s(n) = \frac{\partial^n}{\partial x_1^n}
88+
G(\boldsymbol x, \boldsymbol t)\Big|_{\boldsymbol t=0},
89+
\qquad n = 0, 1, \dots, p
90+
91+
for the 2D Laplace Green's function
92+
93+
.. math::
94+
95+
G(\boldsymbol x, \boldsymbol t)
96+
= -\frac{1}{2\pi}\log|\boldsymbol x - \boldsymbol t|
97+
98+
evaluated at the point :math:`\boldsymbol x = (0.5, 0.3)` with
99+
the target fixed at the origin :math:`\boldsymbol t = 0`.
100+
80101
.. code-block:: python
81102
103+
import numpy as np
82104
import sympy as sp
83105
from sumpy.expansion.diff_op import laplacian, make_identity_diff_op
84106
from sumpy.recurrence import get_large_x1_recurrence, _make_sympy_vec
@@ -89,31 +111,29 @@
89111
90112
# 2. Get recurrence
91113
n_initial, order, recurrence = get_large_x1_recurrence(pde)
92-
# n_initial: number of initial derivatives to seed directly
93-
# order: recurrence order (how many prior values s(n) depends on)
94-
# recurrence: sympy expression giving s(n) in terms of s(n-1), ...
95114
96-
# 3. Compute derivatives at point (x0, x1) = (0.5, 0.3)
115+
# 3. Define G(x, t) and the evaluation point
116+
var = _make_sympy_vec("x", 2) # source coordinates
117+
var_t = _make_sympy_vec("t", 2) # target coordinates
118+
g = (-1/(2*np.pi)) * sp.log(sp.sqrt((var[0]-var_t[0])**2
119+
+ (var[1]-var_t[1])**2))
120+
97121
n = sp.symbols("n")
98122
s = sp.Function("s")
99-
var = _make_sympy_vec("x", 2)
123+
# Evaluate at source x = (0.5, 0.3), target t = 0
100124
x_vals = [(var[0], sp.Rational(1, 2)), (var[1], sp.Rational(3, 10))]
101125
102-
# Seed initial conditions by direct differentiation of G
103-
import numpy as np
104-
var_t = _make_sympy_vec("t", 2)
105-
g = (-1/(2*np.pi)) * sp.log(sp.sqrt((var[0]-var_t[0])**2
106-
+ (var[1]-var_t[1])**2))
126+
# 4. Seed initial derivatives by direct differentiation of G(x, 0)
107127
derivs = {}
108128
for i in range(-order, 0):
109129
derivs[i] = 0j
110130
for i in range(n_initial):
111131
d = sp.diff(g, var[0], i)
112132
for j in range(2):
113-
d = d.subs(var_t[j], 0)
133+
d = d.subs(var_t[j], 0) # fix target at origin
114134
derivs[i] = complex(d.subs(x_vals))
115135
116-
# Apply recurrence up to order p
136+
# 5. Apply recurrence to get derivatives up to order p
117137
p = 8
118138
for i in range(n_initial, p + 1):
119139
expr = recurrence.subs(n, i)
@@ -124,6 +144,28 @@
124144
Example: small-:math:`|x_1|` expansion
125145
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
126146
147+
Continuing from the same setup above, we now compute the same derivatives
148+
via the small-:math:`|x_1|` path. The small-:math:`|x_1|` recurrence
149+
first computes the Taylor coefficients
150+
151+
.. math::
152+
153+
c(n) = \frac{\partial^n}{\partial x_1^n}
154+
G(\boldsymbol x, \boldsymbol t)\Big|_{\boldsymbol t=0,\; x_1=0}
155+
156+
i.e. the derivatives evaluated at the point :math:`(0, 0.3)`.
157+
The expansion then recovers the derivative at the full point
158+
:math:`\boldsymbol x = (0.5, 0.3)` via a truncated Taylor series
159+
in :math:`x_1`:
160+
161+
.. math::
162+
163+
s(n) = \frac{\partial^n}{\partial x_1^n}
164+
G(\boldsymbol x, \boldsymbol t)\Big|_{\boldsymbol t=0}
165+
\approx \sum_{k=0}^{K} \frac{c(n+k)}{k!}\, x_1^k
166+
167+
where :math:`K` is the user-chosen truncation order.
168+
127169
.. code-block:: python
128170
129171
from sumpy.recurrence import get_small_x1_recurrence, get_small_x1_expansion
@@ -135,28 +177,23 @@
135177
taylor_order = 8
136178
expansion, n_coeffs, start_order = get_small_x1_expansion(
137179
pde, taylor_order)
138-
# expansion: sympy expression in s(n), s(n-1), ..., and x0
139-
# n_coeffs: number of prior recurrence values needed
140-
# start_order: minimum n at which the expansion is valid
141180
142-
# 3. Compute Taylor coefficients via the small-|x_1| recurrence
143-
# (these are derivatives evaluated at x_1=0)
181+
# 3. Compute Taylor coefficients: derivatives of G(x, 0) at x_1=0
144182
coeffs = {}
145183
for i in range(-recur_order, 0):
146184
coeffs[i] = 0j
147185
for i in range(start_order):
148-
# Seed by direct differentiation of G at x0=0
149186
d = sp.diff(g, var[0], i)
150187
for j in range(2):
151-
d = d.subs(var_t[j], 0)
152-
coeffs[i] = complex(d.subs(var[0], 0).subs(x_vals))
188+
d = d.subs(var_t[j], 0) # fix target at origin
189+
coeffs[i] = complex(d.subs(var[0], 0).subs(x_vals)) # then set x_1=0
153190
for i in range(start_order, p + 1):
154191
expr = recur.subs(n, i)
155192
for j in range(recur_order, 0, -1):
156193
expr = expr.subs(s(i - j), coeffs[i - j])
157194
coeffs[i] = complex(expr.subs(x_vals))
158195
159-
# 4. Evaluate the expansion at a point with small x_1
196+
# 4. Evaluate the expansion at x = (0.5, 0.3)
160197
for i in range(start_order, p + 1):
161198
expr = expansion.subs(n, i)
162199
for j in range(n_coeffs, -1, -1):

0 commit comments

Comments
 (0)