diff --git a/arraycontext/fake_numpy.py b/arraycontext/fake_numpy.py index 0ca72bd93710364b577c455d6a0de6d14f8ac33e..a117fafff0d015d937e50459407909e8246671bb 100644 --- a/arraycontext/fake_numpy.py +++ b/arraycontext/fake_numpy.py @@ -182,6 +182,31 @@ class BaseFakeNumpyLinalgNamespace: if ord is None: ord = 2 + from arraycontext.impl import _is_meshmode_dofarray, _is_pyopencl_array + + if _is_pyopencl_array(ary): + if ary.ndim != 1: + from arraycontext.impl import _flatten_cl_array + # mimics numpy's norm computation + return self.norm(_flatten_cl_array(ary), ord=2) + + if _is_meshmode_dofarray(ary): + from arraycontext.impl import _flatten_cl_array + + from warnings import warn + warn("Taking an actx.np.linalg.norm of a DOFArray is deprecated. " + "(DOFArrays use 2D arrays internally, and " + "actx.np.linalg.norm should compute matrix norms of those.) " + "This will stop working in 2022. " + "Use meshmode.dof_array.flat_norm instead.", + DeprecationWarning, stacklevel=2) + + import numpy.linalg as la + return la.norm( + [self.norm(_flatten_cl_array(subary), ord=ord) + for _, subary in serialize_container(ary)], + ord=ord) + if is_array_container(ary): if ord == np.inf: return max([self.norm(subary, ord=ord) diff --git a/arraycontext/impl/__init__.py b/arraycontext/impl/__init__.py index 6df8258599acbee87f9b031e86ae365dbb532cbb..093caeee3247d5d8e93fe1df3854de869718865e 100644 --- a/arraycontext/impl/__init__.py +++ b/arraycontext/impl/__init__.py @@ -1,3 +1,7 @@ +"""Various (undocumented) helper functions to avoid creating dependencies +on other packages (such as pyopencl or meshmode). +""" + __copyright__ = """ Copyright (C) 2020-1 University of Illinois Board of Trustees """ @@ -22,11 +26,39 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ +from typing import Any -def _is_meshmode_dofarray(x): + +def _is_meshmode_dofarray(x: Any) -> bool: try: from meshmode.dof_array import DOFArray except ImportError: return False else: return isinstance(x, DOFArray) + + +def _is_pyopencl_array(x: Any) -> bool: + try: + import pyopencl.array as cla + except ImportError: + return False + else: + return isinstance(x, cla.Array) + + +def _flatten_cl_array(ary): + import pyopencl.array as cl + assert isinstance(ary, cl.Array) + + if ary.size == 0: + # Work around https://github.com/inducer/pyopencl/pull/402 + return ary._new_with_changes( + data=None, offset=0, shape=(0,), strides=(ary.dtype.itemsize,)) + if ary.flags.f_contiguous: + return ary.reshape(-1, order="F") + elif ary.flags.c_contiguous: + return ary.reshape(-1, order="C") + else: + raise ValueError("cannot flatten array " + f"with strides {ary.strides} of {ary.dtype}") diff --git a/arraycontext/impl/pyopencl.py b/arraycontext/impl/pyopencl.py index 67374ca11ad66ca69cddcd2fc9b56447369a77e7..cf432eb0b72087cc089bf665d0c03dfb5a2925d7 100644 --- a/arraycontext/impl/pyopencl.py +++ b/arraycontext/impl/pyopencl.py @@ -40,7 +40,6 @@ from arraycontext.fake_numpy import \ BaseFakeNumpyNamespace, BaseFakeNumpyLinalgNamespace from arraycontext.container.traversal import (rec_multimap_array_container, rec_map_array_container) -from arraycontext.container import serialize_container from arraycontext.context import ArrayContext @@ -169,62 +168,8 @@ class PyOpenCLFakeNumpyNamespace(BaseFakeNumpyNamespace): # {{{ fake np.linalg -def _flatten_array(ary): - import pyopencl.array as cl - assert isinstance(ary, cl.Array) - - if ary.size == 0: - # Work around https://github.com/inducer/pyopencl/pull/402 - return ary._new_with_changes( - data=None, offset=0, shape=(0,), strides=(ary.dtype.itemsize,)) - if ary.flags.f_contiguous: - return ary.reshape(-1, order="F") - elif ary.flags.c_contiguous: - return ary.reshape(-1, order="C") - else: - raise ValueError("cannot flatten array " - f"with strides {ary.strides} of {ary.dtype}") - - class _PyOpenCLFakeNumpyLinalgNamespace(BaseFakeNumpyLinalgNamespace): - def norm(self, ary, ord=None): - from numbers import Number - import pyopencl.array as cla - - if isinstance(ary, Number): - return abs(ary) - - if ord is None and isinstance(ary, cla.Array): - if ary.ndim == 1: - ord = 2 - else: - # mimics numpy's norm computation - return self.norm(_flatten_array(ary), ord=2) - - try: - from meshmode.dof_array import DOFArray - except ImportError: - pass - else: - if isinstance(ary, DOFArray): - if ord is None: - ord = 2 - - from warnings import warn - warn("Taking an actx.np.linalg.norm of a DOFArray is deprecated. " - "(DOFArrays use 2D arrays internally, and " - "actx.np.linalg.norm should compute matrix norms of those.) " - "This will stop working in 2022. " - "Use meshmode.dof_array.flat_norm instead.", - DeprecationWarning, stacklevel=2) - - import numpy.linalg as la - return la.norm( - [self.norm(_flatten_array(subary), ord=ord) - for _, subary in serialize_container(ary)], - ord=ord) - - return super().norm(ary, ord) + pass # }}}