From d9bb98d696a00f727a4c29166f0debdfd1019b96 Mon Sep 17 00:00:00 2001
From: Thomas Gibson <gibsonthomas1120@hotmail.com>
Date: Tue, 25 May 2021 12:56:19 -0500
Subject: [PATCH] op: update documentation and nodal reductions

---
 grudge/op.py | 212 ++++++++++++++++++++++++---------------------------
 1 file changed, 101 insertions(+), 111 deletions(-)

diff --git a/grudge/op.py b/grudge/op.py
index d5d3eac4..d57e98f0 100644
--- a/grudge/op.py
+++ b/grudge/op.py
@@ -1,68 +1,6 @@
-__copyright__ = """
-Copyright (C) 2021 Andreas Kloeckner
-Copyright (C) 2021 University of Illinois Board of Trustees
-"""
-
-__license__ = """
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
 """
-
-
-from numbers import Number
-from functools import reduce
-
-from arraycontext import (
-        ArrayContext, FirstAxisIsElementsTag, make_loopy_program,
-        freeze)
-
-from grudge.discretization import DiscretizationCollection
-
-from pytools import (
-    memoize_in,
-    memoize_on_first_arg,
-    keyed_memoize_in
-)
-from pytools.obj_array import obj_array_vectorize, make_obj_array
-
-from meshmode.dof_array import DOFArray
-
-import numpy as np
-import grudge.dof_desc as dof_desc
-
-from grudge.trace_pair import (  # noqa
-    interior_trace_pair,
-    interior_trace_pairs,
-    connected_ranks,
-    cross_rank_trace_pairs,
-    bdry_trace_pair,
-    bv_trace_pair
-)
-
-
-__doc__ = """
-Metadata and geometry
-^^^^^^^^^^^^^^^^^^^^^
-
-Kernel tags
------------
-
-.. autoclass:: HasElementwiseMatvecTag
+Data transfer and geometry
+^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Projection and interpolation
 ----------------------------
@@ -108,9 +46,9 @@ Nodal reductions
 ----------------
 
 .. autofunction:: norm
-.. autofunction:: nodal_summation
-.. autofunction:: nodal_minimum
-.. autofunction:: nodal_maximum
+.. autofunction:: nodal_sum
+.. autofunction:: nodal_min
+.. autofunction:: nodal_max
 .. autofunction:: integral
 
 Elementwise reductions
@@ -119,6 +57,65 @@ Elementwise reductions
 .. autofunction:: elementwise_sum
 """
 
+__copyright__ = """
+Copyright (C) 2021 Andreas Kloeckner
+Copyright (C) 2021 University of Illinois Board of Trustees
+"""
+
+__license__ = """
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+"""
+
+
+from numbers import Number
+from functools import reduce
+
+from arraycontext import (
+    ArrayContext,
+    FirstAxisIsElementsTag,
+    make_loopy_program,
+    freeze
+)
+
+from grudge.discretization import DiscretizationCollection
+
+from pytools import (
+    memoize_in,
+    memoize_on_first_arg,
+    keyed_memoize_in
+)
+from pytools.obj_array import obj_array_vectorize, make_obj_array
+
+from meshmode.dof_array import DOFArray
+
+import numpy as np
+import grudge.dof_desc as dof_desc
+
+from grudge.trace_pair import (  # noqa
+    interior_trace_pair,
+    interior_trace_pairs,
+    connected_ranks,
+    cross_rank_trace_pairs,
+    bdry_trace_pair,
+    bv_trace_pair
+)
+
 
 # {{{ Kernel tags
 
@@ -138,7 +135,7 @@ class HasElementwiseMatvecTag(FirstAxisIsElementsTag):
 # FIXME: Should reintroduce interp and make clear distinctions
 # between projection and interpolations.
 # Related issue: https://github.com/inducer/grudge/issues/38
-# def interp(dcoll, src, tgt, vec):
+# def interp(dcoll: DiscretizationCollection, src, tgt, vec):
 #     from warnings import warn
 #     warn("using 'interp' is deprecated, use 'project' instead.",
 #          DeprecationWarning, stacklevel=2)
@@ -190,7 +187,7 @@ def nodes(dcoll: DiscretizationCollection, dd=None) -> np.ndarray:
 
 
 @memoize_on_first_arg
