Skip to content

Commit cb19052

Browse files
committed
api: prevent sympy warnings with diag
1 parent a9e358e commit cb19052

File tree

8 files changed

+62
-42
lines changed

8 files changed

+62
-42
lines changed

devito/finite_differences/elementary.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from packaging.version import Version
33

44
from devito.finite_differences.differentiable import DifferentiableFunction, diffify
5-
from devito.types.lazy import Evaluable
65

76

87
class factorial(DifferentiableFunction, sympy.factorial):
@@ -89,13 +88,13 @@ def root(x):
8988
return diffify(sympy.root(x))
9089

9190

92-
class Min(sympy.Min, Evaluable):
91+
class Min(sympy.Min, DifferentiableFunction):
9392

9493
def _evaluate(self, **kwargs):
9594
return self.func(*self._evaluate_args(**kwargs), evaluate=False)
9695

9796

98-
class Max(sympy.Max, Evaluable):
97+
class Max(sympy.Max, DifferentiableFunction):
9998

10099
def _evaluate(self, **kwargs):
101100
return self.func(*self._evaluate_args(**kwargs), evaluate=False)

devito/finite_differences/operators.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from sympy import S
2+
3+
14
def div(func, shift=None, order=None, method='FD', side=None, **kwargs):
25
"""
36
Divergence of the input Function.
@@ -194,6 +197,6 @@ def diag(func, size=None):
194197
to = getattr(func, 'time_order', 0)
195198

196199
tens_func = TensorTimeFunction if func.is_TimeDependent else TensorFunction
197-
comps = [[func if i == j else 0 for i in range(dim)] for j in range(dim)]
200+
comps = [[func if i == j else S.Zero for i in range(dim)] for j in range(dim)]
198201
return tens_func(name='diag', grid=func.grid, space_order=func.space_order,
199202
components=comps, time_order=to, diagonal=True)

devito/ir/equations/algorithms.py

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -298,9 +298,10 @@ def _(d, mapper, rebuilt, sregistry):
298298
tkns = tuple(tkn._rebuild(name=sregistry.make_name(prefix=tkn.name))
299299
for tkn in d.thickness)
300300
kwargs = {'thickness': tkns}
301-
fkwargs = {}
301+
fkwargs = {'function': None, 'halo': None, 'padding': None}
302302

303303
idim0 = d.implicit_dimension
304+
idim1 = None
304305
if idim0 is not None:
305306
if idim0 in rebuilt:
306307
idim1 = rebuilt[idim0]
@@ -309,34 +310,34 @@ def _(d, mapper, rebuilt, sregistry):
309310
rebuilt[idim0] = idim1 = idim0._rebuild(name=iname)
310311

311312
kwargs['implicit_dimension'] = idim1
312-
fkwargs['dimensions'] = (idim1,) + d.functions.dimensions[1:]
313313

314-
if d.functions in rebuilt:
315-
functions = rebuilt[d.functions]
316-
else:
317-
# Increment every instance of this name after the first encountered
318-
fname = sregistry.make_name(prefix=d.functions.name, increment_first=False)
319-
# Warn the user if name has been changed, since this will affect overrides
320-
if fname != d.functions.name:
321-
fkwargs['name'] = fname
322-
warning(
323-
f"{str(d.functions)} <{id(d.functions)}> renamed as '{fname}'. "
324-
"Consider assigning a unique name to {d.functions.name}."
325-
)
326-
327-
fkwargs.update({'function': None,
328-
'halo': None,
329-
'padding': None})
330-
331-
# Data in MultiSubDimension function may not have been touched at this point,
332-
# in which case do not use an allocator, as there is nothing to allocate, and
333-
# doing so will petrify the `_data` attribute as None.
334-
if d.functions._data is not None:
335-
fkwargs.update({'allocator': DataReference(d.functions._data)})
336-
337-
rebuilt[d.functions] = functions = d.functions._rebuild(**fkwargs)
338-
339-
kwargs['functions'] = functions
314+
functions = []
315+
for f in as_tuple(d.functions):
316+
if f in rebuilt:
317+
functions.append(rebuilt[f])
318+
else:
319+
# Increment every instance of this name after the first encountered
320+
fname = sregistry.make_name(prefix=f.name, increment_first=False)
321+
# Warn the user if name has been changed, since this will affect overrides
322+
if fname != f.name:
323+
fkwargs['name'] = fname
324+
warning(
325+
f"{str(f)} <{id(f)}> renamed as '{fname}'. "
326+
f"Consider assigning a unique name to {f.name}."
327+
)
328+
329+
if idim1 is not None:
330+
fkwargs['dimensions'] = (idim1,) + f.dimensions[1:]
331+
# Data in MultiSubDimension function may not have been touched at this point,
332+
# in which case do not use an allocator, as there is nothing to allocate, and
333+
# doing so will petrify the `_data` attribute as None.
334+
if f._data is not None:
335+
fkwargs.update({'allocator': DataReference(f._data)})
336+
337+
rebuilt[f] = f._rebuild(**fkwargs)
338+
functions.append(rebuilt[f])
339+
340+
kwargs['functions'] = tuple(functions)
340341

341342
mapper[d] = d._rebuild(**kwargs)
342343
mapper.update(zip(d.thickness, tkns, strict=True))

devito/passes/clusters/blocking.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,17 @@ def _has_enough_large_blockable_dims(self, cluster, d, nested=False):
178178
if (cluster.properties.is_parallel_relaxed(i) and
179179
not self._has_short_trip_count(i))]) >= 3
180180

181+
def _is_non_uniform(self, prefix, d):
182+
# A non-uniform Dimension is one that is not guaranteed to have the same
183+
# bounds and cannot be blocked
184+
if not d.is_MultiSub:
185+
# MultiSubdimensions are the only ones that can have variable bounds
186+
return False
187+
188+
# Check if the bound of the MultiSubdimension is variable for d
189+
p_dims = set().union(*[d.dim._defines for d in prefix if not d.dim.is_Time])
190+
return any(p_dims & set(f.dimensions) for f in d.functions)
191+
181192
def callback(self, clusters, prefix):
182193
if not prefix:
183194
return clusters
@@ -190,6 +201,8 @@ def callback(self, clusters, prefix):
190201
return clusters
191202

192203
if is_on_device(c.functions, self.gpu_fit):
204+
if self._is_non_uniform(prefix[:-1], d):
205+
return clusters
193206
if self._has_short_trip_count(d):
194207
if self._has_atomic_blockable_dim(c, d):
195208
# Optimization: minimize number of parallel reductions

devito/passes/clusters/implicit.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,14 @@ def key(tkn):
183183
if not mapper:
184184
continue
185185

186-
found[d.functions].clusters.append(c)
187-
found[d.functions].mapper = reduce(found[d.functions].mapper,
188-
mapper, {dim}, prefix)
186+
for df in d.functions:
187+
found[df].clusters.append(c)
188+
found[df].mapper = reduce(found[df].mapper,
189+
mapper, {dim}, prefix)
189190

190191
# Turn the reduced mapper into a list of equations
191192
processed = []
193+
192194
for bunch in found.values():
193195
exprs = make_implicit_exprs(bunch.mapper)
194196

@@ -226,7 +228,8 @@ def _lower_msd(dim, cluster):
226228
def _(dim, cluster):
227229
i_dim = dim.implicit_dimension
228230
mapper = {
229-
tkn: dim.functions[i_dim, mM]
231+
tkn: f[i_dim, mM]
232+
for f in dim.functions
230233
for tkn, mM in zip(dim.tkns, dim.bounds_indices, strict=True)
231234
}
232235
return mapper, i_dim

devito/types/dimension.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from devito.deprecations import deprecations
1212
from devito.exceptions import InvalidArgument
1313
from devito.logger import debug
14-
from devito.tools import Pickable, is_integer, is_number, memoized_meth
14+
from devito.tools import Pickable, as_tuple, is_integer, is_number, memoized_meth
1515
from devito.types.args import ArgProvider
1616
from devito.types.basic import DataSymbol, Scalar, Symbol
1717
from devito.types.constant import Constant
@@ -823,7 +823,7 @@ def __init_finalize__(self, name, parent, thickness, functions=None,
823823
bounds_indices=None, implicit_dimension=None):
824824

825825
super().__init_finalize__(name, parent, thickness)
826-
self.functions = functions
826+
self.functions = as_tuple(functions)
827827
self.bounds_indices = bounds_indices
828828
self.implicit_dimension = implicit_dimension
829829

devito/types/grid.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ class CartesianDiscretization:
3939

4040
def __init__(self, shape=None, dimensions=None, dtype=None):
4141
self._shape = as_tuple(shape)
42-
self._dimensions = as_tuple(dimensions)
42+
dimensions = as_tuple(dimensions)
43+
self._dimensions = DimensionTuple(*dimensions, getters=dimensions)
4344
self._dtype = dtype
4445

4546
@property
@@ -653,7 +654,7 @@ def __subdomain_finalize_legacy__(self, grid):
653654
sdshape.append(thickness)
654655

655656
self._shape = tuple(sdshape)
656-
self._dimensions = tuple(sub_dimensions)
657+
self._dimensions = DimensionTuple(*sub_dimensions, getters=grid.dimensions)
657658
self._dtype = grid.dtype
658659

659660
@property
@@ -914,7 +915,7 @@ def __subdomain_finalize_core__(self, grid):
914915
bounds_indices=(2*i, 2*i+1), implicit_dimension=i_dim
915916
))
916917

917-
self._dimensions = tuple(dimensions)
918+
self._dimensions = DimensionTuple(*dimensions, getters=grid.dimensions)
918919
self._subfunction = sd_func
919920

920921
def __subdomain_finalize__(self):

tests/test_subdomains.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ class Dummy(SubDomainSet):
693693
# Check that the correct number of thickness expressions are generated
694694
sdsexprs = [i.expr for i in FindNodes(Expression).visit(op)
695695
if i.expr.rhs.is_Indexed
696-
and i.expr.rhs.function is xi.functions]
696+
and i.expr.rhs.function in xi.functions]
697697
# The thickness expressions Eq(x_ltkn0, dummy[n0][0]), ...
698698
# should be scheduled once per dimension
699699
assert len(sdsexprs) == 6

0 commit comments

Comments
 (0)