Skip to content

Commit e89efa2

Browse files
committed
api: Extend side API to all derivative operator shortcuts
1 parent 08cfd37 commit e89efa2

File tree

5 files changed

+152
-25
lines changed

5 files changed

+152
-25
lines changed

devito/finite_differences/derivative.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Derivative(sympy.Derivative, Differentiable, Pickable):
3838
Derivative order.
3939
side : Side or tuple of Side, optional, default=centered
4040
Side of the finite difference location, centered (at x), left (at x - 1)
41-
or right (at x +1).
41+
or right (at x + 1).
4242
transpose : Transpose, optional, default=direct
4343
Forward (matvec=direct) or transpose (matvec=transpose) mode of the
4444
finite difference.

devito/finite_differences/differentiable.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -303,12 +303,12 @@ def shift(self, dim, shift):
303303
return self._subs(dim, dim + shift)
304304

305305
@property
306-
def laplace(self):
306+
def laplace(self, **kwargs):
307307
"""
308308
Generates a symbolic expression for the Laplacian, the second
309309
derivative w.r.t all spatial Dimensions.
310310
"""
311-
return self.laplacian()
311+
return self.laplacian(**kwargs)
312312

313313
def laplacian(self, shift=None, order=None, method='FD', **kwargs):
314314
"""
@@ -329,16 +329,20 @@ def laplacian(self, shift=None, order=None, method='FD', **kwargs):
329329
method: str, optional, default='FD'
330330
Discretization method. Options are 'FD' (default) and
331331
'RSFD' (rotated staggered grid finite-difference).
332+
side : Side or tuple of Side, optional, default=centered
333+
Side of the finite difference location, centered (at x), left (at x - 1)
334+
or right (at x + 1).
332335
weights/w: list, tuple, or dict, optional, default=None
333-
Custom weights for the finite differences.
336+
Custom weights for the finite difference coefficients.
334337
"""
338+
side = kwargs.get("side")
335339
w = kwargs.get('weights', kwargs.get('w'))
336340
order = order or self.space_order
337341
space_dims = self.root_dimensions
338342
shift_x0 = make_shift_x0(shift, (len(space_dims),))
339343
derivs = tuple(f'd{d.name}2' for d in space_dims)
340344
return Add(*[getattr(self, d)(x0=shift_x0(shift, space_dims[i], None, i),
341-
method=method, fd_order=order, w=w)
345+
method=method, fd_order=order, side=side, w=w)
342346
for i, d in enumerate(derivs)])
343347

