Repository: PMEAL/OpenPNM
Pull request #1730 (2020-10-31 14:29:11)

stitch_pores to join disconnted pores within an existing network
fixes issues #1729


Patch:
diff --git a/openpnm/network/DelaunayVoronoiDual.py b/openpnm/network/DelaunayVoronoiDual.py
index 109d71058..b79d3d9d3 100644
--- a/openpnm/network/DelaunayVoronoiDual.py
+++ b/openpnm/network/DelaunayVoronoiDual.py
@@ -144,8 +144,11 @@ class DelaunayVoronoiDual(GenericNetwork):
         self['throat.interconnect'][Ts] = True
 
         # Trim all pores that lie outside of the specified domain
-        self._trim_external_pores(shape=shape)
-        self._label_faces()
+        if self.settings['trim'] == False:
+            pass
+        else:
+            self._trim_external_pores(shape=shape)
+            self._label_faces()
 
     @property
     def tri(self):
diff --git a/openpnm/topotools/__init__.py b/openpnm/topotools/__init__.py
index 1c5e67510..c64bc983a 100644
--- a/openpnm/topotools/__init__.py
+++ b/openpnm/topotools/__init__.py
@@ -28,6 +28,7 @@ from .topotools import reflect_base_points
 from .topotools import rotate_coords
 from .topotools import shear_coords
 from .topotools import stitch
+from .topotools import stitch_pores
 from .topotools import subdivide
 from .topotools import template_cylinder_annulus
 from .topotools import template_sphere_shell
diff --git a/openpnm/topotools/topotools.py b/openpnm/topotools/topotools.py
index f8e17cf8a..70592262b 100644
--- a/openpnm/topotools/topotools.py
+++ b/openpnm/topotools/topotools.py
@@ -2,7 +2,7 @@ import numpy as np
 import scipy as sp
 import scipy.ndimage as spim
 from scipy.sparse import csgraph
-from scipy.spatial import ConvexHull
+from scipy.spatial import ConvexHull, delaunay_plot_2d
 from openpnm.utils import logging, Workspace
 logger = logging.getLogger(__name__)
 ws = Workspace()
@@ -836,6 +836,46 @@ def stitch(network, donor, P_network, P_donor, method='nearest',
             del ws[sim.name]
 
 
+def stitch_pores(network, pores1, pores2, mode='gabriel'):
+    r"""
+    Stitches together pores in a network with disconnected clusters
+
+    Parameter
+    ---------
+    network : OpenPNM Network
+        The network to operate upon
+    pores1 and pores2: array_like
+        The pore indices of the disconnected clusters to be joined
+    mode : str
+        Dictates which tesselation method is used to identify which pores to
+        stitch together.  Options are 'gabriel' (default) or 'delaunay'.
+
+    Returns
+    -------
+    None
+        The network is operated on 'in-place' so nothing is returned.
+
+    """
+    from openpnm.network import Delaunay, Gabriel
+    pores1 = network._parse_indices(pores1)
+    pores2 = network._parse_indices(pores2)
+    C1 = network.coords[pores1, :]
+    C2 = network.coords[pores2, :]
+    crds = np.vstack((C1, C2))
+    if mode == 'delaunay':
+        net = Delaunay(points=crds, settings={'trim': False})
+    if mode == 'gabriel':
+        net = Gabriel(points=crds, settings={'trim': False})
+    net.set_label(pores=range(len(pores1)), label='pore.one')
+    net.set_label(pores=range(len(pores2)), label='pore.two')
+    Ts = net.find_neighbor_throats(pores=net.pores('one'), mode='xor')
+    conns = net.conns[Ts]
+    mapped_conns = np.vstack((pores1[conns[:, 0]],
+                              pores2[conns[:, 1] - len(pores1)])).T
+    mapped_conns = np.sort(mapped_conns, axis=1)
+    extend(network=network, conns=mapped_conns, labels='stitched')
+
+
 def connect_pores(network, pores1, pores2, labels=[], add_conns=True):
     r'''
     Returns the possible connections between two groups of pores, and optionally


Test patch:
diff --git a/tests/unit/topotools/TopotoolsTest.py b/tests/unit/topotools/TopotoolsTest.py
index b2972f8a3..cfb5266f5 100644
--- a/tests/unit/topotools/TopotoolsTest.py
+++ b/tests/unit/topotools/TopotoolsTest.py
@@ -414,6 +414,28 @@ class TopotoolsTest:
         dims = op.topotools.dimensionality(pn)
         assert np.allclose(dims, np.array([False, False, True]))
 
+    def test_stitch_pores(self):
+        np.random.seed(0)
+        pts = np.random.rand(100, 3)
+        pn = op.network.Delaunay(points=pts)
+        Ps = (pn.coords[:, 0] > 0.3) * (pn.coords[:, 0] < 0.6)
+        assert pn.Np == 100
+        op.topotools.trim(network=pn, pores=Ps)
+        assert pn.Np == 73
+        pores1 = pn.coords[:, 0] < 0.3
+        pores2 = pn.coords[:, 0] > 0.6
+        assert pn.Nt == 352
+        op.topotools.stitch_pores(network=pn,
+                                  pores1=pores1,
+                                  pores2=pores2, mode='gabriel')
+        assert pn.Nt == 373
+        op.topotools.trim(network=pn, throats=pn.throats('stitched'))
+        assert pn.Nt == 352
+        op.topotools.stitch_pores(network=pn,
+                                  pores1=pores1,
+                                  pores2=pores2, mode='delaunay')
+        assert pn.Nt == 436
+
 
 if __name__ == '__main__':