Repository: pmeal/openpnm
Issue: ad_dif_conductance must be manually updated when running AdvectionDiffusion.run()

The problem is that `ad_dif_conductance` depends on `phase["pore.pressure"]`, which is only available after running `StokesFlow.run()`. So, in a normal OpenPNM simulation workflow, since `physics` object is obviously instantiated before running `StokesFlow`, the value of `ad_dif_conductance` is outdated since it has been calculated using obsolete `phase["pore.pressure"]` values.

There are many workarounds, here are two alternatives that I thought about:
1. Set `throat.ad_dif_conductance` as an `iterative_prop`, so it gets updated prior to calling the solver. This has the unintended effect of needlessly re-calculating `ad_dif_conductance` in iterative workflows (ex. nonlinear source term, etc.).
2. Overload `run` method for `AdvectionDiffusion` like this:
```
def run():
    self.physics.regenerate_models(propnames="throat.ad_dif_conductance")
    self.super().run()
```


Changed files:
openpnm/algorithms/GenericTransport.py, openpnm/algorithms/AdvectionDiffusion.py, tests/unit/algorithms/AdvectionDiffusionTest.py, tests/unit/algorithms/SolversTest.py

diff --git a/openpnm/algorithms/AdvectionDiffusion.py b/openpnm/algorithms/AdvectionDiffusion.py
index d5f0456d5..2ee2f1230 100644
--- a/openpnm/algorithms/AdvectionDiffusion.py
+++ b/openpnm/algorithms/AdvectionDiffusion.py
@@ -34,6 +34,8 @@ class AdvectionDiffusion(ReactiveTransport):
         self.settings.update(settings)
         if phase is not None:
             self.setup(phase=phase)
+        # Make "conductance" iterative_prop, so it gets updated after running StokesFlow
+        self.set_iterative_props(propnames=self.settings['conductance'])
 
     def setup(self, phase=None, quantity='', conductance='',
               diffusive_conductance='', hydraulic_conductance='', pressure='',
diff --git a/openpnm/algorithms/GenericTransport.py b/openpnm/algorithms/GenericTransport.py
index 74da08ca6..2ce41d69a 100644
--- a/openpnm/algorithms/GenericTransport.py
+++ b/openpnm/algorithms/GenericTransport.py
@@ -17,7 +17,7 @@ def_set = {'phase': None,
            'solver_family': 'scipy',
            'solver_type': 'spsolve',
            'solver_preconditioner': 'jacobi',
-           'solver_tol': 1e-6,
+           'solver_tol': 1e-8,
            'solver_atol': None,
            'solver_rtol': None,
            'solver_maxiter': 5000,
diff --git a/tests/unit/algorithms/AdvectionDiffusionTest.py b/tests/unit/algorithms/AdvectionDiffusionTest.py
index 15202de93..b2158db19 100644
--- a/tests/unit/algorithms/AdvectionDiffusionTest.py
+++ b/tests/unit/algorithms/AdvectionDiffusionTest.py
@@ -1,5 +1,5 @@
-import openpnm as op
 import scipy as sp
+import openpnm as op
 from numpy.testing import assert_allclose
 
 
@@ -31,13 +31,43 @@ class AdvectionDiffusionTest:
 
         self.ad = op.algorithms.AdvectionDiffusion(network=self.net,
                                                    phase=self.phase)
-        self.ad.setup(diffusive_conductance="throat.diffusive_conductance",
-                      hydraulic_conductance="throat.hydraulic_conductance",
-                      pressure="pore.pressure")
         self.ad.settings.update({"cache_A": False, "cache_b": False})
         self.ad.set_value_BC(pores=self.net.pores('back'), values=2)
         self.ad.set_value_BC(pores=self.net.pores('front'), values=0)
 
+    def test_AdvectionDiffusion_setup(self):
+        self.ad.setup(quantity="pore.blah",
+                      conductance="throat.foo",
+                      diffusive_conductance="throat.foo2",
+                      hydraulic_conductance="throat.foo3",
+                      pressure="pore.bar",)
+        assert self.ad.settings["quantity"] == "pore.blah"
+        assert self.ad.settings["conductance"] == "throat.foo"
+        assert self.ad.settings["diffusive_conductance"] == "throat.foo2"
+        assert self.ad.settings["hydraulic_conductance"] == "throat.foo3"
+        assert self.ad.settings["pressure"] == "pore.bar"
+        # Reset back to previous values for other tests to run
+        self.ad.setup(quantity="pore.concentration",
+                      conductance="throat.ad_dif_conductance",
+                      diffusive_conductance="throat.diffusive_conductance",
+                      hydraulic_conductance="throat.hydraulic_conductance",
+                      pressure="pore.pressure")
+
+    def test_conductance_gets_updated_when_pressure_changes(self):
+        mod = op.models.physics.ad_dif_conductance.ad_dif
+        self.phase['pore.p'] = self.phase['pore.pressure'].copy()
+        self.phys.add_model(propname='throat.ad_dif_conductance',
+                            model=mod, s_scheme='powerlaw',
+                            pore_pressure='pore.p')
+        g_old = self.phys["throat.ad_dif_conductance"]
+        # Manually change pressure field
+        self.phase['pore.p'] = self.phase['pore.p']**0.5
+        self.ad.run()
+        g_updated = self.phys["throat.ad_dif_conductance"]
+        # Ensure conductance values are updated
+        assert g_old.mean() != g_updated.mean()
+        assert_allclose(g_updated.mean(), 1.0071212e-15)
+
     def test_powerlaw_advection_diffusion(self):
         mod = op.models.physics.ad_dif_conductance.ad_dif
         self.phys.add_model(propname='throat.ad_dif_conductance_powerlaw',
diff --git a/tests/unit/algorithms/SolversTest.py b/tests/unit/algorithms/SolversTest.py
index 24a791b86..9c2286ee5 100644
--- a/tests/unit/algorithms/SolversTest.py
+++ b/tests/unit/algorithms/SolversTest.py
@@ -41,7 +41,7 @@ class SolversTest:
             self.alg.settings['solver_type'] = solver
             self.alg.run()
             xmean = self.alg['pore.x'].mean()
-            nt.assert_allclose(actual=xmean, desired=0.587595, rtol=1e-4)
+            nt.assert_allclose(actual=xmean, desired=0.587595, rtol=1e-5)
 
     def test_scipy_iterative_diverge(self):
         solvers = ['bicg', 'bicgstab', 'cg', 'cgs', 'qmr', 'gcrotmk',
@@ -54,11 +54,15 @@ class SolversTest:
                 self.alg.run()
         self.alg.settings.update(solver_maxiter=100)
 
-    # def test_pyamg(self):
-    #     self.alg.settings['solver_family'] = 'pyamg'
-    #     self.alg.run()
-    #     xmean = self.alg['pore.x'].mean()
-    #     nt.assert_allclose(actual=xmean, desired=0.587595, rtol=1e-5)
+    def test_pyamg(self):
+        self.alg.settings['solver_family'] = 'pyamg'
+        if importlib.util.find_spec('pyamg') is None:
+            with nt.assert_raises(Exception):
+                self.alg.run()
+        else:
+            self.alg.run()
+            xmean = self.alg['pore.x'].mean()
+            nt.assert_allclose(actual=xmean, desired=0.587595, rtol=1e-5)
 
     def test_petsc(self):
         self.alg.settings['solver_family'] = 'petsc'