Repository: PMEAL/OpenPNM
Pull request #1120 (2018-10-10 19:10:51)

Add linear_scale parameter to VoronoiFibers


Patch:
diff --git a/openpnm/materials/VoronoiFibers.py b/openpnm/materials/VoronoiFibers.py
index 432cb2113..bd7fb9f25 100644
--- a/openpnm/materials/VoronoiFibers.py
+++ b/openpnm/materials/VoronoiFibers.py
@@ -65,6 +65,14 @@ class VoronoiFibers(Project):
         appropriately set the resolution based on the fiber_radius and the
         shape of the domain so as to remain within memory constraints.
 
+    linear_scale : array_like (len 3)
+        This is applied to the domain size before placing the points and then
+        reversed afterwards and has the effect of introducing anisotropy into
+        an otherwise uniformly distributed point distribution. By default no
+        scaling is applied. Applying [1, 1, 2] will stretch the domain by a
+        factor of 2 in the z-direction and this will have the affect of
+        aligning fibers in the x and y directions once scaling is reversed.
+
     References
     ----------
     This approach to modeling fibrous materials was first presented by
@@ -91,9 +99,20 @@ class VoronoiFibers(Project):
     """
 
     def __init__(self, num_points=None, points=None, shape=[1, 1, 1],
-                 fiber_rad=None, resolution=1e-2, name=None, **kwargs):
+                 fiber_rad=None, resolution=1e-2, name=None,
+                 linear_scale=None, **kwargs):
         super().__init__(name=name)
         shape = np.array(shape)
+        scale_applied = False
+        if linear_scale is not None:
+            if len(linear_scale) != 3:
+                logger.exception(msg='linear_scale must have length 3 ' +
+                                 'to scale each axis')
+            else:
+                ls = np.asarray(linear_scale)
+                shape *= ls
+                scale_applied = True
+#                net['pore.coords'] *= ls
         if (len(shape) != 3) or np.any(shape == 0):
             raise Exception('Only 3D, rectangular shapes are supported')
         if fiber_rad is None:
@@ -105,6 +124,8 @@ class VoronoiFibers(Project):
                                   shape=shape,
                                   name=self.name+'_net',
                                   **kwargs)
+        if scale_applied:
+            net['pore.coords'] /= ls
         net.fiber_rad = fiber_rad
         net.resolution = resolution
         del_geom = DelaunayGeometry(project=self,
@@ -112,6 +133,7 @@ class VoronoiFibers(Project):
                                     pores=net.pores('delaunay'),
                                     throats=net.throats('delaunay'),
                                     name=self.name+'_del')
+
         VoronoiGeometry(project=self,
                         network=net,
                         pores=net.pores('voronoi'),
diff --git a/openpnm/topotools/topotools.py b/openpnm/topotools/topotools.py
index 798775b2f..961c559b7 100644
--- a/openpnm/topotools/topotools.py
+++ b/openpnm/topotools/topotools.py
@@ -1043,9 +1043,9 @@ def label_faces(network, tol=0.0, label='surface'):
     yspan = ymax - ymin
     zmin, zmax = sp.amin(crds[:, 2]), sp.amax(crds[:, 2])
     zspan = zmax - zmin
-    network['pore.back'] = (crds[:, 0] >= (1-tol)*xmax) * Psurf
-    network['pore.right'] = (crds[:, 1] >= (1-tol)*ymax) * Psurf
-    network['pore.top'] = (crds[:, 2] >= (1-tol)*zmax) * Psurf
+    network['pore.back'] = (crds[:, 0] >= (xmax - tol*xspan)) * Psurf
+    network['pore.right'] = (crds[:, 1] >= (ymax - tol*yspan)) * Psurf
+    network['pore.top'] = (crds[:, 2] >= (zmax - tol*zspan)) * Psurf
     network['pore.front'] = (crds[:, 0] <= (xmin + tol*xspan)) * Psurf
     network['pore.left'] = (crds[:, 1] <= (ymin + tol*yspan)) * Psurf
     network['pore.bottom'] = (crds[:, 2] <= (zmin + tol*zspan)) * Psurf


Test patch:
diff --git a/tests/unit/materials/VoronoiFibersTest.py b/tests/unit/materials/VoronoiFibersTest.py
index 8547d0920..607a0eb3f 100644
--- a/tests/unit/materials/VoronoiFibersTest.py
+++ b/tests/unit/materials/VoronoiFibersTest.py
@@ -65,7 +65,7 @@ class VoronoiTest:
         plt.close('all')
 
     def test_vertex_dimension(self):
-        prj = op.materials.VoronoiFibers(num_points=100,
+        prj = op.materials.VoronoiFibers(num_points=50,
                                          fiber_rad=0.2,
                                          resolution=0.1,
                                          shape=[3, 2, 1],
@@ -83,6 +83,34 @@ class VoronoiTest:
         assert del_geom.vertex_dimension(B1, B2, 'minmax') == \
             [0.0, 3.0, 0.0, 2.0, 0.0, 1.0]
 
+    def test_linear_scale(self):
+        prj = op.materials.VoronoiFibers(num_points=50,
+                                         fiber_rad=0.2,
+                                         resolution=0.1,
+                                         shape=[2, 2, 2],
+                                         name='test3',
+                                         linear_scale=[1, 1, 2])
+        net = prj.network
+        del_geom = prj.geometries()['test3_del']
+        B1 = net.pores(['top', 'delaunay'], mode='xnor')
+        B2 = net.pores(['bottom', 'delaunay'], mode='xnor')
+        assert del_geom.vertex_dimension(B1, B2, 'volume') == 8.0
+        assert del_geom.vertex_dimension(B1, B2, 'length') == 2.0
+
+    def test_linear_scale_wrong_shape(self):
+        prj = op.materials.VoronoiFibers(num_points=50,
+                                         fiber_rad=0.2,
+                                         resolution=0.1,
+                                         shape=[2, 2, 2],
+                                         name='test4',
+                                         linear_scale=[1, 1])
+        net = prj.network
+        del_geom = prj.geometries()['test4_del']
+        B1 = net.pores(['top', 'delaunay'], mode='xnor')
+        B2 = net.pores(['bottom', 'delaunay'], mode='xnor')
+        assert del_geom.vertex_dimension(B1, B2, 'volume') == 8.0
+        assert del_geom.vertex_dimension(B1, B2, 'length') == 2.0
+
 
 if __name__ == '__main__':
 
diff --git a/tests/unit/topotools/TopotoolsTest.py b/tests/unit/topotools/TopotoolsTest.py
index 067423ca3..f0479890f 100644
--- a/tests/unit/topotools/TopotoolsTest.py
+++ b/tests/unit/topotools/TopotoolsTest.py
@@ -37,6 +37,19 @@ class TopotoolsTest:
         assert net.num_pores('top') == 9
         assert net.num_pores('bottom') == 9
 
+    def test_label_faces_tol(self):
+        net = op.network.Cubic(shape=[3, 3, 3], spacing=1, connectivity=6)
+        net.clear(mode='labels')
+        net['pore.coords'] += np.array([5, 5, 5])
+        topotools.label_faces(network=net, tol=0.2)
+        assert net.num_pores('surface') == 26
+        assert net.num_pores('left') == 9
+        assert net.num_pores('right') == 9
+        assert net.num_pores('front') == 9
+        assert net.num_pores('back') == 9
+        assert net.num_pores('top') == 9
+        assert net.num_pores('bottom') == 9
+
     def test_find_surface_pores(self):
         from skimage.morphology import ball
         net = op.network.CubicTemplate(template=ball(3), spacing=1)