344348
def div(self, shift=None, order=None, method='FD', **kwargs):
@@ -357,15 +361,20 @@ def div(self, shift=None, order=None, method='FD', **kwargs):
357361
method: str, optional, default='FD'
358362
Discretization method. Options are 'FD' (default) and
359363
'RSFD' (rotated staggered grid finite-difference).
364+
side : Side or tuple of Side, optional, default=centered
365+
Side of the finite difference location, centered (at x), left (at x - 1)
366+
or right (at x + 1).
360367
weights/w: list, tuple, or dict, optional, default=None
361368
Custom weights for the finite difference coefficients.
362369
"""
370+
side = kwargs.get("side")
363371
w = kwargs.get('weights', kwargs.get('w'))
364372
space_dims = self.root_dimensions
365373
shift_x0 = make_shift_x0(shift, (len(space_dims),))
366374
order = order or self.space_order
367375
return Add(*[getattr(self, f'd{d.name}')(x0=shift_x0(shift, d, None, i),
368-
fd_order=order, method=method, w=w)
376+
fd_order=order, method=method, side=side,
377+
w=w)
369378
for i, d in enumerate(space_dims)])
370379

371380
def grad(self, shift=None, order=None, method='FD', **kwargs):
@@ -384,16 +393,22 @@ def grad(self, shift=None, order=None, method='FD', **kwargs):
384393
method: str, optional, default='FD'
385394
Discretization method. Options are 'FD' (default) and
386395
'RSFD' (rotated staggered grid finite-difference).
396+
side : Side or tuple of Side, optional, default=centered
397+
Side of the finite difference location, centered (at x), left (at x - 1)
398+
or right (at x + 1).
387399
weights/w: list, tuple, or dict, optional, default=None
388-
Custom weights for the finite
400+
Custom weights for the finite difference coefficients.
389401
"""
390402
from devito.types.tensor import VectorFunction, VectorTimeFunction
391403
space_dims = self.root_dimensions
392404
shift_x0 = make_shift_x0(shift, (len(space_dims),))
393405
order = order or self.space_order
406+
407+
side = kwargs.get("side")
394408
w = kwargs.get('weights', kwargs.get('w'))
395409
comps = [getattr(self, f'd{d.name}')(x0=shift_x0(shift, d, None, i),
396-
fd_order=order, method=method, w=w)
410+
fd_order=order, method=method, side=side,
411+
w=w)
397412
for i, d in enumerate(space_dims)]
398413
vec_func = VectorTimeFunction if self.is_TimeDependent else VectorFunction
399414
return vec_func(name=f'grad_{self.name}', time_order=self.time_order,

devito/finite_differences/operators.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,16 @@ def div(func, shift=None, order=None, method='FD', **kwargs):
1414
method: str, optional, default='FD'
1515
Discretization method. Options are 'FD' (default) and
1616
'RSFD' (rotated staggered grid finite-difference).
17+
side : Side or tuple of Side, optional, default=centered
18+
Side of the finite difference location, centered (at x), left (at x - 1)
19+
or right (at x + 1).
1720
weights/w: list, tuple, or dict, optional, default=None
1821
Custom weights for the finite difference coefficients.
1922
"""
23+
side = kwargs.get("side")
2024
w = kwargs.get('weights', kwargs.get('w'))
2125
try:
22-
return func.div(shift=shift, order=order, method=method, w=w)
26+
return func.div(shift=shift, order=order, method=method, side=side, w=w)
2327
except AttributeError:
2428
return 0
2529

@@ -57,12 +61,16 @@ def grad(func, shift=None, order=None, method='FD', **kwargs):
5761
method: str, optional, default='FD'
5862
Discretization method. Options are 'FD' (default) and
5963
'RSFD' (rotated staggered grid finite-difference).
64+
side : Side or tuple of Side, optional, default=centered
65+
Side of the finite difference location, centered (at x), left (at x - 1)
66+
or right (at x + 1).
6067
weights/w: list, tuple, or dict, optional, default=None
6168
Custom weights for the finite difference coefficients.
6269
"""
70+
side = kwargs.get("side")
6371
w = kwargs.get('weights', kwargs.get('w'))
6472
try:
65-
return func.grad(shift=shift, order=order, method=method, w=w)
73+
return func.grad(shift=shift, order=order, method=method, side=side, w=w)
6674
except AttributeError:
6775
raise AttributeError("Gradient not supported for class %s" % func.__class__)
6876

@@ -100,12 +108,16 @@ def curl(func, shift=None, order=None, method='FD', **kwargs):
100108
method: str, optional, default='FD'
101109
Discretization method. Options are 'FD' (default) and
102110
'RSFD' (rotated staggered grid finite-difference).
111+
side : Side or tuple of Side, optional, default=centered
112+
Side of the finite difference location, centered (at x), left (at x - 1)
113+
or right (at x + 1).
103114
weights/w: list, tuple, or dict, optional, default=None
104115
Custom weights for the finite difference coefficients.
105116
"""
117+
side = kwargs.get("side")
106118
w = kwargs.get('weights', kwargs.get('w'))
107119
try:
108-
return func.curl(shift=shift, order=order, method=method, w=w)
120+
return func.curl(shift=shift, order=order, method=method, side=side, w=w)
109121
except AttributeError:
110122
raise AttributeError("Curl only supported for 3D VectorFunction")
111123

@@ -143,12 +155,16 @@ def laplace(func, shift=None, order=None, method='FD', **kwargs):
143155
Uses `func.space_order` when not specified
144156
method: str, optional, default='FD'
145157
Discretization method. Options are 'FD' (default) and 'RSFD'
158+
side : Side or tuple of Side, optional, default=centered
159+
Side of the finite difference location, centered (at x), left (at x - 1)
160+
or right (at x + 1).
146161
weights/w: list, tuple, or dict, optional, default=None
147162
Custom weights for the finite difference coefficients.
148163
"""
164+
side = kwargs.get("side")
149165
w = kwargs.get('weights', kwargs.get('w'))
150166
try:
151-
return func.laplacian(shift=shift, order=order, method=method, w=w)
167+
return func.laplacian(shift=shift, order=order, method=method, side=side, w=w)
152168
except AttributeError:
153169
return 0
154170

devito/types/tensor.py

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,13 @@ def div(self, shift=None, order=None, method='FD', **kwargs):
234234
method: str, optional, default='FD'
235235
Discretization method. Options are 'FD' (default) and
236236
'RSFD' (rotated staggered grid finite-difference).
237+
side : Side or tuple of Side, optional, default=centered
238+
Side of the finite difference location, centered (at x), left (at x - 1)
239+
or right (at x + 1).
237240
weights/w: list, tuple, or dict, optional, default=None
238241
Custom weights for the finite differences.
239242
"""
243+
side = kwargs.get("side")
240244
w = kwargs.get('weights', kwargs.get('w'))
241245
comps = []
242246
func = vec_func(self)
@@ -247,7 +251,7 @@ def div(self, shift=None, order=None, method='FD', **kwargs):
247251
for i in range(len(self.space_dimensions)):
248252
comps.append(sum([getattr(self[j, i], 'd%s' % d.name)
249253
(x0=shift_x0(shift, d, i, j), fd_order=order,
250-
method=method, w=w)
254+
method=method, side=side, w=w)
251255
for j, d in enumerate(space_dims)]))
252256
return func._new(comps)
253257

@@ -277,9 +281,13 @@ def laplacian(self, shift=None, order=None, method='FD', **kwargs):
277281
method: str, optional, default='FD'
278282
Discretization method. Options are 'FD' (default) and
279283
'RSFD' (rotated staggered grid finite-difference).
284+
side : Side or tuple of Side, optional, default=centered
285+
Side of the finite difference location, centered (at x), left (at x - 1)
286+
or right (at x + 1).
280287
weights/w: list, tuple, or dict, optional, default=None
281288
Custom weights for the finite
282289
"""
290+
side = kwargs.get("side")
283291
w = kwargs.get('weights', kwargs.get('w'))
284292
comps = []
285293
func = vec_func(self)
@@ -290,7 +298,7 @@ def laplacian(self, shift=None, order=None, method='FD', **kwargs):
290298
for j in range(ndim):
291299
comps.append(sum([getattr(self[j, i], 'd%s2' % d.name)
292300
(x0=shift_x0(shift, d, j, i), fd_order=order,
293-
method=method, w=w)
301+
method=method, side=side, w=w)
294302
for i, d in enumerate(space_dims)]))
295303
return func._new(comps)
296304

