Repository: PMEAL/OpenPNM
Pull request #1167 (2018-12-19 04:07:23)

Geometry instantiation defaults to all pores and throats
This is in response to issue #1134.  Pretty trivial, but would make life a bit easier.


Patch:
diff --git a/openpnm/core/Subdomain.py b/openpnm/core/Subdomain.py
index 7db7fc911..1f5399d96 100644
--- a/openpnm/core/Subdomain.py
+++ b/openpnm/core/Subdomain.py
@@ -15,24 +15,15 @@ class Subdomain(Base):
     +---------------------+---------------------------------------------------+
     | Methods             | Description                                       |
     +=====================+===================================================+
-    | ``add_locations``   | Specified which pores and throats the object      |
+    | ``_add_locations``  | Specified which pores and throats the object      |
     |                     | should be assigned to                             |
     +---------------------+---------------------------------------------------+
-    | ``drop_locations``  | Removes the object from the specified pores and   |
+    | ``_drop_locations`` | Removes the object from the specified pores and   |
     |                     | throats                                           |
     +---------------------+---------------------------------------------------+
-    | ``_get_boss``       | Geomtry and Physics objects are subservient to    |
-    |                     | Network and Phase objects, respectively, so this  |
-    |                     | method returns a handle to the appropriate *boss* |
+    | ``_set_locations``  | The actual general method called by the above    |
     +---------------------+---------------------------------------------------+
 
-    Also listed above is a hidden method that might be useful.  The act of
-    assign a Subdomain object to a subset of pores or throats basically amounts
-    to creating a list in the *boss* object with the Subdomain's name, like
-    ``'pore.geo_1'``, with True values where ``geo_1`` applies and False
-    elsewhere.  Changing the locations of objects is just a matter of changing
-    the locations of the True's and False's.
-
     The Project object has two methods, ``check_geometry_health`` and
     ``check_physics_health`` that look to make sure all locations are assigned
     to one and only one Geometry and/or Physics.
@@ -72,7 +63,7 @@ class Subdomain(Base):
                                 hit + ' is already defined')
         super().__setitem__(key, value)
 
-    def add_locations(self, pores=[], throats=[]):
+    def _add_locations(self, pores=[], throats=[]):
         r"""
         Adds associations between an object and its boss object at the
         given pore and/or throat locations.
@@ -97,7 +88,7 @@ class Subdomain(Base):
         if len(throats) > 0:
             self._set_locations(element='throat', indices=throats, mode='add')
 
-    def drop_locations(self, pores=[], throats=[], complete=False):
+    def _drop_locations(self, pores=[], throats=[]):
         r"""
         Removes association between an objectx and its boss object at the
         given pore and/or throat locations.
@@ -108,10 +99,6 @@ class Subdomain(Base):
             The pore and/or throat locations from which the association should
             be removed.  These indices refer to the full domain.
 
-        complete : boolean (default is ``False``)
-            If ``True`` then *all* pore and throat associations are removed
-            along with any trace that the objects were associated.
-
         Notes
         -----
         For *Physics* objects, the boss is the *Phase* with which it was
@@ -121,17 +108,12 @@ class Subdomain(Base):
         boss = self.project.find_full_domain(self)
         pores = boss._parse_indices(pores)
         throats = boss._parse_indices(throats)
-        if complete:
-            pores = boss.pores(self.name)
-            throats = boss.throats(self.name)
         if len(pores) > 0:
-            self._set_locations(element='pore', indices=pores, mode='drop',
-                                complete=complete)
+            self._set_locations(element='pore', indices=pores, mode='drop')
         if len(throats) > 0:
-            self._set_locations(element='throat', indices=throats, mode='drop',
-                                complete=complete)
+            self._set_locations(element='throat', indices=throats, mode='drop')
 