-def normal(dcoll, dd):
+def normal(dcoll: DiscretizationCollection, dd):
     r"""Get the unit normal to the specified surface discretization, *dd*.
 
     :arg dd: a :class:`~grudge.dof_desc.DOFDesc` as the surface discretization.
@@ -223,8 +220,9 @@ def h_max_from_volume(dcoll: DiscretizationCollection, dim=None, dd=None):
         dim = dcoll.dim
 
     ones = dcoll.discr_from_dd(dd).zeros(dcoll._setup_actx) + 1.0
-    return nodal_maximum(
+    return nodal_max(
         dcoll,
+        dd,
         elementwise_sum(dcoll, mass(dcoll, dd, ones))
     ) ** (1.0 / dim)
 
@@ -250,8 +248,9 @@ def h_min_from_volume(dcoll: DiscretizationCollection, dim=None, dd=None):
         dim = dcoll.dim
 
     ones = dcoll.discr_from_dd(dd).zeros(dcoll._setup_actx) + 1.0
-    return nodal_minimum(
+    return nodal_min(
         dcoll,
+        dd,
         elementwise_sum(dcoll, mass(dcoll, dd, ones))
     ) ** (1.0 / dim)
 
@@ -337,7 +336,7 @@ def local_d_dx(dcoll: DiscretizationCollection, xyz_axis, vec):
     return _compute_local_gradient(dcoll, vec, xyz_axis)
 
 
-def _div_helper(dcoll, diff_func, vecs):
+def _div_helper(dcoll: DiscretizationCollection, diff_func, vecs):
     if not isinstance(vecs, np.ndarray):
         raise TypeError("argument must be an object array")
     assert vecs.dtype == object
@@ -380,7 +379,8 @@ def local_div(dcoll: DiscretizationCollection, vecs):
 
 # {{{ Weak derivative operators
 
-def reference_stiffness_transpose_matrix(actx, out_element_group, in_element_group):
+def reference_stiffness_transpose_matrix(
+        actx: ArrayContext, out_element_group, in_element_group):
     @keyed_memoize_in(
         actx, reference_stiffness_transpose_matrix,
         lambda out_grp, in_grp: (out_grp.discretization_key(),
@@ -424,7 +424,8 @@ def reference_stiffness_transpose_matrix(actx, out_element_group, in_element_gro
                                            in_element_group)
 
 
-def _apply_stiffness_transpose_operator(dcoll, dd_out, dd_in, vec, xyz_axis):
+def _apply_stiffness_transpose_operator(
+        dcoll: DiscretizationCollection, dd_out, dd_in, vec, xyz_axis):
     from grudge.geometry import \
         inverse_surface_metric_derivative, area_element
 
@@ -593,7 +594,8 @@ def reference_mass_matrix(actx: ArrayContext, out_element_group, in_element_grou
     return get_ref_mass_mat(out_element_group, in_element_group)
 
 
-def _apply_mass_operator(dcoll, dd_out, dd_in, vec):
+def _apply_mass_operator(
+        dcoll: DiscretizationCollection, dd_out, dd_in, vec):
     if isinstance(vec, np.ndarray):
         return obj_array_vectorize(
             lambda vi: _apply_mass_operator(dcoll,
@@ -874,8 +876,8 @@ def _apply_face_mass_operator(dcoll: DiscretizationCollection, dd, vec):
                 "{[jdof]: 0 <= jdof < nface_nodes}"
             ],
             """