@@ -372,15 +380,20 @@ def div(self, shift=None, order=None, method='FD', **kwargs):
372380
method: str, optional, default='FD'
373381
Discretization method. Options are 'FD' (default) and
374382
'RSFD' (rotated staggered grid finite-difference).
383+
side : Side or tuple of Side, optional, default=centered
384+
Side of the finite difference location, centered (at x), left (at x - 1)
385+
or right (at x + 1).
375386
weights/w: list, tuple, or dict, optional, default=None
376387
Custom weights for the finite difference coefficients.
377388
"""
389+
side = kwargs.get("side")
378390
w = kwargs.get('weights', kwargs.get('w'))
379391
shift_x0 = make_shift_x0(shift, (len(self.space_dimensions),))
380392
order = order or self.space_order
381393
space_dims = self.root_dimensions
382394
return sum([getattr(self[i], 'd%s' % d.name)(x0=shift_x0(shift, d, None, i),
383-
fd_order=order, method=method, w=w)
395+
fd_order=order, method=method,
396+
side=side, w=w)
384397
for i, d in enumerate(space_dims)])
385398

386399
@property
@@ -404,16 +417,21 @@ def laplacian(self, shift=None, order=None, method='FD', **kwargs):
404417
method: str, optional, default='FD'
405418
Discretization method. Options are 'FD' (default) and
406419
'RSFD' (rotated staggered grid finite-difference).
420+
side : Side or tuple of Side, optional, default=centered
421+
Side of the finite difference location, centered (at x), left (at x - 1)
422+
or right (at x + 1).
407423
weights/w: list, tuple, or dict, optional, default=None
408424
Custom weights for the finite
409425
"""
426+
side = kwargs.get("side")
410427
w = kwargs.get('weights', kwargs.get('w'))
411428
func = vec_func(self)
412429
shift_x0 = make_shift_x0(shift, (len(self.space_dimensions),))
413430
order = order or self.space_order
414431
space_dims = self.root_dimensions
415432
comps = [sum([getattr(s, 'd%s2' % d.name)(x0=shift_x0(shift, d, None, i),
416-
fd_order=order, w=w, method=method)
433+
fd_order=order, method=method,
434+
side=side, w=w)
417435
for i, d in enumerate(space_dims)])
418436
for s in self]
419437
return func._new(comps)
@@ -432,29 +450,39 @@ def curl(self, shift=None, order=None, method='FD', **kwargs):
432450
method: str, optional, default='FD'
433451
Discretization method. Options are 'FD' (default) and
434452
'RSFD' (rotated staggered grid finite-difference).
453+
side : Side or tuple of Side, optional, default=centered
454+
Side of the finite difference location, centered (at x), left (at x - 1)
455+
or right (at x + 1).
435456
weights/w: list, tuple, or dict, optional, default=None
436457
Custom weights for the finite difference coefficients.
437458
"""
438459
if len(self.space_dimensions) != 3:
439460
raise AttributeError("Curl only supported for 3D VectorFunction")
440461
# The curl of a VectorFunction is a VectorFunction
462+
side = kwargs.get("side")
441463
w = kwargs.get('weights', kwargs.get('w'))
442464
dims = self.root_dimensions
443465
derivs = ['d%s' % d.name for d in dims]
444466
shift_x0 = make_shift_x0(shift, (len(dims), len(dims)))
445467
order = order or self.space_order
446468
comp1 = (getattr(self[2], derivs[1])(x0=shift_x0(shift, dims[1], 2, 1),
447-
fd_order=order, method=method, w=w) -
469+
fd_order=order, method=method,
470+
side=side, w=w) -
448471
getattr(self[1], derivs[2])(x0=shift_x0(shift, dims[2], 1, 2),
449-
fd_order=order, method=method, w=w))
472+
fd_order=order, method=method,
473+
side=side, w=w))
450474
comp2 = (getattr(self[0], derivs[2])(x0=shift_x0(shift, dims[2], 0, 2),
451-
fd_order=order, method=method, w=w) -
475+
fd_order=order, method=method,
476+
side=side, w=w) -
452477
getattr(self[2], derivs[0])(x0=shift_x0(shift, dims[0], 2, 0),
453-
fd_order=order, method=method, w=w))
478+
fd_order=order, method=method,
479+
side=side, w=w))
454480
comp3 = (getattr(self[1], derivs[0])(x0=shift_x0(shift, dims[0], 1, 0),
455-
fd_order=order, method=method, w=w) -
481+
fd_order=order, method=method,
482+
side=side, w=w) -
456483
getattr(self[0], derivs[1])(x0=shift_x0(shift, dims[1], 0, 1),
457-
fd_order=order, method=method, w=w))
484+
fd_order=order, method=method,
485+
side=side, w=w))
458486
func = vec_func(self)
459487
return func._new(3, 1, [comp1, comp2, comp3])
460488

@@ -472,17 +500,22 @@ def grad(self, shift=None, order=None, method='FD', **kwargs):
472500
method: str, optional, default='FD'
473501
Discretization method. Options are 'FD' (default) and
474502
'RSFD' (rotated staggered grid finite-difference).
503+
side : Side or tuple of Side, optional, default=centered
504+
Side of the finite difference location, centered (at x), left (at x - 1)
505+
or right (at x + 1).
475506
weights/w: list, tuple, or dict, optional, default=None
476507
Custom weights for the finite difference coefficients.
477508
"""
509+
side = kwargs.get("side")
478510
w = kwargs.get('weights', kwargs.get('w'))
479511
func = tens_func(self)
480512
ndim = len(self.space_dimensions)
481513
shift_x0 = make_shift_x0(shift, (ndim, ndim))
482514
order = order or self.space_order
483515
space_dims = self.root_dimensions
484-
comps = [[getattr(f, 'd%s' % d.name)(x0=shift_x0(shift, d, i, j), w=w,
485-
fd_order=order, method=method)
516+
comps = [[getattr(f, 'd%s' % d.name)(x0=shift_x0(shift, d, i, j),
517+
fd_order=order, method=method,
518+
side=side, w=w)
486519
for j, d in enumerate(space_dims)]
487520
for i, f in enumerate(self)]
488521
return func._new(comps)

0 commit comments

Comments
 (0)