Skip to content

Commit

Permalink
Merge branch 'main' into python3.13
Browse files Browse the repository at this point in the history
  • Loading branch information
jcapriot authored Nov 5, 2024
2 parents 9fec809 + 93d48ec commit f5e7362
Show file tree
Hide file tree
Showing 16 changed files with 216 additions and 60 deletions.
6 changes: 3 additions & 3 deletions .ci/azure/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ jobs:
- bash: |
# Update latest symlink
cd discretize-docs
rm -f en/latest
ln -s "en/$BRANCH_NAME" en/latest
cd discretize-docs/en
rm -f latest
ln -s "$BRANCH_NAME" latest
displayName: Point Latest to tag
condition: eq(variables.IS_TAG, true)
Expand Down
14 changes: 5 additions & 9 deletions .github/workflows/build_distributions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,6 @@ jobs:

- name: Build wheels
uses: pypa/cibuildwheel@v2.21.3
# env:
# CIBW_SOME_OPTION: value
# ...
# with:
# package-dir: .
# output-dir: wheelhouse
# config-file: "{package}/pyproject.toml"

- uses: actions/upload-artifact@v4
with:
Expand Down Expand Up @@ -63,5 +56,8 @@ jobs:
merge-multiple: true

- uses: pypa/gh-action-pypi-publish@release/v1
# with:
# To test: repository-url: https://test.pypi.org/legacy/
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
skip-existing: true
packages-dir: ./dist/
9 changes: 5 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,24 +61,25 @@ Currently, discretize supports:

Installing
^^^^^^^^^^
**discretize** is on conda-forge
**discretize** is on conda-forge, and is the recommended installation method.

.. code:: shell
conda install -c conda-forge discretize
**discretize** is on pypi
Prebuilt wheels of **discretize** are on pypi for most platforms

.. code:: shell
pip install discretize
To install from source
To install from source, note this requires a `c++` compiler supporting the `c++17` standard.

.. code:: shell
git clone https://github.com/simpeg/discretize.git
python setup.py install
cd discretize
pip install .
Citing discretize
^^^^^^^^^^^^^^^^^
Expand Down
30 changes: 1 addition & 29 deletions discretize/_extensions/meson.build
Original file line number Diff line number Diff line change
@@ -1,34 +1,6 @@
# NumPy include directory
numpy_nodepr_api = ['-DNPY_NO_DEPRECATED_API=NPY_1_22_API_VERSION']
np_dep = dependency('numpy', required: false)
if not np_dep.found()
# For cross-compilation it is often not possible to run the Python interpreter
# in order to retrieve numpy's include directory. It can be specified in the
# cross file instead:
# [properties]
# numpy-include-dir = /abspath/to/host-pythons/site-packages/numpy/core/include
#
# This uses the path as is, and avoids running the interpreter.
incdir_numpy = meson.get_external_property('numpy-include-dir', 'not-given')
if incdir_numpy == 'not-given'
incdir_numpy = run_command(py,
[
'-c',
'''import os
import numpy as np
try:
incdir = os.path.relpath(np.get_include())
except Exception:
incdir = np.get_include()
print(incdir)
'''
],
check: true
).stdout().strip()
endif
inc_np = include_directories(incdir_numpy)
np_dep = declare_dependency(include_directories: inc_np)
endif
np_dep = dependency('numpy')

