Skip to content

Commit c8e5415

Browse files
authored
Merge pull request #2185 from devitocodes/custom-fd-v3
api: fix symbolic coeffs for cross derivatives
2 parents ca2960d + 36b6b21 commit c8e5415

5 files changed

Lines changed: 74 additions & 57 deletions

File tree

‎devito/finite_differences/coefficients.py‎

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import sympy
21
import numpy as np
32
from cached_property import cached_property
43

54
from devito.finite_differences import generate_indices
5+
from devito.finite_differences.tools import numeric_weights, symbolic_weights
66
from devito.tools import filter_ordered, as_tuple
77

88
__all__ = ['Coefficient', 'Substitutions', 'default_rules']
@@ -245,15 +245,25 @@ def generate_subs(deriv_order, function, index):
245245
subs = {}
246246

247247
mapper = {dim: index}
248+
# Get full range of indices and weights
249+
indices, x0 = generate_indices(function, dim,
250+
fd_order, side=None, x0=mapper)
251+
sweights = symbolic_weights(function, deriv_order, indices, x0)
252+
253+
# Actual FD used indices and weights
254+
if deriv_order == 1 and fd_order == 2:
255+
fd_order = 1
248256

249257
indices, x0 = generate_indices(function, dim,
250258
fd_order, side=None, x0=mapper)
251259

252-
coeffs = sympy.finite_diff_weights(deriv_order, indices, x0)[-1][-1]
260+
coeffs = numeric_weights(deriv_order, indices, x0)
261+
262+
for (c, i) in zip(coeffs, indices):
263+
subs.update({function._coeff_symbol(i, deriv_order, function, index): c})
253264

254-
for j in range(len(coeffs)):
255-
subs.update({function._coeff_symbol
256-
(indices[j], deriv_order, function, index): coeffs[j]})
265+
# Set all unused weights to zero
266+
subs.update({w: 0 for w in sweights if w not in subs})
257267

258268
return subs
259269

‎devito/finite_differences/differentiable.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,9 @@ def _new_rawargs(self, *args, **kwargs):
728728
kwargs.pop('is_commutative', None)
729729
return self.func(*args, **kwargs)
730730

731+
def _coeff_symbol(self, *args, **kwargs):
732+
return self.base._coeff_symbol(*args, **kwargs)
733+
731734

732735
class diffify(object):
733736

‎devito/finite_differences/tools.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def check_symbolic(func):
6060
def wrapper(expr, *args, **kwargs):
6161
if expr._uses_symbolic_coefficients:
6262
expr_dict = expr.as_coefficients_dict()
63-
if any(len(expr_dict) > 1 for item in expr_dict):
63+
if any(v > 1 for k, v in expr_dict.items()):
6464
raise NotImplementedError("Applying the chain rule to functions "
6565
"with symbolic coefficients is not currently "
6666
"supported")
@@ -337,6 +337,7 @@ def generate_indices_staggered(expr, dim, order, side=None, x0=None):
337337
ind0 = expr.indices_ref[dim]
338338
except AttributeError:
339339
ind0 = start
340+
340341
if start != ind0:
341342
if order < 2:
342343
indices = [start - diff/2, start + diff/2]

‎examples/seismic/tutorials/07_DRP_schemes.ipynb‎

Lines changed: 37 additions & 49 deletions
Large diffs are not rendered by default.

‎tests/test_symbolic_coefficients.py‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,12 @@ def test_default_rules(self, order, stagger):
3232
staggered=staggered)
3333
u1 = TimeFunction(name='u', grid=grid, time_order=order, space_order=order,
3434
staggered=staggered, coefficients='symbolic')
35-
eq0 = Eq(-u0.dx+u0.dt)
35+
36+
eq0 = Eq(u0.dt-u0.dx)
3637
eq1 = Eq(u1.dt-u1.dx)
37-
assert(eq0.evalf(_PRECISION).__repr__() == eq1.evalf(_PRECISION).__repr__())
38+
39+
assert(eq0.evaluate.evalf(_PRECISION).__repr__() ==
40+
eq1.evaluate.evalf(_PRECISION).__repr__())
3841

3942
@pytest.mark.parametrize('expr, sorder, dorder, dim, weights, expected', [
4043
('u.dx', 2, 1, 0, (-0.6, 0.1, 0.6),
@@ -374,3 +377,15 @@ def test_aggregate_w_custom_coeffs(self):
374377
assert aggregated.args[1] == q.dx2
375378

376379
Operator([Eq(q.forward, expr)])(time_M=2) # noqa
380+
381+
def test_cross_derivs(self):
382+
grid = Grid(shape=(11, 11, 11))
383+
q = TimeFunction(name='q', grid=grid, space_order=8, time_order=2,
384+
coefficients='symbolic')
385+
q0 = TimeFunction(name='q', grid=grid, space_order=8, time_order=2)
386+
387+
eq0 = Eq(q0.forward, q0.dx.dy)
388+
eq1 = Eq(q.forward, q.dx.dy)
389+
390+
assert(eq0.evaluate.evalf(_PRECISION).__repr__() ==
391+
eq1.evaluate.evalf(_PRECISION).__repr__())

0 commit comments

Comments
 (0)