-            result[iel, idof] = sum(f, sum(jdof, mat[idof, f, jdof]        \
-                                                 * jac_surf[f, iel, jdof]  \
+            result[iel, idof] = sum(f, sum(jdof, mat[idof, f, jdof]
+                                                 * jac_surf[f, iel, jdof]
                                                  * vec[f, iel, jdof]))
             """,
             name="face_mass"
@@ -922,7 +924,7 @@ def face_mass(dcoll: DiscretizationCollection, *args):
     May be called with ``(vec)`` or ``(dd, vec)``.
 
     :arg dd: a :class:`~grudge.dof_desc.DOFDesc`, or a value convertible to one.
-        Defaults to the base 'all_faces' discretization if not provided.
+        Defaults to the base ``"all_faces"`` discretization if not provided.
     :arg vec: a :class:`~meshmode.dof_array.DOFArray` or object array of
         :class:`~meshmode.dof_array.DOFArray`\ s.
     :returns: a :class:`~meshmode.dof_array.DOFArray` denoting the
@@ -945,18 +947,19 @@ def face_mass(dcoll: DiscretizationCollection, *args):
 
 # {{{ Nodal reductions
 
-def _norm(dcoll, vec, p, dd):
+def _norm(dcoll: DiscretizationCollection, vec, p, dd):
     if isinstance(vec, Number):
         return np.fabs(vec)
     if p == 2:
         return np.sqrt(
-            nodal_summation(
+            nodal_sum(
                 dcoll,
+                dd,
                 vec * _apply_mass_operator(dcoll, dd, dd, vec)
             )
         )
     elif p == np.inf:
-        return nodal_maximum(dcoll, dcoll._setup_actx.np.fabs(vec))
+        return nodal_max(dcoll, dd, dcoll._setup_actx.np.fabs(vec))
     else:
         raise NotImplementedError("Unsupported value of p")
 
@@ -975,6 +978,9 @@ def norm(dcoll: DiscretizationCollection, vec, p, dd=None):
         Defaults to the base volume discretization if not provided.
     :returns: a nonegative scalar denoting the norm.
     """
+    # FIXME: Make MPI-aware
+    # NOTE: Must retain a way to do local reductions
+
     if dd is None:
         dd = dof_desc.DD_VOLUME
 
@@ -996,79 +1002,63 @@ def norm(dcoll: DiscretizationCollection, vec, p, dd=None):
 
 
 def nodal_sum(dcoll: DiscretizationCollection, dd, vec):
-    from warnings import warn
-    warn("Using 'nodal_sum' is deprecated, use 'nodal_summation' instead.",
-         DeprecationWarning, stacklevel=2)
-    return nodal_summation(dcoll, vec)
-
-
-def nodal_summation(dcoll: DiscretizationCollection, vec):
     r"""Return the nodal sum of a vector of degrees of freedom *vec*.
 
+    :arg dd: a :class:`~grudge.dof_desc.DOFDesc`, or a value
+        convertible to one.
     :arg vec: a :class:`~meshmode.dof_array.DOFArray`.
     :returns: a scalar denoting the nodal sum.
     """
     # FIXME: Make MPI-aware
+    # NOTE: Must retain a way to do local reductions
     actx = vec.array_context
     return sum([actx.np.sum(grp_ary) for grp_ary in vec])
 
 
 def nodal_min(dcoll: DiscretizationCollection, dd, vec):
-    from warnings import warn
-    warn("Using 'nodal_min' is deprecated, use 'nodal_minimum' instead.",
-         DeprecationWarning, stacklevel=2)
-    return nodal_minimum(dcoll, vec)
-
-
-def nodal_minimum(dcoll: DiscretizationCollection, vec):
     r"""Return the nodal minimum of a vector of degrees of freedom *vec*.
 
+    :arg dd: a :class:`~grudge.dof_desc.DOFDesc`, or a value
+        convertible to one.
     :arg vec: a :class:`~meshmode.dof_array.DOFArray`.
     :returns: a scalar denoting the nodal minimum.
     """
     # FIXME: Make MPI-aware
+    # NOTE: Must retain a way to do local reductions
     actx = vec.array_context
     return reduce(lambda acc, grp_ary: actx.np.minimum(acc, actx.np.min(grp_ary)),
                   vec, -np.inf)
 
 
 def nodal_max(dcoll: DiscretizationCollection, dd, vec):
-    from warnings import warn
-    warn("Using 'nodal_max' is deprecated, use 'nodal_maximum' instead.",
-         DeprecationWarning, stacklevel=2)
-    return nodal_maximum(dcoll, vec)
-
-
-def nodal_maximum(dcoll: DiscretizationCollection, vec):
     r"""Return the nodal maximum of a vector of degrees of freedom *vec*.
 
+    :arg dd: a :class:`~grudge.dof_desc.DOFDesc`, or a value
+        convertible to one.
     :arg vec: a :class:`~meshmode.dof_array.DOFArray`.
     :returns: a scalar denoting the nodal maximum.
     """
     # FIXME: Make MPI-aware
+    # NOTE: Must retain a way to do local reductions
     actx = vec.array_context
     return reduce(lambda acc, grp_ary: actx.np.maximum(acc, actx.np.max(grp_ary)),
                   vec, -np.inf)
 
 
-def integral(dcoll: DiscretizationCollection, vec, dd=None):
+def integral(dcoll: DiscretizationCollection, dd, vec):
     """Numerically integrates a function represented by a
     :class:`~meshmode.dof_array.DOFArray` of degrees of freedom.
 
-    :arg vec: a :class:`~meshmode.dof_array.DOFArray`
     :arg dd: a :class:`~grudge.dof_desc.DOFDesc`, or a value convertible to one.
-        Defaults to the base volume discretization if not provided.
+    :arg vec: a :class:`~meshmode.dof_array.DOFArray`
     :returns: a scalar denoting the evaluated integral.
     """
 
-    if dd is None:
-        dd = dof_desc.DD_VOLUME
-
     dd = dof_desc.as_dofdesc(dd)
 
     ones = dcoll.discr_from_dd(dd).zeros(vec.array_context) + 1.0
-    return nodal_summation(
-        dcoll, vec * _apply_mass_operator(dcoll, dd, dd, ones)
+    return nodal_sum(
+        dcoll, dd, vec * _apply_mass_operator(dcoll, dd, dd, ones)
     )
 
 # }}}
@@ -1076,7 +1066,7 @@ def integral(dcoll: DiscretizationCollection, vec, dd=None):
 
 # {{{  Elementwise reductions
 
-def _map_elementwise_reduction(actx, op_name):
+def _map_elementwise_reduction(actx: ArrayContext, op_name):
     @memoize_in(actx, (_map_elementwise_reduction,
                        "elementwise_%s_prg" % op_name))
     def prg():
-- 
GitLab