Skip to content
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .test-conda-env-py3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ dependencies:
- pyopencl
- python=3
- gmsh
- jax

# test scripts use ompi-specific arguments
- openmpi
Expand Down
2 changes: 2 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
intersphinx_mapping = {
"arraycontext": ("https://documen.tician.de/arraycontext/", None),
"loopy": ("https://documen.tician.de/loopy/", None),
"jax": ("https://docs.jax.dev/en/latest/", None),
"meshmode": ("https://documen.tician.de/meshmode/", None),
"modepy": ("https://documen.tician.de/modepy/", None),
"mpi4py": ("https://mpi4py.readthedocs.io/en/stable", None),
Expand All @@ -32,6 +33,7 @@
os.environ["PYOPENCL_TEST"] = "port:cpu"

nitpick_ignore_regex = [
["py:mod", r"jax"], # FIXME: not sure why this does not work
["py:class", r"np\.ndarray"],
["py:data|py:class", r"arraycontext.*ContainerTc"],
]
35 changes: 34 additions & 1 deletion grudge/array_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
.. autoclass:: MPIPyOpenCLArrayContext
.. autoclass:: MPINumpyArrayContext
.. class:: MPIPytatoArrayContext
.. autoclass:: MPIEagerJAXArrayContext
.. autofunction:: get_reasonable_array_context_class
"""

Expand Down Expand Up @@ -76,10 +77,11 @@
_HAVE_FUSION_ACTX = False


from arraycontext import ArrayContext, NumpyArrayContext
from arraycontext import ArrayContext, EagerJAXArrayContext, NumpyArrayContext
from arraycontext.container import ArrayContainer
from arraycontext.impl.pytato.compile import LazilyPyOpenCLCompilingFunctionCaller
from arraycontext.pytest import (
_PytestEagerJaxArrayContextFactory,
_PytestNumpyArrayContextFactory,
_PytestPyOpenCLArrayContextFactoryWithClass,
_PytestPytatoPyOpenCLArrayContextFactory,
Expand Down Expand Up @@ -428,6 +430,26 @@ def clone(self) -> Self:
# }}}


# {{{ distributed + eager jax

class MPIEagerJAXArrayContext(EagerJAXArrayContext, MPIBasedArrayContext):
"""An array context for using distributed computation with :mod:`jax`
eager evaluation.

.. autofunction:: __init__
"""

def __init__(self, mpi_communicator) -> None:
super().__init__()

self.mpi_communicator = mpi_communicator

def clone(self) -> Self:
return type(self)(self.mpi_communicator)

# }}}


# {{{ distributed + pytato array context subclasses

class MPIBasePytatoPyOpenCLArrayContext(
Expand Down Expand Up @@ -521,12 +543,23 @@ def __call__(self):
return self.actx_class()


class PytestEagerJAXArrayContextFactory(_PytestEagerJaxArrayContextFactory):
actx_class = EagerJAXArrayContext

def __call__(self):
import jax
jax.config.update("jax_enable_x64", True)
return self.actx_class()


register_pytest_array_context_factory("grudge.pyopencl",
PytestPyOpenCLArrayContextFactory)
register_pytest_array_context_factory("grudge.pytato-pyopencl",
PytestPytatoPyOpenCLArrayContextFactory)
register_pytest_array_context_factory("grudge.numpy",
PytestNumpyArrayContextFactory)
register_pytest_array_context_factory("grudge.eager-jax",
PytestEagerJAXArrayContextFactory)

# }}}

Expand Down
14 changes: 10 additions & 4 deletions grudge/geometry/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,15 +566,21 @@ def _signed_face_ones(

signed_face_ones_numpy = actx.to_numpy(signed_ones)

new_group_arrays = []
for igrp, grp in enumerate(all_faces_conn.groups):
grp_field = signed_face_ones_numpy[igrp]
sign_mask = np.ones_like(grp_field)

@alexfikl alexfikl May 29, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a hard time remembering why this was written this way (I think those signed_face_ones arrays are just created this way so that they have the right shape?), but maybe we can improve it a bit.

How about this?

  • Remove the signed_face_ones and signed_face_ones_numpy things.
  • Get the discretization discr = dcoll.discr_from_dd(dd.with_discr_tag(DISCR_TAG_BASE))
  • For each zip(discr.groups, conn.groups), mask = np.ones((dgrp.nelements, dgrp.nunit_dofs), dtype=discr.real_dtype)
  • The rest just stays the same (?)

Would something like that work? The main idea being that we'll just create everything in numpy and then transfer it over to the array context, so we don't have to worry about how writable the arrays are.

We might want to tag the end result in the same way that Discretization.zeros does too?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion! What do you think of 85a0d54? (feel free to push directly to this branch if I did something silly, I am very unfamiliar with this code).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! (doesn't look like the test failure is related?)


for batch in grp.batches:
assert batch.to_element_face is not None
i = actx.to_numpy(actx.thaw(batch.to_element_indices))
grp_field = signed_face_ones_numpy[igrp].reshape(-1)
grp_field[i] = \
(2.0 * (batch.to_element_face % 2) - 1.0) * grp_field[i]
sign = (2.0 * (batch.to_element_face % 2) - 1.0)
sign_mask[i, :] = sign

new_group_arrays.append(grp_field * sign_mask)
Comment thread
matthiasdiener marked this conversation as resolved.
Outdated

return actx.from_numpy(signed_face_ones_numpy)
from meshmode.dof_array import DOFArray
return actx.from_numpy(DOFArray(actx, tuple(new_group_arrays)))


def parametrization_derivative(
Expand Down
4 changes: 3 additions & 1 deletion test/test_dt_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from arraycontext import pytest_generate_tests_for_array_contexts

from grudge.array_context import (
PytestEagerJAXArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestPyOpenCLArrayContextFactory,
PytestPytatoPyOpenCLArrayContextFactory,
Expand All @@ -36,7 +37,8 @@
pytest_generate_tests = pytest_generate_tests_for_array_contexts(
[PytestPyOpenCLArrayContextFactory,
PytestPytatoPyOpenCLArrayContextFactory,
PytestNumpyArrayContextFactory])
PytestNumpyArrayContextFactory,
PytestEagerJAXArrayContextFactory])

import logging

Expand Down
10 changes: 8 additions & 2 deletions test/test_euler_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,18 @@
)

from grudge import op
from grudge.array_context import PytestPyOpenCLArrayContextFactory
from grudge.array_context import (
PytestEagerJAXArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestPyOpenCLArrayContextFactory,
)


logger = logging.getLogger(__name__)
pytest_generate_tests = pytest_generate_tests_for_array_contexts(
[PytestPyOpenCLArrayContextFactory])
[PytestPyOpenCLArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestEagerJAXArrayContextFactory])


@pytest.mark.parametrize("order", [1, 2, 3])
Expand Down
10 changes: 8 additions & 2 deletions test/test_grudge.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,19 @@
from pytools.obj_array import flat_obj_array

from grudge import dof_desc, geometry, op
from grudge.array_context import PytestPyOpenCLArrayContextFactory
from grudge.array_context import (
PytestEagerJAXArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestPyOpenCLArrayContextFactory,
)
from grudge.discretization import make_discretization_collection


logger = logging.getLogger(__name__)
pytest_generate_tests = pytest_generate_tests_for_array_contexts(
[PytestPyOpenCLArrayContextFactory])
[PytestPyOpenCLArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestEagerJAXArrayContextFactory])


# {{{ mass operator trig integration
Expand Down
4 changes: 3 additions & 1 deletion test/test_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from meshmode.dof_array import flat_norm

from grudge.array_context import (
PytestEagerJAXArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestPyOpenCLArrayContextFactory,
PytestPytatoPyOpenCLArrayContextFactory,
Expand All @@ -44,7 +45,8 @@
pytest_generate_tests = pytest_generate_tests_for_array_contexts(
[PytestPyOpenCLArrayContextFactory,
PytestPytatoPyOpenCLArrayContextFactory,
PytestNumpyArrayContextFactory])
PytestNumpyArrayContextFactory,
PytestEagerJAXArrayContextFactory])


# {{{ inverse metric
Expand Down
10 changes: 8 additions & 2 deletions test/test_modal_connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,18 @@

from arraycontext import pytest_generate_tests_for_array_contexts

from grudge.array_context import PytestPyOpenCLArrayContextFactory
from grudge.array_context import (
PytestEagerJAXArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestPyOpenCLArrayContextFactory,
)
from grudge.discretization import make_discretization_collection


pytest_generate_tests = pytest_generate_tests_for_array_contexts(
[PytestPyOpenCLArrayContextFactory])
[PytestPyOpenCLArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestEagerJAXArrayContextFactory])

import pytest

Expand Down
14 changes: 12 additions & 2 deletions test/test_mpi_communication.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@
from pytools.obj_array import flat_obj_array

from grudge import dof_desc, op
from grudge.array_context import MPIPyOpenCLArrayContext, MPIPytatoArrayContext
from grudge.array_context import (
MPIEagerJAXArrayContext,
MPINumpyArrayContext,
MPIPyOpenCLArrayContext,
MPIPytatoArrayContext,
)
from grudge.discretization import make_discretization_collection
from grudge.shortcuts import compiled_lsrk45_step

Expand All @@ -49,7 +54,8 @@ class SimpleTag:

# {{{ mpi test infrastructure

DISTRIBUTED_ACTXS = [MPIPyOpenCLArrayContext, MPIPytatoArrayContext]
DISTRIBUTED_ACTXS = [MPIPyOpenCLArrayContext, MPIPytatoArrayContext,
MPIEagerJAXArrayContext, MPINumpyArrayContext]


def run_test_with_mpi(num_ranks, f, *args):
Expand Down Expand Up @@ -87,6 +93,10 @@ def run_test_with_mpi_inner():
actx = actx_class(comm, queue, mpi_base_tag=15000)
elif actx_class is MPIPyOpenCLArrayContext:
actx = actx_class(comm, queue)
elif actx_class is MPIEagerJAXArrayContext:
actx = actx_class(comm)
elif actx_class is MPINumpyArrayContext:
actx = actx_class(comm)
else:
raise ValueError("unknown actx_class")

Expand Down
10 changes: 8 additions & 2 deletions test/test_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@
from pytools.obj_array import make_obj_array

from grudge import geometry, op
from grudge.array_context import PytestPyOpenCLArrayContextFactory
from grudge.array_context import (
PytestEagerJAXArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestPyOpenCLArrayContextFactory,
)
from grudge.discretization import make_discretization_collection
from grudge.dof_desc import (
DISCR_TAG_BASE,
Expand All @@ -52,7 +56,9 @@

logger = logging.getLogger(__name__)
pytest_generate_tests = pytest_generate_tests_for_array_contexts(
[PytestPyOpenCLArrayContextFactory])
[PytestPyOpenCLArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestEagerJAXArrayContextFactory])


# {{{ gradient
Expand Down
10 changes: 8 additions & 2 deletions test/test_reductions.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,19 @@
from pytools.obj_array import make_obj_array

from grudge import op
from grudge.array_context import PytestPyOpenCLArrayContextFactory
from grudge.array_context import (
PytestEagerJAXArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestPyOpenCLArrayContextFactory,
)
from grudge.discretization import make_discretization_collection


logger = logging.getLogger(__name__)
pytest_generate_tests = pytest_generate_tests_for_array_contexts(
[PytestPyOpenCLArrayContextFactory])
[PytestPyOpenCLArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestEagerJAXArrayContextFactory])


@pytest.mark.parametrize(("mesh_size", "with_initial"), [
Expand Down
14 changes: 0 additions & 14 deletions test/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,11 @@

import numpy as np
import numpy.linalg as la # noqa

from arraycontext import pytest_generate_tests_for_array_contexts

from grudge.array_context import PytestPyOpenCLArrayContextFactory


pytest_generate_tests = pytest_generate_tests_for_array_contexts(
[PytestPyOpenCLArrayContextFactory])

import logging

import pytest

from pytools.obj_array import make_obj_array


logger = logging.getLogger(__name__)


# {{{ map_subarrays and rec_map_subarrays

@dataclass(frozen=True, eq=True)
Expand Down
10 changes: 8 additions & 2 deletions test/test_trace_pair.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,20 @@
from arraycontext import pytest_generate_tests_for_array_contexts
from meshmode.dof_array import DOFArray

from grudge.array_context import PytestPyOpenCLArrayContextFactory
from grudge.array_context import (
PytestEagerJAXArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestPyOpenCLArrayContextFactory,
)
from grudge.discretization import make_discretization_collection
from grudge.trace_pair import TracePair


logger = logging.getLogger(__name__)
pytest_generate_tests = pytest_generate_tests_for_array_contexts(
[PytestPyOpenCLArrayContextFactory])
[PytestPyOpenCLArrayContextFactory,
PytestNumpyArrayContextFactory,
PytestEagerJAXArrayContextFactory])


def test_trace_pair(actx_factory):
Expand Down