Skip to content

Commit

Permalink
Merge pull request #2893 from PMEAL/adjust_sa_model
Browse files Browse the repository at this point in the history
Adjusted surface area model to accept lower limit (amin), defaults to 0 #enh
  • Loading branch information
jgostick authored Jan 27, 2024
2 parents 0273ab4 + 7c45c22 commit c24a6ae
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 8 deletions.
44 changes: 36 additions & 8 deletions openpnm/models/geometry/pore_surface_area/_funcs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import numpy as _np
from openpnm.models.geometry import _geodocs
import logging


logger = logging.getLogger(__name__)


__all__ = ["sphere",
Expand All @@ -13,7 +17,8 @@
def sphere(
network,
pore_diameter='pore.diameter',
throat_cross_sectional_area='throat.cross_sectional_area'
throat_cross_sectional_area='throat.cross_sectional_area',
amin=0,
):
r"""
Calculates internal surface area of pore bodies assuming they are spheres,
Expand All @@ -24,6 +29,8 @@ def sphere(
%(network)s
%(Dp)s
%(Act)s
amin : float
The lower limit for surface area, useful for preventing
Returns
-------
Expand All @@ -42,15 +49,19 @@ def sphere(
Tca = network[throat_cross_sectional_area]
_np.subtract.at(value, network.conns[:, 0], Tca)
_np.subtract.at(value, network.conns[:, 1], Tca)
value = _np.clip(value, 1e-12, _np.inf)
if amin is not None:
value = _np.clip(value, amin, _np.inf)
elif _np.any(value < 0):
logger.warn('Negative pore surface areas found')
return value


@_geodocs
def circle(
network,
pore_diameter='pore.diameter',
throat_cross_sectional_area='throat.cross_sectional_area'
throat_cross_sectional_area='throat.cross_sectional_area',
amin=0,
):
r"""
Calculates internal surface area of pore bodies assuming they are
Expand All @@ -61,6 +72,8 @@ def circle(
%(network)s
%(Dp)s
%(Act)s
amin : float
The lower limit for surface area, useful for preventing
Returns
-------
Expand All @@ -73,14 +86,18 @@ def circle(
Tca = network[throat_cross_sectional_area]
_np.subtract.at(value, network.conns[:, 0], Tca)
_np.subtract.at(value, network.conns[:, 1], Tca)
value = _np.clip(value, 1e-12, _np.inf)
if amin is not None:
value = _np.clip(value, amin, _np.inf)
elif _np.any(value < 0):
logger.warn('Negative pore surface areas found')
return value


def cube(
network,
pore_diameter='pore.diameter',
throat_cross_sectional_area='throat.cross_sectional_area'
throat_cross_sectional_area='throat.cross_sectional_area',
amin=0,
):
r"""
Calculates internal surface area of pore bodies assuming they are cubes
Expand All @@ -91,6 +108,8 @@ def cube(
%(network)s
%(Dp)s
%(Act)s
amin : float
The lower limit for surface area, useful for preventing
Returns
-------
Expand All @@ -101,14 +120,18 @@ def cube(
Tca = network[throat_cross_sectional_area]
_np.subtract.at(value, network.conns[:, 0], Tca)
_np.subtract.at(value, network.conns[:, 1], Tca)
value = _np.clip(value, 1e-12, _np.inf)
if amin is not None:
value = _np.clip(value, amin, _np.inf)
elif _np.any(value < 0):
logger.warn('Negative pore surface areas found')
return value


def square(
network,
pore_diameter='pore.diameter',
throat_cross_sectional_area='throat.cross_sectional_area'
throat_cross_sectional_area='throat.cross_sectional_area',
amin=0,
):
r"""
Calculates internal surface area of pore bodies assuming they are
Expand All @@ -119,6 +142,8 @@ def square(
%(network)s
%(Dp)s
%(Act)s
amin : float
The lower limit for surface area, useful for preventing
Returns
-------
Expand All @@ -129,5 +154,8 @@ def square(
Tca = network[throat_cross_sectional_area]
_np.subtract.at(value, network.conns[:, 0], Tca)
_np.subtract.at(value, network.conns[:, 1], Tca)
value = _np.clip(value, 1e-12, _np.inf)
if amin is not None:
value = _np.clip(value, amin, _np.inf)
elif _np.any(value < 0):
logger.warn('Negative pore surface areas found')
return value
17 changes: 17 additions & 0 deletions tests/unit/models/geometry/PoreSurfaceAreaTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import openpnm.models.geometry.pore_surface_area as mods
import numpy as np
from numpy.testing import assert_allclose
import pytest


class PoreSurfaceAreaTest:
Expand Down Expand Up @@ -69,6 +70,22 @@ def test_circle_multi_geom(self):
assert_allclose(a, b)
assert_allclose(c, d)

def test_negative_surface_area(self):
pn = op.network.Cubic([2, 1, 1])
pn.add_model_collection(op.models.collections.geometry.circles_and_rectangles)
pn.regenerate_models()
pn.add_model(propname='pore.surface_area', model=op.models.geometry.pore_surface_area.circle)
pn['throat.cross_sectional_area'] = 100
pn.regenerate_models('pore.surface_area@all')
assert np.all(pn['pore.surface_area'] == 0)
with pytest.warns():
pn.add_model(
propname='pore.surface_area',
model=op.models.geometry.pore_surface_area.circle,
amin=None,
)
assert np.all(pn['pore.surface_area'] < 0)


if __name__ == '__main__':

Expand Down

0 comments on commit c24a6ae

Please sign in to comment.