Skip to content

Commit

Permalink
Merge branch 'dev' into fixing-basic-usage-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
jgostick committed Nov 22, 2023
2 parents be976f3 + 8e320be commit 7bb0564
Show file tree
Hide file tree
Showing 20 changed files with 119 additions and 51 deletions.
1 change: 1 addition & 0 deletions .github/workflows/examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ jobs:
pip install \
-r requirements.txt \
-r requirements/tests.txt
pip install pypardiso
- name: Running tests
run:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/gh-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ jobs:
run: |
pip install -r requirements.txt
pip install -r requirements/docs.txt
pip install pypardiso
- name: Build the documentation
run: |
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ jobs:
-r requirements.txt \
-r requirements/tests.txt
- name: Install pypardiso on non-macOS
if: (matrix.os != 'macos-latest')
run: |
pip install pypardiso
- name: Running tests
run:
pytest . --color=yes
5 changes: 5 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ jobs:
-r requirements.txt \
-r requirements/tests.txt
- name: Install pypardiso on non-macOS
if: (matrix.os != 'macos-latest')
run: |
pip install pypardiso
- name: Disable numba JIT for codecov to include jitted methods
if: (matrix.python-version == 3.9) && (matrix.os == 'ubuntu-latest')
run: |
Expand Down
27 changes: 14 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,41 @@
# Overview of OpenPNM

*OpenPNM* is a comprehensive framework for performing pore network simulations of porous materials.
OpenPNM is a comprehensive framework for performing pore network simulations of porous materials.

## More Information