# Deal with M_PI & friends; add `use_math_defines` to c_args or cpp_args
# Cython doesn't always get this right itself (see, e.g., gh-16800), so
Expand Down
1 change: 1 addition & 0 deletions discretize/base/base_tensor_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,7 @@ def _get_interpolation_matrix(
raise ValueError("Points outside of mesh")
else:
indZeros = np.logical_not(self.is_inside(loc))
loc = loc.copy()
loc[indZeros, :] = np.array([v.mean() for v in self.get_tensor("CC")])

location_type = self._parse_location_type(location_type)
Expand Down
2 changes: 1 addition & 1 deletion discretize/mixins/mpl_mod.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ def plot_slice(
the given normal.
>>> M = discretize.TensorMesh([32, 32, 32])
>>> v = discretize.utils.random_model(M.vnC, seed=789).reshape(-1, order='F')
>>> v = discretize.utils.random_model(M.vnC, random_seed=789).reshape(-1, order='F')
>>> x_slice, y_slice, z_slice = 0.75, 0.25, 0.9
>>> plt.figure(figsize=(7.5, 3))
>>> ax = plt.subplot(131)
Expand Down
25 changes: 25 additions & 0 deletions discretize/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
assert_isadjoint
""" # NOQA D205

import warnings

import numpy as np
import scipy.sparse as sp

Expand Down Expand Up @@ -81,6 +83,23 @@
_happiness_rng = np.random.default_rng()


def _warn_random_test():
stack = inspect.stack()
in_pytest = any(x[0].f_globals["__name__"].startswith("_pytest.") for x in stack)
in_nosetest = any(x[0].f_globals["__name__"].startswith("nose.") for x in stack)

if in_pytest or in_nosetest:
test = "pytest" if in_pytest else "nosetest"
warnings.warn(
f"You are running a {test} without setting a random seed, the results might not be"
"repeatable. For repeatable tests please pass an argument to `random seed` that is"
"not `None`.",
UserWarning,
stacklevel=3,
)
return in_pytest or in_nosetest


def setup_mesh(mesh_type, nC, nDim, random_seed=None):
"""Generate arbitrary mesh for testing.
Expand Down Expand Up @@ -110,6 +129,8 @@ def setup_mesh(mesh_type, nC, nDim, random_seed=None):
A discretize mesh of class specified by the input argument *mesh_type*
"""
if "random" in mesh_type:
if random_seed is None:
_warn_random_test()
rng = np.random.default_rng(random_seed)
if "TensorMesh" in mesh_type:
if "uniform" in mesh_type:
Expand Down Expand Up @@ -649,6 +670,8 @@ def check_derivative(
x0 = mkvc(x0)

if dx is None:
if random_seed is None:
_warn_random_test()
rng = np.random.default_rng(random_seed)
dx = rng.standard_normal(len(x0))

Expand Down Expand Up @@ -867,6 +890,8 @@ def assert_isadjoint(
"""
__tracebackhide__ = True

if random_seed is None:
_warn_random_test()
rng = np.random.default_rng(random_seed)

def random(size, iscomplex):
Expand Down
19 changes: 16 additions & 3 deletions discretize/tree_mesh.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Module containing the TreeMesh implementation."""

import warnings

# ___ ___ ___ ___ ___ ___
# /\ \ /\ \ /\ \ /\ \ /\ \ /\ \
# /::\ \ /::\ \ \:\ \ /::\ \ /::\ \ /::\ \
Expand Down Expand Up @@ -169,7 +171,7 @@ class TreeMesh(
diagonal_balance : bool, optional
Whether to balance cells along the diagonal of the tree during construction.
This will effect all calls to refine the tree.
This will affect all calls to refine the tree.
Examples
--------
Expand Down Expand Up @@ -233,9 +235,20 @@ class TreeMesh(
_items = {"h", "origin", "cell_state"}

# inheriting stuff from BaseTensorMesh that isn't defined in _QuadTree
def __init__(self, h=None, origin=None, diagonal_balance=False, **kwargs):
def __init__(self, h=None, origin=None, diagonal_balance=None, **kwargs):
if "x0" in kwargs:
origin = kwargs.pop("x0")

if diagonal_balance is None:
diagonal_balance = False
warnings.warn(
"In discretize v1.0 the TreeMesh will change the default value of "
"diagonal_balance to True, which will likely slightly change meshes you have"
"previously created. If you need to keep the current behavoir, explicitly set "
"diagonal_balance=False.",
FutureWarning,
stacklevel=2,
)
super().__init__(h=h, origin=origin, diagonal_balance=diagonal_balance)

cell_state = kwargs.pop("cell_state", None)
Expand Down Expand Up @@ -926,7 +939,7 @@ def face_z_divergence(self): # NOQA D102

def point2index(self, locs): # NOQA D102
# Documentation inherited from discretize.base.BaseMesh
return self.get_containing_cell_indexes(locs)
return self.get_containing_cells(locs)

def cell_levels_by_index(self, indices):
"""Fast function to return a list of levels for the given cell indices.
Expand Down
21 changes: 16 additions & 5 deletions discretize/utils/mesh_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
num_types = [int, float]


def random_model(shape, seed=None, anisotropy=None, its=100, bounds=None):
def random_model(
shape, random_seed=None, anisotropy=None, its=100, bounds=None, seed=None
):
"""Create random tensor model.
Creates a random tensor model by convolving a kernel function with a
Expand All @@ -29,7 +31,7 @@ def random_model(shape, seed=None, anisotropy=None, its=100, bounds=None):
----------
shape : (dim) tuple of int
shape of the model.
seed : numpy.random.Generator, int, optional
random_seed : numpy.random.Generator, int, optional
pick which model to produce, prints the seed if you don't choose
anisotropy : numpy.ndarray, optional
this is the kernel that is convolved with the model
Expand All @@ -56,7 +58,7 @@ def random_model(shape, seed=None, anisotropy=None, its=100, bounds=None):
>>> vmin, vmax = 0., 1.
>>> mesh = TensorMesh([h, h])
>>> model = random_model(mesh.shape_cells, seed=4, bounds=[vmin, vmax])
>>> model = random_model(mesh.shape_cells, random_seed=4, bounds=[vmin, vmax])
>>> fig = plt.figure(figsize=(5, 4))
>>> ax = plt.subplot(111)
Expand All @@ -68,8 +70,17 @@ def random_model(shape, seed=None, anisotropy=None, its=100, bounds=None):
if bounds is None:
bounds = [0, 1]

rng = np.random.default_rng(seed)
if seed is None:
if seed is not None:
warnings.warn(
"Deprecated in version 0.11.0. The `seed` keyword argument has been renamed to `random_seed` "
"for consistency across the package. Please update your code to use the new keyword argument.",
FutureWarning,
stacklevel=2,
)
random_seed = seed

rng = np.random.default_rng(random_seed)
if random_seed is None:
print("Using a seed of: ", rng.bit_generator.seed_seq)

if type(shape) in num_types:
Expand Down
11 changes: 8 additions & 3 deletions docs/_static/versions.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@
"url": "https://discretize.simpeg.xyz/en/main/"
},
{
"name": "0.10.0 (stable)",
"version": "v0.10.0",
"url": "https://discretize.simpeg.xyz/en/v0.10.0/",
"name": "0.11.0 (stable)",
"version": "v0.11.0",
"url": "https://discretize.simpeg.xyz/en/v0.11.0/",
"preferred": true
},
{
"name": "0.10.0",
"version": "v0.10.0",
"url": "https://discretize.simpeg.xyz/en/v0.10.0/"
}
]

2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def linkcode_resolve(domain, info):
"icon_links": [
{
"name": "GitHub",
"url": "https://github.com/simpeg/simpeg",
"url": "https://github.com/simpeg/discretize",
"icon": "fab fa-github",
},
{
Expand Down
89 changes: 89 additions & 0 deletions docs/release/0.11.0-notes.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
.. currentmodule:: discretize

.. _0.11.0_notes:

===================================
``discretize`` 0.11.0 Release Notes
===================================

October 24, 2024

This minor release contains many bugfixes and updates related to new package builds.

Numpy 2
-------
`discretize` now fully supports `numpy` 2! It is both built against and tested against `numpy` 2.0. It still
has a minimum required runtime of `numpy` 1.22 though, as building against numpy 2.0 emits ABI compatible calls for
older numpy versions.

Of note to developers, we now require `numpy` 2.0 for building as it makes use of the `numpy-config` tool to locate
the `numpy` include directory.

Python versions
---------------
`discretize` has bumped its minimum supported `python` version to 3.10, and is tested against versions 3.10-3.13. In the
future we intended to stay in line with the minimum `python` version supported by the most recent `numpy` release.


Random Generators
-----------------
`discretize` and its testing utilities now make use of ``numpy.random.RandomGenerator`` to make draws from random
number generators instead of the deprecated ``numpy.random.rand`` functions. These functions now support a new keyword
argument `random_seed` :

* :func:``discretize.tests.setup_mesh`` (only used when ``"random" in mesh_type``)
* :func:``discretize.tests.check_derivative`` (only used when ``dx=None``)
* :func:``discretize.tests.assert_isadjoint``
* :func:``discretize.tests.OrderTest.orderTest`` (only used when ``"random" in mesh_type``)
* :func:``discretize.utils.random_model``

Maintainers of downstream packages should explicitly set seeded generators when using these methods for testing
purposess to ensure reproducibility.


Cell Bounds
-----------
:class:``discretize.TensorMesh`` and :class:``discretize.TreeMesh`` now have a ``cell_bounds`` property that returns the
``(x_min, x_max, y_min, y_max, z_min, z_max)`` of every cell in the mesh at once. Also now the
:class:``discretize.tree_mesh.TreeCell`` has a corresponding ``bounds`` property.


``TreeMesh`` updates
--------------------
You can now query a :class:``discretize.TreeMesh`` for cells contained in the same geometric primitives that are supported
for refining. In addition there is a new :func:``discretize.TreeMesh.refine_plane`` method for refining along a plane.


Contributors
============

* @jcapriot
* @santisoler
* @prisae
* @xiaolongw1223
* @lheagy
* @omid-b

Pull requests
=============

* `#347 <https://github.com/simpeg/discretize/pull/347>`__: Replace deprecated Numpy's `product` by `prod`
* `#351 <https://github.com/simpeg/discretize/pull/351>`__: Replace Slack links for Mattermost links
* `#353 <https://github.com/simpeg/discretize/pull/353>`__: Fix typo in tutorials
* `#354 <https://github.com/simpeg/discretize/pull/354>`__: Update year in LICENSE
* `#356 <https://github.com/simpeg/discretize/pull/356>`__: Expose TreeMesh geometric intersections used for refine functions.
* `#358 <https://github.com/simpeg/discretize/pull/358>`__: Replace hanging CurviMesh in docstring for CurvilinearMesh
* `#360 <https://github.com/simpeg/discretize/pull/360>`__: Update use of `numpy`'s random number generators.
* `#364 <https://github.com/simpeg/discretize/pull/364>`__: Fix slicer re #363
* `#366 <https://github.com/simpeg/discretize/pull/366>`__: Add `TensorMesh.cell_bounds` property
* `#367 <https://github.com/simpeg/discretize/pull/367>`__: Add `TreeCell.bounds` and `TreeMesh.cell_bounds` methods
* `#368 <https://github.com/simpeg/discretize/pull/368>`__: Set minimum to Python 3.10 (and general CI Maintenance)
* `#371 <https://github.com/simpeg/discretize/pull/371>`__: Add version switcher to discretize docs
* `#372 <https://github.com/simpeg/discretize/pull/372>`__: Deploy docs to a new folder named after their tagged version
* `#373 <https://github.com/simpeg/discretize/pull/373>`__: display dev doc banner
* `#374 <https://github.com/simpeg/discretize/pull/374>`__: Bump pydata_sphinx_theme version to 0.15.4
* `#375 <https://github.com/simpeg/discretize/pull/375>`__: Fix caching of internal projection matrices
* `#376 <https://github.com/simpeg/discretize/pull/376>`__: Fix macos-latest build
* `#379 <https://github.com/simpeg/discretize/pull/379>`__: Numpy2.0 updates
* `#380 <https://github.com/simpeg/discretize/pull/380>`__: Create build_distributions.yml
* `#381 <https://github.com/simpeg/discretize/pull/381>`__: 0.11.0 Release Notes
Loading

0 comments on commit f5e7362

Please sign in to comment.