-    def _set_locations(self, element, indices, mode, complete=False):
+    def _set_locations(self, element, indices, mode):
         r"""
         This private method is called by ``set_locations`` and
         ``remove_locations`` as needed.
@@ -171,7 +153,4 @@ class Subdomain(Base):
         # Remove label from boss if ALL locations are removed
         if mode == 'drop':
             if ~np.any(boss[element+'.'+self.name]):
-                if complete:
-                    del boss[element+'.'+self.name]
-                else:
-                    boss[element+'.'+self.name] = False
+                boss[element+'.'+self.name] = False
diff --git a/openpnm/geometry/GenericGeometry.py b/openpnm/geometry/GenericGeometry.py
index 96017364a..a6c3aaee1 100644
--- a/openpnm/geometry/GenericGeometry.py
+++ b/openpnm/geometry/GenericGeometry.py
@@ -68,7 +68,7 @@ class GenericGeometry(Subdomain, ModelsMixin):
 
     """
 
-    def __init__(self, network=None, project=None, pores=[], throats=[],
+    def __init__(self, network=None, project=None, pores=None, throats=None,
                  settings={}, **kwargs):
         # Define some default settings
         self.settings.update({'prefix': 'geo'})
@@ -88,4 +88,9 @@ class GenericGeometry(Subdomain, ModelsMixin):
         if network:
             network['pore.'+self.name] = False
             network['throat.'+self.name] = False
-            self.add_locations(pores=pores, throats=throats)
+            if (pores is None) and (throats is None):
+                logger.info('No pores and throats given, assigning ' +
+                            self.name + ' to entire domain')
+                pores = network.Ps
+                throats = network.Ts
+            self._add_locations(pores=pores, throats=throats)
diff --git a/openpnm/physics/GenericPhysics.py b/openpnm/physics/GenericPhysics.py
index 0322cccaf..a004ee3ce 100644
--- a/openpnm/physics/GenericPhysics.py
+++ b/openpnm/physics/GenericPhysics.py
@@ -47,10 +47,18 @@ class GenericPhysics(Subdomain, ModelsMixin):
 
         super().__init__(project=project, **kwargs)
 
-        if phase is not None:
-            phase['pore.'+self.name] = False
-            phase['throat.'+self.name] = False
-        if geometry is not None:
-            Ps = network.pores(geometry.name)
-            Ts = network.throats(geometry.name)
-            self.add_locations(pores=Ps, throats=Ts)
+        network = self.project.network
+        if network:
+            if phase is None:
+                logger.warning('No Phase provided, ' + self.name +
+                               ' will not be associated with a phase')
+            else:
+                phase['pore.'+self.name] = False
+                phase['throat.'+self.name] = False
+            if geometry is None:
+                logger.warning('No Geometry provided, ' + self.name +
+                               'will not be associated with any locations')
+            else:
+                Ps = network.pores(geometry.name)
+                Ts = network.throats(geometry.name)
+                self._add_locations(pores=Ps, throats=Ts)
diff --git a/openpnm/physics/Standard.py b/openpnm/physics/Standard.py
index a6ed27cc6..3a762aace 100644
--- a/openpnm/physics/Standard.py
+++ b/openpnm/physics/Standard.py
@@ -43,15 +43,8 @@ class Standard(GenericPhysics):
             else:
                 project = network.project
 
-        super().__init__(project=project, **kwargs)
-
-        if phase is not None:
-            phase['pore.'+self.name] = False
-            phase['throat.'+self.name] = False
-        if geometry is not None:
-            Ps = network.pores(geometry.name)
-            Ts = network.throats(geometry.name)
-            self.add_locations(pores=Ps, throats=Ts)
+        super().__init__(project=project, phase=phase, geometry=geometry,
+                         **kwargs)
 
         self.add_model(propname='throat.flow_shape_factors',
                        model=mods.flow_shape_factors.ball_and_stick)
diff --git a/openpnm/utils/Project.py b/openpnm/utils/Project.py
index 7d43e466d..6bc95ebc8 100644
--- a/openpnm/utils/Project.py
+++ b/openpnm/utils/Project.py
@@ -512,7 +512,8 @@ class Project(list):
         if objtype.startswith('net'):
             obj = openpnm.network.GenericNetwork(project=self, name=name)
         elif objtype.startswith('geo'):
-            obj = openpnm.geometry.GenericGeometry(project=self, name=name)
+            obj = openpnm.geometry.GenericGeometry(project=self, name=name,
+                                                   pores=[], throats=[])
         elif objtype.startswith('pha'):
             obj = openpnm.phases.GenericPhase(project=self, name=name)
         elif objtype.startswith('phy'):


Test patch:
diff --git a/pytest.ini b/pytest.ini
index 3edde03b2..22478befa 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -2,6 +2,7 @@
 python_files = *.py
 python_classes = *Test
 python_functions = test_*
+filterwarnings = ignore:.*U.*mode is deprecated:DeprecationWarning
 pep8maxlinelength = 90
 pep8ignore =
     E127    # continuation line over-indented
@@ -18,6 +19,7 @@ addopts =
     --ignore=setup.py
     --ignore=test_requirements.txt
     --ignore=requirements.txt
+    -p no:warnings
 
 norecursedirs =
     .git
diff --git a/tests/unit/core/SubdomainTest.py b/tests/unit/core/SubdomainTest.py
index db183247e..3124e4502 100644
--- a/tests/unit/core/SubdomainTest.py
+++ b/tests/unit/core/SubdomainTest.py
@@ -37,26 +37,26 @@ class SubdomainTest:
     def test_drop_locations_from_geom_successively_with_single_geometry(self):
         assert self.geo.Np == 27
         assert self.geo.Nt == 54
-        self.geo.drop_locations(pores=[0, 1, 2], throats=[0, 1, 2])
+        self.geo._drop_locations(pores=[0, 1, 2], throats=[0, 1, 2])
         assert self.geo.Np == 24
         assert self.geo.Nt == 51
-        self.geo.drop_locations(pores=[3, 4], throats=[3, 4])
+        self.geo._drop_locations(pores=[3, 4], throats=[3, 4])
         assert self.geo.Np == 22
         assert self.geo.Nt == 49
-        self.geo.add_locations(pores=[0, 1, 2, 3, 4], throats=[0, 1, 2, 3, 4])
+        self.geo._add_locations(pores=[0, 1, 2, 3, 4], throats=[0, 1, 2, 3, 4])
         assert self.geo.Np == 27
         assert self.geo.Nt == 54
 
     def test_drop_locations_from_physics_successively_with_two_physics(self):
         assert self.phys1.Np == 27
         assert self.phys1.Nt == 54
-        self.phys1.drop_locations(pores=[0, 1], throats=[0, 1])
+        self.phys1._drop_locations(pores=[0, 1], throats=[0, 1])
         assert self.phys1.Np == 25
         assert self.phys1.Nt == 52
-        self.phys1.drop_locations(pores=[3, 4], throats=[3, 4])
+        self.phys1._drop_locations(pores=[3, 4], throats=[3, 4])
         assert self.phys1.Np == 23
         assert self.phys1.Nt == 50
-        self.phys1.add_locations(pores=[0, 1, 3, 4], throats=[0, 1, 3, 4])
+        self.phys1._add_locations(pores=[0, 1, 3, 4], throats=[0, 1, 3, 4])
         assert self.phys1.Np == 27
         assert self.phys1.Nt == 54
 
@@ -65,14 +65,14 @@ class SubdomainTest:
         assert self.phys1.Nt == 54
         assert 'pore.'+self.phys1.name in self.phase1.keys()
         assert 'throat.'+self.phys1.name in self.phase1.keys()
-        self.phys1.drop_locations(pores=self.net.Ps)
+        self.phys1._drop_locations(pores=self.net.Ps)
         assert 'pore.'+self.phys1.name in self.phase1.keys()
         assert self.phase1.num_pores(self.phys1.name) == 0
         assert 'throat.'+self.phys1.name in self.phase1.keys()
-        self.phys1.drop_locations(throats=self.net.Ts)
+        self.phys1._drop_locations(throats=self.net.Ts)
         assert 'throat.'+self.phys1.name in self.phase1.keys()
         assert self.phase1.num_throats(self.phys1.name) == 0
-        self.phys1.add_locations(pores=self.net.Ps, throats=self.net.Ts)
+        self.phys1._add_locations(pores=self.net.Ps, throats=self.net.Ts)
 
     def test_writting_subdict_names_across_subdomains(self):
         ws = op.Workspace()