For more details about the package can be found in the [on-line documentation](https://openpnm.org)
For more details about the package can be found in the [online documentation](https://openpnm.org)

## Installation and Requirements

### Preferred method
The preferred way of installing OpenPNM is through [Anaconda Cloud](https://anaconda.org/conda-forge/openpnm) using:
### [pip](https://pypi.org/project/openpnm/)
OpenPNM can be installed using `pip` by running the following command in a terminal:

```
conda install -c conda-forge openpnm
```shell
pip install openpnm
```

### Alternative method
OpenPNM can also be installed from the [Python Package Index](https://pypi.org/project/openpnm/) using:
### [conda-forge](https://anaconda.org/conda-forge/openpnm)
OpenPNM can also be installed from the [conda-forge](https://anaconda.org/conda-forge/openpnm) repository using:

```
pip install openpnm
conda install -c conda-forge openpnm
```

However, we don't recommend installing using `pip` since `pypardiso`, which is a blazing fast direct solver, is not available for Windows users who use Python 3.7+.
> [!WARNING]
> For compatibility with ARM64 architecture, we removed `pypardiso` as a hard dependency. However, we still strongly recommend that non-macOS users (including users of older Macs with an Intel CPU) manually install `pypardiso` via `pip install pypardiso` or `conda install -c conda-forge pypardiso`, otherwise OpenPNM simulations will be very slow.
### For developers
For developers who intend to change the source code or contribute to OpenPNM, the source code can be downloaded from [Github](https://github.com/pmeal/OpenPNM/) and installed by running:
For developers who intend to change the source code or contribute to OpenPNM, the source code can be downloaded from [Github](https://github.com/PMEAL/OpenPNM/) and installed by running:

```
pip install -e 'path/to/downloaded/files'
```

The advantage to installing from the source code is that you can edit the files and have access to your changes each time you import *OpenPNM*.
The advantage to installing from the source code is that you can edit the files and have access to your changes each time you import OpenPNM.

OpenPNM requires the *Scipy Stack* (Numpy, Scipy, Matplotlib, etc), which is most conveniently obtained by installing the [Anaconda Distribution](https://conda.io/docs/user-guide/install/download.html).
OpenPNM requires the Scipy Stack (Numpy, Scipy, Matplotlib, etc), which is most conveniently obtained by installing the [Anaconda Distribution](https://www.anaconda.com/download/).

## Asking Questions and Getting Help

Expand Down
43 changes: 26 additions & 17 deletions openpnm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,34 @@
"""

from . import _skgraph
from . import utils
from . import core
from . import models
from . import topotools
from . import network
from . import phase
from . import algorithms
from . import solvers
from . import integrators
from . import io
from . import contrib
from . import visualization

from .utils import Workspace, Project
import logging

from rich.logging import RichHandler

FORMAT = "%(message)s"
logging.basicConfig(
format=FORMAT, datefmt="[%X]", handlers=[RichHandler(rich_tracebacks=True)]
)

import numpy as _np

from . import (
_skgraph,
algorithms,
contrib,
core,
integrators,
io,
models,
network,
phase,
solvers,
topotools,
utils,
visualization,
)
from .utils import Project, Workspace

_np.seterr(divide='ignore', invalid='ignore')

__version__ = utils._get_version()

utils._setup_logger_rich()
2 changes: 1 addition & 1 deletion openpnm/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '3.2.1.dev3'
__version__ = '3.3.0.dev5'
2 changes: 1 addition & 1 deletion openpnm/_skgraph/generators/_voronoi_delaunay_dual.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def voronoi_delaunay_dual(
points=points,
shape=shape,
reflect=reflect,
f=1,
f=f,
)

# Generate mask to remove any dims with all 0's
Expand Down
2 changes: 1 addition & 1 deletion openpnm/_skgraph/generators/tools/_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def parse_points(shape, points, reflect=False, f=1):
"""
# Deal with input arguments
shape = np.array(shape, dtype=int)
shape = np.array(shape, dtype=float)
if isinstance(points, int):
points = generate_base_points(num_points=points,
domain_size=shape,
Expand Down
6 changes: 5 additions & 1 deletion openpnm/models/_doctxt.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from matplotlib._docstring import Substitution
try:
from matplotlib._docstring import Substitution
except ModuleNotFoundError:
from matplotlib.docstring import Substitution



__all__ = [
Expand Down
5 changes: 4 additions & 1 deletion openpnm/models/geometry/_geodocs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from matplotlib._docstring import Substitution
try:
from matplotlib._docstring import Substitution
except ModuleNotFoundError:
from matplotlib.docstring import Substitution


__all__ = [
Expand Down
11 changes: 11 additions & 0 deletions openpnm/models/misc/_neighbor_lookups.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ def from_neighbor_throats(target, prop, mode='min', ignore_nans=True):
neighboring throats
'mean' Returns the value of the mean property of the
neighboring throats
'sum' Returns the sum of the property of the neighboring
throats
=========== =====================================================
Returns
Expand Down Expand Up @@ -69,6 +71,11 @@ def from_neighbor_throats(target, prop, mode='min', ignore_nans=True):
if ignore_nans:
np.subtract.at(counts, im.row, nans[im.col])
values = values/counts
if mode == 'sum':
if ignore_nans:
data[nans] = 0
values = np.zeros((network.Np, ))
np.add.at(values, im.row, data[im.col])
return values


Expand Down Expand Up @@ -98,6 +105,8 @@ def from_neighbor_pores(target, prop, mode='min', ignore_nans=True):
neighboring pores
'mean' Returns the value of the mean property of the
neighboring pores
'sum' Returns the sum of the property of the neighrboring
pores
=========== =====================================================
ignore_nans : bool (default is ``True``)
Expand All @@ -122,6 +131,8 @@ def from_neighbor_pores(target, prop, mode='min', ignore_nans=True):
value = np.amax(pvalues, axis=1)
if mode == 'mean':
value = np.mean(pvalues, axis=1)
if mode == 'sum':
value = np.sum(pvalues, axis=1)
except np.AxisError: # Handle case of empty pvalues
value = []
return np.array(value)
6 changes: 5 additions & 1 deletion openpnm/models/phase/_phasedocs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from matplotlib._docstring import Substitution
try:
from matplotlib._docstring import Substitution
except ModuleNotFoundError:
from matplotlib.docstring import Substitution


__all__ = [
'_phasedocs',
Expand Down
15 changes: 9 additions & 6 deletions openpnm/phase/_phase.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,16 @@ def __getitem__(self, key):
if element + '.' + prop in self.keys():
vals = super().__getitem__(element + '.' + prop)
else: # If above are not triggered then try to interpolate
if self.settings['auto_interpolate']:
if (element == 'pore') and ('throat.'+prop not in self.keys()):
try:
if self.settings['auto_interpolate']:
if (element == 'pore') and ('throat.'+prop not in self.keys()):
raise KeyError(key)
elif (element == 'throat') and ('pore.'+prop not in self.keys()):
raise KeyError(key)
vals = self.interpolate_data(element + '.' + prop)
else:
raise KeyError(key)
elif (element == 'throat') and ('pore.'+prop not in self.keys()):
raise KeyError(key)
vals = self.interpolate_data(element + '.' + prop)
else:
except AttributeError:
raise KeyError(key)

# Finally get locs
Expand Down
6 changes: 4 additions & 2 deletions openpnm/solvers/_pardiso.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from pypardiso import spsolve
from scipy.sparse import csc_matrix, csr_matrix

from openpnm.solvers import DirectSolver
from scipy.sparse import csr_matrix, csc_matrix

__all__ = ['PardisoSpsolve']

Expand All @@ -10,6 +10,8 @@ class PardisoSpsolve(DirectSolver):

def solve(self, A, b, **kwargs):
"""Solves the given linear system of equations Ax=b."""
from pypardiso import spsolve

if not isinstance(A, (csr_matrix, csc_matrix)):
A = A.tocsr()
return (spsolve(A, b), 0)
16 changes: 15 additions & 1 deletion openpnm/utils/_workspace.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import pickle
import re
import sys
from datetime import datetime
from uuid import uuid4

Expand Down Expand Up @@ -39,7 +40,20 @@ class WorkspaceSettings(SettingsAttr):
may be unable to continue running.
======= ==============================================================
"""
default_solver = 'PardisoSpsolve'
# Pardiso requires MKL, which is not available on new Apple chips
if sys.platform == 'darwin':
default_solver = 'ScipySpsolve'
else:
try:
import pypardiso
default_solver = 'PardisoSpsolve'
except ImportError:
default_solver = 'ScipySpsolve'
msg = (
'PARDISO solver not installed, run `pip install pypardiso`. '
'Otherwise, simulations will be slow. Apple M chips not supported.'
)
logger.error(msg)

@property
def loglevel(self):
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 3.2.1.dev3
current_version = 3.3.0.dev5
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\.(?P<release>\D+)(?P<build>\d+)?
serialize = {major}.{minor}.{patch}.{release}{build}

Expand Down
8 changes: 4 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import os
import sys
import codecs
import os
import os.path
import sys
from distutils.util import convert_path
from setuptools import setup, find_packages

from setuptools import find_packages, setup

sys.path.append(os.getcwd())
ver_path = convert_path('openpnm/__version__.py')
Expand Down Expand Up @@ -59,7 +60,6 @@ def get_version(rel_path):
'numpy',
'pandas',
'pyamg',
'pypardiso',
'rich',
'scikit-image',
'scipy',
Expand Down
5 changes: 5 additions & 0 deletions tests/unit/algorithms/SolversTest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import sys

import numpy as np
import numpy.testing as nt
import pytest

import openpnm as op


Expand All @@ -25,6 +29,7 @@ def test_scipy_spsolve(self):
x = self.alg['pore.x']
nt.assert_allclose(x.mean(), 0.624134, rtol=1e-5)

@pytest.mark.skipif(sys.platform == 'darwin', reason="Pardiso not available on arm64")
def test_pardiso_spsolve(self):
solver = op.solvers.PardisoSpsolve()
self.alg.run(solver=solver)
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/algorithms/TransientMultiPhysicsTest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import numpy as np
import numpy.testing as nt

import openpnm as op
import openpnm.models.geometry.diffusive_size_factors as gd
import openpnm.models.physics as pm
Expand Down Expand Up @@ -48,7 +49,6 @@ def setup_class(self):
"cache_A": False,
"cache_b": False
}
self.pardiso = op.solvers.PardisoSpsolve()
self.rk45 = op.integrators.ScipyRK45(verbose=True)

# First algorithm, transient fourier conduction
Expand Down

0 comments on commit 7bb0564

Please sign in to comment.