From ea72946d8b6137f248fa4cdbbbff9842b73ac5a8 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Thu, 9 Apr 2026 19:33:29 -0400 Subject: [PATCH 01/11] update the _build_data_index function to use depth-first search sorted loop to prevent recursion --- .vscode/settings.json | 4 + desc/compute/__init__.py | 157 +++++++++++++++++++++++++++++++++------ 2 files changed, 139 insertions(+), 22 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..c820b9a31a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "python-envs.defaultEnvManager": "ms-python.python:conda", + "python-envs.defaultPackageManager": "ms-python.python:conda" +} diff --git a/desc/compute/__init__.py b/desc/compute/__init__.py index 1627dfe63f..e2f0c4784f 100644 --- a/desc/compute/__init__.py +++ b/desc/compute/__init__.py @@ -23,8 +23,7 @@ """ -# just need to import all the submodules here to register everything in the -# data_index +import numpy as np from ..utils import rpz2xyz, rpz2xyz_vec, xyz2rpz, xyz2rpz_vec from . import ( @@ -55,42 +54,156 @@ profile_names, ) +# just need to import all the submodules here to register everything in the +# data_index + # Rather than having to recursively compute the full dependencies every time we # compute something, it's easier to just do it once for all quantities when we first # import the compute module. -def _build_data_index(): +def _build_data_index(): # noqa: C901 + """For each quantity in data_index, build the full set of dependencies. + + This function first performs a sort of the quantities such that the ones with + no dependencies come first, then the ones that depend only on those, etc. Then + it iterates through the quantities in that order, building the full dependency + set for each one by taking the union of its direct dependencies and the full + dependencies of those dependencies, which have already been computed by the time + we get to this quantity. + + The first sorting is important to avoid deep recursion when building the full + dependency sets. Since the first elements of the order have no dependencies, + we can build their full dependency sets by simple union operation. + + Note: This function is originally written by Claude Code and reviewed by Yigit + Gunsur Elmacioglu. + """ + + def _collect_deps(p, all_deps): + """Collect transforms, params, profiles from a list of dependency keys. + + For each key in the data_index, we call this function with full set of + dependencies of that key, and it collects the transforms, params, and + profiles needed by all those dependencies in a single pass. + """ + transforms = {} + params = [] + profiles = [] + for k in all_deps: + k_deps = data_index[p][k]["dependencies"] + for tkey, tval in k_deps["transforms"].items(): + if tkey not in transforms: + transforms[tkey] = [] + transforms[tkey] += tval + params += k_deps["params"] + profiles += k_deps["profiles"] + transforms = {k: np.unique(v, axis=0).tolist() for k, v in transforms.items()} + profiles = sorted(set(profiles)) + return transforms, params, profiles for p in data_index: - for key in data_index[p]: + # --- Step 1: Topological sort via iterative Depth-First Search --- + # We need to process quantities with no dependencies before the + # quantities that depend on them. This way, when we process key K, + # all of K's dependencies already have their full_dependencies and + # full_with_axis_dependencies cached, and we can build K's full + # dependency set with a simple set union instead of deep recursion. + order = [] + visited = set() + for start in data_index[p]: + if start in visited: + continue + stack = [(start, False)] + while stack: + node, processed = stack.pop() + if processed: + if node not in visited: + visited.add(node) + order.append(node) + continue + if node in visited: + continue + # Mark for post-processing after all deps are visited. + stack.append((node, True)) + node_deps = data_index[p][node]["dependencies"] + for dep in node_deps["data"]: + if dep not in visited: + stack.append((dep, False)) + for dep in node_deps["axis_limit_data"]: + if dep not in visited: + stack.append((dep, False)) + + # --- Step 2: Build full dependency sets incrementally --- + # Because we iterate in topological order, every dependency of the + # current key already has its full_dependencies cached. So the full + # transitive data deps of key K is just: + # union of (each direct dep D) + (D's already-cached full data deps) + # No recursion needed — O(number of direct deps) per key. + for key in order: + d = data_index[p][key] + deps_info = d["dependencies"] + direct_data = deps_info["data"] + + # Full data deps without axis limit contributions. + # Apply union operation + full_data_set = set() + for dep in direct_data: + full_data_set.add(dep) + full_data_set.update(data_index[p][dep]["full_dependencies"]["data"]) + deps_no_axis = sorted(full_data_set) + + transforms, params, profiles = _collect_deps(p, [key] + deps_no_axis) full = { - "data": get_data_deps(key, p, has_axis=False, basis="rpz"), - "transforms": get_derivs(key, p, has_axis=False, basis="rpz"), - "params": get_params(key, p, has_axis=False, basis="rpz"), - "profiles": get_profiles(key, p, has_axis=False, basis="rpz"), + "data": deps_no_axis, + "transforms": transforms, + "params": params, + "profiles": profiles, } - data_index[p][key]["full_dependencies"] = full - full_with_axis_data = get_data_deps(key, p, has_axis=True) - if len(full["data"]) >= len(full_with_axis_data): - # Then this quantity and all its dependencies do not need anything + # Cache now so later keys can use it. + d["full_dependencies"] = full + + # Full data deps including axis limit data contributions. + # axis_limit_data lists extra quantities needed to evaluate limits + # at the magnetic axis; these are only relevant when has_axis=True. + axis_limit_data = deps_info["axis_limit_data"] + full_data_axis_set = set() + for dep in direct_data: + full_data_axis_set.add(dep) + full_data_axis_set.update( + data_index[p][dep]["full_with_axis_dependencies"]["data"] + ) + for dep in axis_limit_data: + full_data_axis_set.add(dep) + full_data_axis_set.update( + data_index[p][dep]["full_with_axis_dependencies"]["data"] + ) + deps_with_axis = sorted(full_data_axis_set) + + if len(deps_no_axis) >= len(deps_with_axis): + # This quantity and all its dependencies do not need anything # extra to evaluate its limit at the magnetic axis. - # The dependencies in the `full` dictionary and the `full_with_axis` - # dictionary will be identical, so we assign the same reference to - # avoid storing a copy. + # Assign the same reference to avoid storing a copy. full_with_axis = full else: + transforms_a, params_a, profiles_a = _collect_deps( + p, [key] + deps_with_axis + ) full_with_axis = { - "data": full_with_axis_data, - "transforms": get_derivs(key, p, has_axis=True, basis="rpz"), - "params": get_params(key, p, has_axis=True, basis="rpz"), - "profiles": get_profiles(key, p, has_axis=True, basis="rpz"), + "data": deps_with_axis, + "transforms": transforms_a, + "params": params_a, + "profiles": profiles_a, } + # transforms, params, and profiles can be the same for both full and + # full_with_axis, so check if they are and if so, dereference the copy + # to save memory. for _key, val in full_with_axis.items(): if full[_key] == val: - # Nothing extra was needed to evaluate this quantity's limit. - # One is a copy of the other; dereference to save memory. + # Nothing extra was needed for this field. + # Dereference the copy to save memory. full_with_axis[_key] = full[_key] - data_index[p][key]["full_with_axis_dependencies"] = full_with_axis + + d["full_with_axis_dependencies"] = full_with_axis _build_data_index() From e99c82ffc719e057621d570b0114e77f723c89b1 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Thu, 9 Apr 2026 19:45:44 -0400 Subject: [PATCH 02/11] keep the keys in topologically sorted order to make future looped _compute easier --- desc/compute/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/desc/compute/__init__.py b/desc/compute/__init__.py index e2f0c4784f..343ca29002 100644 --- a/desc/compute/__init__.py +++ b/desc/compute/__init__.py @@ -139,6 +139,10 @@ def _collect_deps(p, all_deps): # transitive data deps of key K is just: # union of (each direct dep D) + (D's already-cached full data deps) # No recursion needed — O(number of direct deps) per key. + + # The deps are stored in topological order (not alphabetical) so that + # iterating over them computes quantities in valid dependency order. + topo_index = {key: i for i, key in enumerate(order)} for key in order: d = data_index[p][key] deps_info = d["dependencies"] @@ -150,7 +154,7 @@ def _collect_deps(p, all_deps): for dep in direct_data: full_data_set.add(dep) full_data_set.update(data_index[p][dep]["full_dependencies"]["data"]) - deps_no_axis = sorted(full_data_set) + deps_no_axis = sorted(full_data_set, key=topo_index.__getitem__) transforms, params, profiles = _collect_deps(p, [key] + deps_no_axis) full = { @@ -177,7 +181,7 @@ def _collect_deps(p, all_deps): full_data_axis_set.update( data_index[p][dep]["full_with_axis_dependencies"]["data"] ) - deps_with_axis = sorted(full_data_axis_set) + deps_with_axis = sorted(full_data_axis_set, key=topo_index.__getitem__) if len(deps_no_axis) >= len(deps_with_axis): # This quantity and all its dependencies do not need anything From 1027c75e63a52043a1a522da27f49336865a0d0c Mon Sep 17 00:00:00 2001 From: YigitElma Date: Thu, 9 Apr 2026 20:25:26 -0400 Subject: [PATCH 03/11] remove the module level default_quad computation, use lru_cache instead --- desc/integrals/bounce_integral.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/desc/integrals/bounce_integral.py b/desc/integrals/bounce_integral.py index 02ca47d65e..d7a5bd1405 100644 --- a/desc/integrals/bounce_integral.py +++ b/desc/integrals/bounce_integral.py @@ -2,6 +2,7 @@ import warnings from abc import ABC, abstractmethod +from functools import lru_cache from equinox import Module from interpax import CubicHermiteSpline, PPoly @@ -147,10 +148,13 @@ def plot(self, l, m, pitch_inv=None, **kwargs): """Plot B and bounce points on the specified field line.""" -default_quad = get_quadrature( - leggauss(32), - (automorphism_sin, grad_automorphism_sin), -) +@lru_cache(maxsize=1) +def _default_quad(): + """Compute and cache the default quadrature instead of module level import time.""" + return get_quadrature( + leggauss(32), + (automorphism_sin, grad_automorphism_sin), + ) class Bounce2D(Bounce): @@ -301,7 +305,7 @@ def __init__( is_reshaped = is_reshaped or is_fourier vander = setdefault(vander, {}) - self._quad = get_quadrature(setdefault(quad, default_quad), automorphism) + self._quad = get_quadrature(setdefault(quad, _default_quad()), automorphism) self._NFP = grid.NFP self._num_t = grid.num_theta self._modes_z, self._modes_t = rfft2_modes( @@ -1468,7 +1472,7 @@ def __init__( ): """Returns an object to compute bounce integrals.""" assert grid.is_meshgrid - quad = setdefault(quad, default_quad) + quad = setdefault(quad, _default_quad()) self._quad = get_quadrature(quad, automorphism) self._data = { From 1716fa00e141bb3018c089b72694714b8a322720 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Thu, 9 Apr 2026 20:41:44 -0400 Subject: [PATCH 04/11] update gitignore, vscode started createing this file multiple times --- .gitignore | 2 ++ .vscode/settings.json | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index df621252f0..551d089d5f 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ uv.lock # Environments .env .venv + +.vscode/ diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index c820b9a31a..0000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "python-envs.defaultEnvManager": "ms-python.python:conda", - "python-envs.defaultPackageManager": "ms-python.python:conda" -} From d2a757e5ea4b531dd946f7f5ec17af9b16a969e8 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Thu, 9 Apr 2026 20:50:33 -0400 Subject: [PATCH 05/11] update changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fab2b32f6a..7c25c36ba4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,21 @@ Changelog ========= + +Performance Improvements + +- Reduces import time of `desc.compute` module which is triggered by almost all other DESC modules. Now, `_build_data_index` uses depth-first search dependency tree construction algorithm. + + +v0.17.1 +------- + Bug Fixes - Fixes incorrect units in the documentation of some curvature variables. - Fixes SyntaxError thrown when loading hdf5 data from file-like objects. + v0.17.0 ------- From f05ffdccee45a414a0c458580f957d84eaa449cf Mon Sep 17 00:00:00 2001 From: YigitElma Date: Fri, 10 Apr 2026 00:02:27 -0400 Subject: [PATCH 06/11] remove default_quad from import level, we mostly pass quad anyway, simplify desc.backend jax tests --- desc/backend.py | 10 ++++------ desc/integrals/bounce_integral.py | 29 +++++++++++++++++------------ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/desc/backend.py b/desc/backend.py index bfd6908108..50f67da3c6 100644 --- a/desc/backend.py +++ b/desc/backend.py @@ -36,13 +36,11 @@ + "installed JAX with GPU support?" ) set_device("cpu") - x = jnp.linspace(0, 5) - y = jnp.exp(x) + x = jnp.arange(2) use_jax = True except ModuleNotFoundError: jnp = np - x = jnp.linspace(0, 5) - y = jnp.exp(x) + x = jnp.arange(2) use_jax = False set_device(kind="cpu") warnings.warn(colored("Failed to load JAX", "red")) @@ -54,10 +52,10 @@ def print_backend_info(): if use_jax: print( f"Using JAX backend: jax version={jax.__version__}, " - + f"jaxlib version={jaxlib.__version__}, dtype={y.dtype}." + + f"jaxlib version={jaxlib.__version__}, dtype={x.dtype}." ) else: - print(f"Using NumPy backend: version={np.__version__}, dtype={y.dtype}.") + print(f"Using NumPy backend: version={np.__version__}, dtype={x.dtype}.") print( "Using device: {}, with {:.2f} GB available memory.".format( desc_config.get("device"), desc_config.get("avail_mem") diff --git a/desc/integrals/bounce_integral.py b/desc/integrals/bounce_integral.py index d7a5bd1405..7db397cc04 100644 --- a/desc/integrals/bounce_integral.py +++ b/desc/integrals/bounce_integral.py @@ -2,7 +2,6 @@ import warnings from abc import ABC, abstractmethod -from functools import lru_cache from equinox import Module from interpax import CubicHermiteSpline, PPoly @@ -148,15 +147,6 @@ def plot(self, l, m, pitch_inv=None, **kwargs): """Plot B and bounce points on the specified field line.""" -@lru_cache(maxsize=1) -def _default_quad(): - """Compute and cache the default quadrature instead of module level import time.""" - return get_quadrature( - leggauss(32), - (automorphism_sin, grad_automorphism_sin), - ) - - class Bounce2D(Bounce): """Computes bounce integrals using pseudo-spectral methods. @@ -305,7 +295,16 @@ def __init__( is_reshaped = is_reshaped or is_fourier vander = setdefault(vander, {}) - self._quad = get_quadrature(setdefault(quad, _default_quad()), automorphism) + self._quad = get_quadrature( + setdefault( + quad, + get_quadrature( + leggauss(32), + (automorphism_sin, grad_automorphism_sin), + ), + ), + automorphism, + ) self._NFP = grid.NFP self._num_t = grid.num_theta self._modes_z, self._modes_t = rfft2_modes( @@ -1472,7 +1471,13 @@ def __init__( ): """Returns an object to compute bounce integrals.""" assert grid.is_meshgrid - quad = setdefault(quad, _default_quad()) + quad = setdefault( + quad, + get_quadrature( + leggauss(32), + (automorphism_sin, grad_automorphism_sin), + ), + ) self._quad = get_quadrature(quad, automorphism) self._data = { From 7b4673bb763b007f9cc9b49227d2ca20d1fc7a88 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 13 Apr 2026 23:24:06 -0400 Subject: [PATCH 07/11] put default quad creation inside if statement, add stop gradient --- desc/integrals/bounce_integral.py | 34 ++++++++++++++----------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/desc/integrals/bounce_integral.py b/desc/integrals/bounce_integral.py index 7db397cc04..028063adac 100644 --- a/desc/integrals/bounce_integral.py +++ b/desc/integrals/bounce_integral.py @@ -295,16 +295,14 @@ def __init__( is_reshaped = is_reshaped or is_fourier vander = setdefault(vander, {}) - self._quad = get_quadrature( - setdefault( - quad, - get_quadrature( - leggauss(32), - (automorphism_sin, grad_automorphism_sin), - ), - ), - automorphism, - ) + if quad is None: + quad = get_quadrature( + leggauss(32), (automorphism_sin, grad_automorphism_sin) + ) + elif automorphism is not None: + quad = get_quadrature(quad, automorphism) + self._quad = jax.lax.stop_gradient(quad) + self._NFP = grid.NFP self._num_t = grid.num_theta self._modes_z, self._modes_t = rfft2_modes( @@ -1471,15 +1469,13 @@ def __init__( ): """Returns an object to compute bounce integrals.""" assert grid.is_meshgrid - quad = setdefault( - quad, - get_quadrature( - leggauss(32), - (automorphism_sin, grad_automorphism_sin), - ), - ) - - self._quad = get_quadrature(quad, automorphism) + if quad is None: + quad = get_quadrature( + leggauss(32), (automorphism_sin, grad_automorphism_sin) + ) + elif automorphism is not None: + quad = get_quadrature(quad, automorphism) + self._quad = jax.lax.stop_gradient(quad) self._data = { "|b^zeta|": jnp.abs(data["B^zeta"]) * Lref / data["|B|"], "|B|": data["|B|"] / Bref, From 2a6316b8595b46e3e480d013379e84a2b71fe082 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 13 Apr 2026 23:28:21 -0400 Subject: [PATCH 08/11] add exp back with smaller array --- desc/backend.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/desc/backend.py b/desc/backend.py index 50f67da3c6..e2d0b02a04 100644 --- a/desc/backend.py +++ b/desc/backend.py @@ -36,11 +36,13 @@ + "installed JAX with GPU support?" ) set_device("cpu") - x = jnp.arange(2) + x = jnp.linspace(0, 5, 2) + y = jnp.exp(x) use_jax = True except ModuleNotFoundError: jnp = np - x = jnp.arange(2) + x = jnp.linspace(0, 5, 2) + y = jnp.exp(x) use_jax = False set_device(kind="cpu") warnings.warn(colored("Failed to load JAX", "red")) From fd2f837a6bf277210c32fe38cb48ea0d788f14b4 Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 13 Apr 2026 23:46:59 -0400 Subject: [PATCH 09/11] update changelog --- CHANGELOG.md | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c25c36ba4..3c5621a65b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,26 @@ Changelog ========= +New Features + +- Adds ``num_neighbors`` parameter to ``CoilSetMinDistance`` that limits the pairwise distance computation to the nearest neighbors per coil, reducing memory useage for large coilsets. +- Method to plot frequency spectrum of inverse stream map in field line coordinates ``Bounce2D.plot_angle_spectrum``. +- Method to compute bounce integrals in batches is now added to the public API ``Bounce2D.batch``. +- Initiated deprecation of ``Bounce2D.compute_fieldline_length`` in favor of ``eq.compute("V_psi")``. + - The quadrature resolution in ``Bounce2D.compute_fieldline_length`` now corresponds to the resolution over a single field period instead of the resolution over a toroidal transit. + +Bug Fixes + +- Fixes SyntaxError thrown when loading hdf5 data from file-like objects. Performance Improvements -- Reduces import time of `desc.compute` module which is triggered by almost all other DESC modules. Now, `_build_data_index` uses depth-first search dependency tree construction algorithm. +- Reduces import time of `desc` modules. + - Now, `desc.compute._build_data_index` uses depth-first search algorithm to construct the dependency tree. + - Some of the default value computations at import time are removed (i.e. `desc.integrals.bounce_integral.default_quad`) +- [Significantly improves convergence of inverse stream maps](https://github.com/PlasmaControl/DESC/pull/1919). +- Check-pointing to bounce integrals to improve speed and reduce memory of reverse mode differentiation. +- Resolves a JAX memory regression in bounce integrals by avoiding materialization of a large tensor in memory. Previously, we had closed the issue by adding nuffts as a workaround. This update actually solves the issue for the case when a user specifies to not use nuffts as well. v0.17.1 @@ -13,7 +29,6 @@ v0.17.1 Bug Fixes - Fixes incorrect units in the documentation of some curvature variables. -- Fixes SyntaxError thrown when loading hdf5 data from file-like objects. v0.17.0 @@ -21,11 +36,6 @@ v0.17.0 New Features -- [Significantly improves convergence of inverse stream maps](https://github.com/PlasmaControl/DESC/pull/1919). - - Method to plot frequency spectrum of inverse stream map in field line coordinates ``Bounce2D.plot_angle_spectrum``. -- Method to compute bounce integrals in batches is now added to the public API ``Bounce2D.batch``. -- Initiated deprecation of ``Bounce2D.compute_fieldline_length`` in favor of ``eq.compute("V_psi")``. - - The quadrature resolution in ``Bounce2D.compute_fieldline_length`` now corresponds to the resolution over a single field period instead of the resolution over a toroidal transit. - Adds particle tracing capabilities in ``desc.particles`` module. - Particle tracing is done via ``desc.particles.trace_particles`` function. - Particles can be initialized in couple different ways: @@ -54,7 +64,6 @@ Bug Fixes - No longer uses the full Hessian to compute the scale when ``x_scale="auto"`` and using a scipy optimizer that approximates the hessian (e.g. if using ``"scipy-bfgs"``, no longer attempts the Hessian computation to get the x_scale). - ``SplineMagneticField.from_field()`` correctly uses the ``NFP`` input when given. Also adds this as a similar input option to ``MagneticField.save_mgrid()``. -- Significantly improves convergence of inverse stream maps in bounce integrals. - Fixes some bugs that hampered robustness of ``desc.geometry.FourierRZToroidalSurface.constant_offset_surface``, particularly when the given grid had stellarator symmetry or when NFP=1. - Fixes possible bug in computing normalizations when both kinetic and pressure profiles are assigned. Also adds warnings whenever an pressure is added to a kinetic-constrained equilibrium and vice-versa to alert user to ambiguous equilibrium setups. - Adds error in ``MercierStability`` to guard against situation where if a grid with a point at ``rho=0`` were used, NaN would be computed, as``MercierStability`` is undefined on-axis. @@ -62,8 +71,6 @@ Bug Fixes Performance Improvements - `ProximalProjection.grad` uses a single VJP on the objective instead of multiple JVP followed by a manual VJP. This should be more efficient for expensive objectives. -- Check-pointing to bounce integrals to improve speed and reduce memory of reverse mode differentiation. -- Resolves a JAX memory regression in bounce integrals by avoiding materialization of a large tensor in memory. Previously, we had closed the issue by adding nuffts as a workaround. This update actually solves the issue for the case when a user specifies to not use nuffts as well. Deprecations From fcf7fd8fdc40ed0cd3c46f652598d8bd9ff3bfbe Mon Sep 17 00:00:00 2001 From: YigitElma Date: Mon, 13 Apr 2026 23:54:30 -0400 Subject: [PATCH 10/11] remove redundant changes --- desc/backend.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/desc/backend.py b/desc/backend.py index e2d0b02a04..a5dbd9a17b 100644 --- a/desc/backend.py +++ b/desc/backend.py @@ -54,10 +54,10 @@ def print_backend_info(): if use_jax: print( f"Using JAX backend: jax version={jax.__version__}, " - + f"jaxlib version={jaxlib.__version__}, dtype={x.dtype}." + + f"jaxlib version={jaxlib.__version__}, dtype={y.dtype}." ) else: - print(f"Using NumPy backend: version={np.__version__}, dtype={x.dtype}.") + print(f"Using NumPy backend: version={np.__version__}, dtype={y.dtype}.") print( "Using device: {}, with {:.2f} GB available memory.".format( desc_config.get("device"), desc_config.get("avail_mem") From 9e41a77578cb17da5aae89ee48624774a2cc1837 Mon Sep 17 00:00:00 2001 From: Kaya Unalmis Date: Mon, 13 Apr 2026 22:57:42 -0700 Subject: [PATCH 11/11] . Co-authored-by: Kaya Unalmis --- desc/integrals/bounce_integral.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/desc/integrals/bounce_integral.py b/desc/integrals/bounce_integral.py index 028063adac..d14f209bc9 100644 --- a/desc/integrals/bounce_integral.py +++ b/desc/integrals/bounce_integral.py @@ -299,7 +299,7 @@ def __init__( quad = get_quadrature( leggauss(32), (automorphism_sin, grad_automorphism_sin) ) - elif automorphism is not None: + else: quad = get_quadrature(quad, automorphism) self._quad = jax.lax.stop_gradient(quad) @@ -1473,7 +1473,7 @@ def __init__( quad = get_quadrature( leggauss(32), (automorphism_sin, grad_automorphism_sin) ) - elif automorphism is not None: + else: quad = get_quadrature(quad, automorphism) self._quad = jax.lax.stop_gradient(quad) self._data = {