Repository: PMEAL/OpenPNM
Pull request #1413 (2020-03-02 17:05:45)

Fix issue 1356
fixed issue #1356 
fixed other minor issues
improved ionic transport example
added ionic transport test


Patch:
diff --git a/examples/simulations/Transient Fickian Diffusion.ipynb b/examples/simulations/Transient Fickian Diffusion.ipynb
index be15afbe2..44552f520 100644
--- a/examples/simulations/Transient Fickian Diffusion.ipynb
+++ b/examples/simulations/Transient Fickian Diffusion.ipynb
@@ -277,7 +277,6 @@
       "t_step                              1\n",
       "t_output                            5\n",
       "t_tolerance                         1e-12\n",
-      "rxn_tolerance                       1e-05\n",
       "t_precision                         12\n",
       "t_scheme                            cranknicolson\n",
       "――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――\n"
@@ -339,11 +338,25 @@
       "3     pore.concentration                              377 / 377  \n",
       "4     pore.concentration@0                            377 / 377  \n",
       "5     pore.concentration@10                           377 / 377  \n",
-      "6     pore.concentration@15                           377 / 377  \n",
-      "7     pore.concentration@20                           377 / 377  \n",
-      "8     pore.concentration@25                           377 / 377  \n",
-      "9     pore.concentration@26                           377 / 377  \n",
-      "10    pore.concentration@5                            377 / 377  \n",
+      "6     pore.concentration@100                          377 / 377  \n",
+      "7     pore.concentration@15                           377 / 377  \n",
+      "8     pore.concentration@20                           377 / 377  \n",
+      "9     pore.concentration@25                           377 / 377  \n",
+      "10    pore.concentration@30                           377 / 377  \n",
+      "11    pore.concentration@35                           377 / 377  \n",
+      "12    pore.concentration@40                           377 / 377  \n",
+      "13    pore.concentration@45                           377 / 377  \n",
+      "14    pore.concentration@5                            377 / 377  \n",
+      "15    pore.concentration@50                           377 / 377  \n",
+      "16    pore.concentration@55                           377 / 377  \n",
+      "17    pore.concentration@60                           377 / 377  \n",
+      "18    pore.concentration@65                           377 / 377  \n",
+      "19    pore.concentration@70                           377 / 377  \n",
+      "20    pore.concentration@75                           377 / 377  \n",
+      "21    pore.concentration@80                           377 / 377  \n",
+      "22    pore.concentration@85                           377 / 377  \n",
+      "23    pore.concentration@90                           377 / 377  \n",
+      "24    pore.concentration@95                           377 / 377  \n",
       "――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――\n",
       "#     Labels                                        Assigned Locations\n",
       "――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――\n",
@@ -491,7 +504,7 @@
    "outputs": [
     {
      "data": {
-      "image/png": "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\n",
+      "image/png": "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\n",
       "text/plain": [
        "<Figure size 432x432 with 2 Axes>"
       ]
@@ -533,7 +546,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.7.6"
+   "version": "3.7.3"
   }
  },
  "nbformat": 4,
diff --git a/openpnm/algorithms/ChargeConservation.py b/openpnm/algorithms/ChargeConservation.py
index fca54a750..ab148eb45 100644
--- a/openpnm/algorithms/ChargeConservation.py
+++ b/openpnm/algorithms/ChargeConservation.py
@@ -24,6 +24,8 @@ class ChargeConservation(ReactiveTransport):
 
     def __init__(self, settings={}, phase=None, **kwargs):
         def_set = {'phase': None,
+                   'cache_A': False,
+                   'cache_b': False,
                    'quantity': 'pore.potential',
                    'conductance': 'throat.ionic_conductance',
                    'charge_conservation': 'electroneutrality',
diff --git a/openpnm/algorithms/GenericTransport.py b/openpnm/algorithms/GenericTransport.py
index 385377476..cd79ce703 100644
--- a/openpnm/algorithms/GenericTransport.py
+++ b/openpnm/algorithms/GenericTransport.py
@@ -598,7 +598,7 @@ class GenericTransport(GenericAlgorithm):
 
         # PyAMG
         if self.settings['solver_family'] == 'pyamg':
-            # Check if petsc is available
+            # Check if PyAMG is available
             try:
                 import pyamg
             except Exception:
diff --git a/openpnm/algorithms/IonicTransport.py b/openpnm/algorithms/IonicTransport.py
index 844aa4609..56288d92c 100644
--- a/openpnm/algorithms/IonicTransport.py
+++ b/openpnm/algorithms/IonicTransport.py
@@ -11,16 +11,16 @@ class IonicTransport(ReactiveTransport):
         def_set = {'phase': None,
                    'potential_field': '',
                    'ions': [],
-                   'i_tolerance': 1e-4,
-                   'i_max_iter': 10}
+                   'g_tol': 1e-4,
+                   'g_max_iter': 10}
         super().__init__(**kwargs)
         self.settings.update(def_set)
         self.settings.update(settings)
         if phase is not None:
             self.setup(phase=phase)
 
-    def setup(self, phase=None, potential_field='', ions=[], i_tolerance=None,
-              i_max_iter=None, **kwargs):
+    def setup(self, phase=None, potential_field='', ions=[], g_tol=None,
+              g_max_iter=None, **kwargs):
         r"""
         """
         if phase:
@@ -29,10 +29,10 @@ class IonicTransport(ReactiveTransport):
             self.settings['potential_field'] = potential_field
         if ions:
             self.settings['ions'] = ions
-        if i_tolerance:
-            self.settings['i_tolerance'] = i_tolerance
-        if i_max_iter:
-            self.settings['i_max_iter'] = i_max_iter
+        if g_tol:
+            self.settings['g_tol'] = g_tol
+        if g_max_iter:
+            self.settings['g_max_iter'] = g_max_iter
         super().setup(**kwargs)
 
     def run(self, t=None):
@@ -64,44 +64,44 @@ class IonicTransport(ReactiveTransport):
         p_alg._charge_conservation_eq_source_term(e_alg=e_alg)
 
         # Initialize residuals & old/new fields for Gummel iterats
-        i_tol = self.settings['i_tolerance']
-        i_res = {}
-        i_old = {}
-        i_new = {}
+        g_tol = self.settings['g_tol']
+        g_res = {}
+        g_old = {}
+        g_new = {}
         for alg in algs:
-            i_res[alg.name] = 1e+06
-            i_old[alg.name] = None
-            i_new[alg.name] = None
+            g_res[alg.name] = 1e+06
+            g_old[alg.name] = None
+            g_new[alg.name] = None
 
         # Iterate (Gummel) until solutions converge
-        for itr in range(int(self.settings['i_max_iter'])):
-            i_r = [float(format(i, '.3g')) for i in i_res.values()]
-            i_r = str(i_r)[1:-1]
-            print('Gummel iter: '+str(itr+1)+', residuals: '+i_r)
-            i_convergence = max(i for i in i_res.values()) < i_tol
-            if not i_convergence:
+        for itr in range(int(self.settings['g_max_iter'])):
+            g_r = [float(format(i, '.3g')) for i in g_res.values()]
+            g_r = str(g_r)[1:-1]
+            print('Gummel iter: '+str(itr+1)+', residuals: '+g_r)
+            g_convergence = max(i for i in g_res.values()) < g_tol
+            if not g_convergence:
                 # Ions
                 for e in e_alg:
-                    i_old[e.name] = (e[e.settings['quantity']].copy())
-                    e._run_reactive(x0=i_old[e.name])
-                    i_new[e.name] = (e[e.settings['quantity']].copy())
+                    g_old[e.name] = (e[e.settings['quantity']].copy())
+                    e._run_reactive(x0=g_old[e.name])
+                    g_new[e.name] = (e[e.settings['quantity']].copy())
                     # Residual
-                    i_res[e.name] = np.sum(np.absolute(
-                        i_old[e.name]**2-i_new[e.name]**2))
+                    g_res[e.name] = np.sum(np.absolute(
+                        g_old[e.name]**2-g_new[e.name]**2))
                     phase.update(e.results())
 
                 # Poisson eq
                 phys[0].regenerate_models()
-                i_old[p_alg.name] = p_alg[p_alg.settings['quantity']].copy()
-                p_alg._run_reactive(x0=i_old[p_alg.name])
-                i_new[p_alg.name] = p_alg[p_alg.settings['quantity']].copy()
+                g_old[p_alg.name] = p_alg[p_alg.settings['quantity']].copy()
+                p_alg._run_reactive(x0=g_old[p_alg.name])
+                g_new[p_alg.name] = p_alg[p_alg.settings['quantity']].copy()
                 # Residual
-                i_res[p_alg.name] = np.sum(np.absolute(
-                    i_old[p_alg.name]**2 - i_new[p_alg.name]**2))
+                g_res[p_alg.name] = np.sum(np.absolute(
+                    g_old[p_alg.name]**2 - g_new[p_alg.name]**2))
                 # Update phase and physics
                 phase.update(p_alg.results())
                 phys[0].regenerate_models()
 
-            if i_convergence:
+            if g_convergence:
                 print('Solution converged')
                 break
diff --git a/openpnm/algorithms/TransientIonicTransport.py b/openpnm/algorithms/TransientIonicTransport.py
index 1c2efecb7..457a8c51d 100644
--- a/openpnm/algorithms/TransientIonicTransport.py
+++ b/openpnm/algorithms/TransientIonicTransport.py
@@ -15,8 +15,8 @@ class TransientIonicTransport(IonicTransport, TransientReactiveTransport):
                    'gui': {'setup':        {'phase': None,
                                             'potential_field': '',
                                             'ions': [],
-                                            'i_tolerance': None,
-                                            'i_max_iter': None,
+                                            'solver_tol': None,
+                                            'solver_maxiter': None,
                                             't_initial': None,
                                             't_final': None,
                                             't_step': None,
@@ -31,8 +31,8 @@ class TransientIonicTransport(IonicTransport, TransientReactiveTransport):
         if phase is not None:
             self.setup(phase=phase)
 
-    def setup(self, phase=None, potential_field='', ions=[], i_tolerance=None,
-              i_max_iter=None, t_initial=None, t_final=None, t_step=None,
+    def setup(self, phase=None, potential_field='', ions=[], g_tol=None,
+              g_max_iter=None, t_initial=None, t_final=None, t_step=None,
               t_output=None, t_tolerance=None, t_precision=None, t_scheme='',
               **kwargs):
         if phase:
@@ -41,10 +41,10 @@ class TransientIonicTransport(IonicTransport, TransientReactiveTransport):
             self.settings['potential_field'] = potential_field
         if ions:
             self.settings['ions'] = ions
-        if i_tolerance:
-            self.settings['i_tolerance'] = i_tolerance
-        if i_max_iter:
-            self.settings['i_max_iter'] = i_max_iter
+        if g_tol:
+            self.settings['g_tol'] = g_tol
+        if g_max_iter:
+            self.settings['g_max_iter'] = g_max_iter
         if t_initial is not None:
             self.settings['t_initial'] = t_initial
         if t_final is not None:
@@ -83,21 +83,19 @@ class TransientIonicTransport(IonicTransport, TransientReactiveTransport):
                 except KeyError:
                     alg.set_IC(0)
 
-        # Save A matrix of the steady sys of eqs (WITHOUT BCs applied)
-        for alg in algs:
-            alg._build_A()
-            alg._A_steady = (alg._A).copy()
-        # Initialize A and b with BCs applied
         for e in e_alg:
+            # Save A matrix of the steady sys of eqs (WITHOUT BCs applied)
+            e._build_A()
+            e._A_steady = (e._A).copy()
+            # Initialize A and b with BCs applied
             e._t_update_A()
             e._t_update_b()
             e._apply_BCs()
             e._A_t = (e._A).copy()
             e._b_t = (e._b).copy()
         # Init A&b with BCs for charge conservation eq, independent of t_scheme
+        p_alg._build_A()
         p_alg._apply_BCs()
-        p_alg._A_t = (p_alg._A).copy()
-        p_alg._b_t = (p_alg._b).copy()
 
         if t is None:
             t = self.settings['t_initial']
@@ -106,14 +104,14 @@ class TransientIonicTransport(IonicTransport, TransientReactiveTransport):
             alg._update_iterative_props()
 
         # Setup algorithms transient settings
-        for alg in algs:
-            alg.setup(t_initial=self.settings['t_initial'],
-                      t_final=self.settings['t_final'],
-                      t_step=self.settings['t_step'],
-                      t_output=self.settings['t_output'],
-                      t_tolerance=self.settings['t_tolerance'],
-                      t_precision=self.settings['t_precision'],
-                      t_scheme=self.settings['t_scheme'])
+        for e in e_alg:
+            e.setup(t_initial=self.settings['t_initial'],
+                    t_final=self.settings['t_final'],
+                    t_step=self.settings['t_step'],
+                    t_output=self.settings['t_output'],
+                    t_tolerance=self.settings['t_tolerance'],
+                    t_precision=self.settings['t_precision'],
+                    t_scheme=self.settings['t_scheme'])
 
         self._run_transient(t=t)
 
@@ -132,9 +130,10 @@ class TransientIonicTransport(IonicTransport, TransientReactiveTransport):
         dt = self.settings['t_step']
         to = self.settings['t_output']
         t_tol = self.settings['t_tolerance']
-        i_tol = self.settings['i_tolerance']
         t_pre = self.settings['t_precision']
         s = self.settings['t_scheme']
+        g_tol = self.settings['g_tol']
+        g_max_iter = int(self.settings['g_max_iter'])
         # Initialize residuals & old/new fields for time marching
         t_res = {}
         t_old = {}
@@ -183,48 +182,50 @@ class TransientIonicTransport(IonicTransport, TransientReactiveTransport):
                         t_old[alg.name] = alg[alg.settings['quantity']].copy()
 
                     # Initialize residuals & old/new fields for Gummel iterats
-                    i_res = {}
-                    i_old = {}
-                    i_new = {}
+                    g_res = {}
+                    g_old = {}
+                    g_new = {}
                     for alg in algs:
-                        i_res[alg.name] = 1e+06
-                        i_old[alg.name] = None
-                        i_new[alg.name] = None
+                        g_res[alg.name] = 1e+03
+                        g_old[alg.name] = None
+                        g_new[alg.name] = None
 
                     # Iterate (Gummel) until solutions converge
-                    for itr in range(int(self.settings['i_max_iter'])):
-                        i_r = [float(format(i, '.3g')) for i in i_res.values()]
-                        i_r = str(i_r)[1:-1]
-                        print('Gummel iter: '+str(itr+1)+', residuals: '+i_r)
-                        i_convergence = max(i for i in i_res.values()) < i_tol
-                        if not i_convergence:
+                    for itr in range(g_max_iter):
+                        g_r = [float(format(i, '.3g')) for i in g_res.values()]
+                        g_r = str(g_r)[1:-1]
+                        print('Start Gummel iter: ' + str(itr+1) +
+                              ', residuals: ' + g_r)
+                        g_convergence = max(i for i in g_res.values()) < g_tol
+                        if not g_convergence:
                             # Ions
                             for e in e_alg:
-                                i_old[e.name] = (
+                                g_old[e.name] = (
                                     e[e.settings['quantity']].copy())
-                                e._t_run_reactive(x0=i_old[e.name])
-                                i_new[e.name] = (
+
+                                e._t_run_reactive(x0=g_old[e.name])
+                                g_new[e.name] = (
                                     e[e.settings['quantity']].copy())
                                 # Residual
-                                i_res[e.name] = np.sum(np.absolute(
-                                    i_old[e.name]**2 - i_new[e.name]**2))
+                                g_res[e.name] = np.sum(np.absolute(
+                                    g_old[e.name]**2 - g_new[e.name]**2))
                                 phase.update(e.results())
 
-                            # Poisson eq
+                            # Charge conservation eq
                             phys[0].regenerate_models()
-                            i_old[p_alg.name] = (
+                            g_old[p_alg.name] = (
                                 p_alg[p_alg.settings['quantity']].copy())
-                            p_alg._t_run_reactive(x0=i_old[p_alg.name])
-                            i_new[p_alg.name] = (
+                            p_alg._run_reactive(x0=g_old[p_alg.name])
+                            g_new[p_alg.name] = (
                                 p_alg[p_alg.settings['quantity']].copy())
                             # Residual
-                            i_res[p_alg.name] = np.sum(np.absolute(
-                                i_old[p_alg.name]**2 - i_new[p_alg.name]**2))
+                            g_res[p_alg.name] = np.sum(np.absolute(
+                                g_old[p_alg.name]**2 - g_new[p_alg.name]**2))
                             # Update phase and physics
                             phase.update(p_alg.results())
                             phys[0].regenerate_models()
 
-                        elif i_convergence:
+                        elif g_convergence:
                             print('Solution for time step: ' + str(time)
                                   + ' s converged')
                             break
@@ -232,7 +233,8 @@ class TransientIonicTransport(IonicTransport, TransientReactiveTransport):
                     for alg in algs:  # Save new fields & compute t residuals
                         t_new[alg.name] = alg[alg.settings['quantity']].copy()
                         t_res[alg.name] = np.sum(
-                            np.absolute(t_old[alg.name]**2 - t_new[alg.name]**2))
+                            np.absolute(t_old[alg.name]**2 -
+                                        t_new[alg.name]**2))
 
                     # Output transient solutions. Round time to ensure every
                     # value in outputs is exported.
@@ -244,22 +246,22 @@ class TransientIonicTransport(IonicTransport, TransientReactiveTransport):
                                 t_new[alg.name])
 
                     # Update A matrix of the steady sys of eqs (WITHOUT BCs)
-                    for alg in algs:
+                    for e in e_alg:
                         # Update conductance first
-                        physics = alg.project.find_physics(phase=phase)
+                        physics = e.project.find_physics(phase=phase)
                         for ph in physics:
                             ph.regenerate_models()
                         # Update A matrix
-                        alg._build_A()
-                        alg._A_steady = (alg._A).copy()
+                        e._build_A()
+                        e._A_steady = (e._A).copy()
 
                     # Update A and b and apply BCs
-                    for alg in algs:
-                        alg._t_update_A()
-                        alg._t_update_b()
-                        alg._apply_BCs()
-                        alg._A_t = (alg._A).copy()
-                        alg._b_t = (alg._b).copy()
+                    for e in e_alg:
+                        e._t_update_A()
+                        e._t_update_b()
+                        e._apply_BCs()
+                        e._A_t = (e._A).copy()
+                        e._b_t = (e._b).copy()
 
                 else:  # Stop time iterations if residual < t_tolerance
                     # Output steady state solution
diff --git a/openpnm/algorithms/TransientReactiveTransport.py b/openpnm/algorithms/TransientReactiveTransport.py
index 703461c4a..a887c9b3f 100644
--- a/openpnm/algorithms/TransientReactiveTransport.py
+++ b/openpnm/algorithms/TransientReactiveTransport.py
@@ -35,7 +35,7 @@ class TransientReactiveTransport(ReactiveTransport):
                    't_step': 0.1,
                    't_output': 1e+08,
                    't_tolerance': 1e-06,
-                   'rxn_tolerance': 1e-05,
+                   'solver_tol': 1e-08,
                    't_precision': 12,
                    't_scheme': 'implicit',
                    'gui': {'setup':        {'phase': None,
@@ -114,10 +114,10 @@ class TransientReactiveTransport(ReactiveTransport):
             default value is 1e-06. The 'residual' measures the variation from
             one time-step to another in the value of the 'quantity' solved for.
 
-        rxn_tolerance : scalar
+        solver_tol : scalar
             Tolerance to achieve within each time step. The solver passes to
-            next time step when 'residual' falls below 'rxn_tolerance'. The
-            default value is 1e-05.
+            next time step when 'residual' falls below 'solver_tol'. The
+            default value is 1e-08.
 
         t_precision : integer
             The time precision (number of decimal places).
@@ -186,7 +186,6 @@ class TransientReactiveTransport(ReactiveTransport):
         elif (s == 'steady'):
             f1, f2 = 1, 0
         # Compute A (operations involve conversion to 'csr')
-        temp = np.reshape(Vi, (self.Np, 1))
         A = ((f2/dt) * sprs.coo_matrix.multiply(
             sprs.coo_matrix(np.reshape(Vi, (self.Np, 1)), shape=(self.Np, 1)),
             sprs.identity(self.Np, format='coo')) + f1 * self._A_steady)
@@ -344,10 +343,12 @@ class TransientReactiveTransport(ReactiveTransport):
                     # Output steady state solution
                     t_str = self._nbr_to_str(time)
                     self[quantity + '@' + t_str] = x_new
-                    logger.info('        Exporting time step: ' + str(time) + ' s')
+                    logger.info('        Exporting time step: ' +
+                                str(time) + ' s')
                     break
             if (round(time, t_pre) == tf):
-                logger.info('    Maximum time step reached: ' + str(time) + ' s')
+                logger.info('    Maximum time step reached: ' +
+                            str(time) + ' s')
             else:
                 logger.info('    Transient solver converged after: '
                             + str(time) + ' s')
@@ -357,7 +358,7 @@ class TransientReactiveTransport(ReactiveTransport):
         Repeatedly updates transient 'A', 'b', and the solution guess within
         each time step according to the applied source term then calls '_solve'
         to solve the resulting system of linear equations. Stops when the
-        residual falls below 'rxn_tolerance'.
+        residual falls below 'solver_tol'.
 
         Parameters
         ----------
@@ -378,36 +379,34 @@ class TransientReactiveTransport(ReactiveTransport):
             x0 = np.zeros(self.Np, dtype=float)
         x = x0
         self[self.settings['quantity']] = x
-        relax = self.settings['relaxation_quantity']
-        phase = self.project.phases()[self.settings['phase']]
-        # Reference for residual's normalization
-        ref = np.sum(np.absolute(self._A_t.diagonal())) or 1
-        for itr in range(int(self.settings['max_iter'])):
-            self[self.settings['quantity']] = x
-            phase.update(self.results())
+
+        w = self.settings['relaxation_quantity']
+        quantity = self.settings['quantity']
+        max_it = int(self.settings['max_iter'])
+        # Write initial guess to algorithm for _update_iterative_props to work
+        self[quantity] = x = x0
+
+        for itr in range(max_it):
+            # Update iterative properties on phase and physics
             self._update_iterative_props()
+            # Build A and b, apply source terms and correct according to scheme
             self._A = (self._A_t).copy()
             self._b = (self._b_t).copy()
             self._apply_sources()
             self._correct_apply_sources()
-            # Compute the normalized residual
-            res = np.linalg.norm(self.b-self.A*x)/ref
-            if res >= self.settings['rxn_tolerance']:
-                logger.info('Tolerance not met: ' + str(res))
-                x_new = self._solve()
-                # Relaxation
-                x_new = relax*x_new + (1-relax)*self[self.settings['quantity']]
-                self[self.settings['quantity']] = x_new
-                x = x_new
-            elif (res < self.settings['rxn_tolerance']):
-                x_new = x
-                logger.info('Solution converged: ' + str(res))
-                break
-            else:  # If res is nan or inf
-                x_new = x
-                logger.warning('Residual undefined: ' + str(res))
-                break
-        return x_new
+            # Compute the residual
+            res = self._get_residual()
+
+            if self._is_converged():
+                logger.info(f'Solution converged: {res:.4e}')
+                return x
+            logger.info(f'Tolerance not met: {res:.4e}')
+            # Solve, use relaxation, and update solution on algorithm obj
+            self[quantity] = x = self._solve(x0=x) * w + x * (1 - w)
+
+        # Check solution convergence after max_it iterations
+        if not self._is_converged():
+            raise Exception(f"Not converged after {max_it} iterations.")
 
     def results(self, times=None, **kwargs):
         r"""
diff --git a/scripts/example_transient_AD.py b/scripts/example_transient_AD.py
index 2783278fb..54a3c8242 100644
--- a/scripts/example_transient_AD.py
+++ b/scripts/example_transient_AD.py
@@ -54,11 +54,7 @@ phys.add_model(propname='throat.ad_dif_conductance',
 ad = op.algorithms.TransientAdvectionDiffusion(network=net, phase=water)
 ad.set_value_BC(pores=net.pores('back'), values=100)
 ad.set_value_BC(pores=net.pores('front'), values=90)
-ad.settings['rxn_tolerance'] = 1e-12
-
-ad.settings['i_max_iter'] = 10
-ad.settings['i_tolerance'] = 1e-04
-ad.settings['charge_conservation'] = 'laplace'
+ad.settings['solver_tol'] = 1e-12
 ad.settings['t_output'] = 500
 ad.settings['t_step'] = 100
 ad.settings['t_final'] = 2000
diff --git a/scripts/example_transient_PNP.py b/scripts/example_transient_PNP.py
index 29926c430..429831f5c 100644
--- a/scripts/example_transient_PNP.py
+++ b/scripts/example_transient_PNP.py
@@ -53,50 +53,51 @@ phys.add_model(propname='throat.diffusive_conductance.' + Cl.name,
                throat_diffusivity='throat.diffusivity.' + Cl.name,
                model=eB_dif, regen_mode='normal')
 
+# settings for algorithms
+setts1 = {'solver_maxiter': 5, 'solver_tol': 1e-08, 'solver_rtol': 1e-08,
+          'max_iter': 10}
+setts2 = {'g_tol': 1e-4, 'g_max_iter': 4, 't_output': 5000, 't_step': 500,
+          't_final': 20000, 't_scheme': 'implicit'}
+
 # algorithms
-sf = op.algorithms.StokesFlow(network=net, phase=sw)
+sf = op.algorithms.StokesFlow(network=net, phase=sw, settings=setts1)
 sf.set_value_BC(pores=net.pores('back'), values=0.01)
 sf.set_value_BC(pores=net.pores('front'), values=0.00)
-sf.settings['rxn_tolerance'] = 1e-12
 sf.run()
 sw.update(sf.results())
 
-p = op.algorithms.TransientChargeConservation(network=net, phase=sw)
-p.set_value_BC(pores=net.pores('left'), values=0.01)
+p = op.algorithms.TransientChargeConservation(network=net, phase=sw,
+                                              settings=setts1)
+p.set_value_BC(pores=net.pores('left'), values=0.1)
 p.set_value_BC(pores=net.pores('right'), values=0.00)
 p.settings['charge_conservation'] = 'electroneutrality'
 
-eA = op.algorithms.TransientNernstPlanck(network=net, phase=sw, ion=Na.name)
+eA = op.algorithms.TransientNernstPlanck(network=net, phase=sw, ion=Na.name,
+                                         settings=setts1)
 eA.set_value_BC(pores=net.pores('back'), values=100)
 eA.set_value_BC(pores=net.pores('front'), values=90)
-eA.settings['rxn_tolerance'] = 1e-12
 
-eB = op.algorithms.TransientNernstPlanck(network=net, phase=sw, ion=Cl.name)
+eB = op.algorithms.TransientNernstPlanck(network=net, phase=sw, ion=Cl.name,
+                                         settings=setts1)
 eB.set_value_BC(pores=net.pores('back'), values=100)
 eB.set_value_BC(pores=net.pores('front'), values=90)
-eB.settings['rxn_tolerance'] = 1e-12
 
 ad_dif_mig_Na = op.models.physics.ad_dif_mig_conductance.ad_dif_mig
 phys.add_model(propname='throat.ad_dif_mig_conductance.' + Na.name,
+               pore_pressure=sf.settings['quantity'],
                model=ad_dif_mig_Na, ion=Na.name,
-               s_scheme='exponential')
+               s_scheme='powerlaw')
 
 ad_dif_mig_Cl = op.models.physics.ad_dif_mig_conductance.ad_dif_mig
 phys.add_model(propname='throat.ad_dif_mig_conductance.' + Cl.name,
                pore_pressure=sf.settings['quantity'],
                model=ad_dif_mig_Cl, ion=Cl.name,
-               s_scheme='exponential')
-
-pnp = op.algorithms.TransientIonicTransport(network=net, phase=sw)
-pnp.setup(potential_field=p.name, ions=[eA.name, eB.name])
-pnp.settings['i_max_iter'] = 10
-pnp.settings['i_tolerance'] = 1e-04
-pnp.settings['t_output'] = 100
-pnp.settings['t_step'] = 100
-pnp.settings['t_final'] = 3000
-# pnp.settings['t_scheme'] = 'steady'
-
-pnp.run()
+               s_scheme='powerlaw')
+
+it = op.algorithms.TransientIonicTransport(network=net, phase=sw,
+                                           settings=setts2)
+it.setup(potential_field=p.name, ions=[eA.name, eB.name])
+it.run()
 
 sw.update(sf.results())
 sw.update(p.results())


Test patch:
diff --git a/tests/unit/algorithms/TransientIonicTransportTest.py b/tests/unit/algorithms/TransientIonicTransportTest.py
new file mode 100644
index 000000000..c7e069096
--- /dev/null
+++ b/tests/unit/algorithms/TransientIonicTransportTest.py
@@ -0,0 +1,198 @@
+import numpy as np
+import openpnm as op
+from openpnm.phases import mixtures
+
+
+class TransientIonicTransportTest:
+
+    def setup_class(self):
+        np.random.seed(0)
+        self.net = op.network.Cubic(shape=[8, 8, 1], spacing=9e-4)
+
+        prs = (self.net['pore.back'] * self.net['pore.right'] +
+               self.net['pore.back'] * self.net['pore.left'] +
+               self.net['pore.front'] * self.net['pore.right'] +
+               self.net['pore.front'] * self.net['pore.left'])
+        thrts = self.net['throat.surface']
+        op.topotools.trim(network=self.net, pores=self.net.Ps[prs],
+                          throats=self.net.Ts[thrts])
+
+        self.geo = op.geometry.StickAndBall(network=self.net,
+                                            pores=self.net.Ps,
+                                            throats=self.net.Ts)
+        pr_d = op.models.misc.constant
+        trt_d = op.models.misc.constant
+        self.geo.add_model(propname='pore.diameter', model=pr_d, value=1.5e-4)
+        self.geo.add_model(propname='throat.diameter', model=trt_d, value=1e-4)
+        self.geo.regenerate_models()
+
+        self.phase = mixtures.SalineWater(network=self.net)
+        # Retrieve handles to each species for use below
+        self.Cl, self.Na, self.H2O = self.phase.components.values()
+
+        # physics
+        self.phys = op.physics.GenericPhysics(network=self.net,
+                                              phase=self.phase,
+                                              geometry=self.geo)
+
+        flow = op.models.physics.hydraulic_conductance.hagen_poiseuille
+        self.phys.add_model(propname='throat.hydraulic_conductance',
+                            pore_viscosity='pore.viscosity',
+                            throat_viscosity='throat.viscosity',
+                            model=flow, regen_mode='normal')
+
+        current = op.models.physics.ionic_conductance.electroneutrality
+        self.phys.add_model(propname='throat.ionic_conductance',
+                            ions=[self.Na.name, self.Cl.name],
+                            model=current, regen_mode='normal')
+
+        eA_dif = op.models.physics.diffusive_conductance.ordinary_diffusion
+        self.phys.add_model(propname='throat.diffusive_conductance.' +
+                            self.Na.name,
+                            pore_diffusivity='pore.diffusivity.'+self.Na.name,
+                            throat_diffusivity='throat.diffusivity.' +
+                            self.Na.name, model=eA_dif, regen_mode='normal')
+
+        eB_dif = op.models.physics.diffusive_conductance.ordinary_diffusion
+        self.phys.add_model(propname='throat.diffusive_conductance.' +
+                            self.Cl.name,
+                            pore_diffusivity='pore.diffusivity.'+self.Cl.name,
+                            throat_diffusivity='throat.diffusivity.' +
+                            self.Cl.name, model=eB_dif, regen_mode='normal')
+
+        # settings for algorithms
+        self.settings1 = {'solver_maxiter': 5, 'solver_tol': 1e-08,
+                          'solver_rtol': 1e-08, 'max_iter': 10}
+        self.settings2 = {'g_tol': 1e-4, 'g_max_iter': 4, 't_output': 5000,
+                          't_step': 500, 't_final': 20000,
+                          't_scheme': 'implicit'}
+
+    def test_transient_ionic_reactive_transport(self):
+        # algorithms
+        sf = op.algorithms.StokesFlow(network=self.net, phase=self.phase,
+                                      settings=self.settings1)
+        sf.set_value_BC(pores=self.net.pores('back'), values=0.01)
+        sf.set_value_BC(pores=self.net.pores('front'), values=0.00)
+        sf.run()
+        self.phase.update(sf.results())
+
+        p = op.algorithms.TransientChargeConservation(network=self.net,
+                                                      phase=self.phase,
+                                                      settings=self.settings1)
+        p.set_value_BC(pores=self.net.pores('left'), values=0.1)
+        p.set_value_BC(pores=self.net.pores('right'), values=0.00)
+        p.settings['charge_conservation'] = 'electroneutrality'
+
+        eA = op.algorithms.TransientNernstPlanck(network=self.net,
+                                                 phase=self.phase,
+                                                 ion=self.Na.name,
+                                                 settings=self.settings1)
+        eA.set_value_BC(pores=self.net.pores('back'), values=100)
+        eA.set_value_BC(pores=self.net.pores('front'), values=90)
+
+        eB = op.algorithms.TransientNernstPlanck(network=self.net,
+                                                 phase=self.phase,
+                                                 ion=self.Cl.name,
+                                                 settings=self.settings1)
+        eB.set_value_BC(pores=self.net.pores('back'), values=100)
+        eB.set_value_BC(pores=self.net.pores('front'), values=90)
+
+        ad_dif_mig_Na = op.models.physics.ad_dif_mig_conductance.ad_dif_mig
+        self.phys.add_model(propname='throat.ad_dif_mig_conductance.' +
+                            self.Na.name,
+                            pore_pressure=sf.settings['quantity'],
+                            model=ad_dif_mig_Na, ion=self.Na.name,
+                            s_scheme='powerlaw')
+
+        ad_dif_mig_Cl = op.models.physics.ad_dif_mig_conductance.ad_dif_mig
+        self.phys.add_model(propname='throat.ad_dif_mig_conductance.' +
+                            self.Cl.name,
+                            pore_pressure=sf.settings['quantity'],
+                            model=ad_dif_mig_Cl, ion=self.Cl.name,
+                            s_scheme='powerlaw')
+
+        it = op.algorithms.TransientIonicTransport(network=self.net,
+                                                   phase=self.phase,
+                                                   settings=self.settings2)
+        it.setup(potential_field=p.name, ions=[eA.name, eB.name])
+        it.run()
+
+        self.phase.update(sf.results())
+        self.phase.update(p.results())
+        self.phase.update(eA.results())
+        self.phase.update(eB.results())
+
+        x = ([8.571000e-02, 7.143000e-02, 5.714000e-02, 4.286000e-02,
+              2.857000e-02, 1.429000e-02, 1.000000e-01, 8.571000e-02,
+              7.143000e-02, 5.714000e-02, 4.286000e-02, 2.857000e-02,
+              1.429000e-02, 0.000000e+00, 1.000000e-01, 8.571000e-02,
+              7.143000e-02, 5.714000e-02, 4.286000e-02, 2.857000e-02,
+              1.429000e-02, 0.000000e+00, 1.000000e-01, 8.571000e-02,
+              7.143000e-02, 5.714000e-02, 4.286000e-02, 2.857000e-02,
+              1.429000e-02, 0.000000e+00, 1.000000e-01, 8.571000e-02,
+              7.143000e-02, 5.714000e-02, 4.286000e-02, 2.857000e-02,
+              1.429000e-02, 0.000000e+00, 1.000000e-01, 8.571000e-02,
+              7.143000e-02, 5.714000e-02, 4.286000e-02, 2.857000e-02,
+              1.429000e-02, 0.000000e+00, 1.000000e-01, 8.571000e-02,
+              7.143000e-02, 5.714000e-02, 4.286000e-02, 2.857000e-02,
+              1.429000e-02, 0.000000e+00, 8.571000e-02, 7.143000e-02,
+              5.714000e-02, 4.286000e-02, 2.857000e-02, 1.429000e-02,
+              9.000000e+01, 9.000000e+01, 9.000000e+01, 9.000000e+01,
+              9.000000e+01, 9.000000e+01, 9.343697e+01, 9.343697e+01,
+              9.343697e+01, 9.343697e+01, 9.343697e+01, 9.343697e+01,
+              9.343697e+01, 9.343697e+01, 9.577144e+01, 9.577145e+01,
+              9.577145e+01, 9.577145e+01, 9.577145e+01, 9.577145e+01,
+              9.577145e+01, 9.577144e+01, 9.735708e+01, 9.735709e+01,
+              9.735709e+01, 9.735709e+01, 9.735709e+01, 9.735709e+01,
+              9.735709e+01, 9.735708e+01, 9.843409e+01, 9.843409e+01,
+              9.843410e+01, 9.843410e+01, 9.843410e+01, 9.843410e+01,
+              9.843409e+01, 9.843409e+01, 9.916563e+01, 9.916563e+01,
+              9.916563e+01, 9.916563e+01, 9.916563e+01, 9.916563e+01,
+              9.916563e+01, 9.916563e+01, 9.966251e+01, 9.966251e+01,
+              9.966251e+01, 9.966251e+01, 9.966251e+01, 9.966251e+01,
+              9.966251e+01, 9.966251e+01, 1.000000e+02, 1.000000e+02,
+              1.000000e+02, 1.000000e+02, 1.000000e+02, 1.000000e+02,
+              9.000000e+01, 9.000000e+01, 9.000000e+01, 9.000000e+01,
+              9.000000e+01, 9.000000e+01, 9.269748e+01, 9.269748e+01,
+              9.269748e+01, 9.269748e+01, 9.269748e+01, 9.269748e+01,
+              9.269748e+01, 9.269748e+01, 9.479053e+01, 9.479054e+01,
+              9.479054e+01, 9.479054e+01, 9.479054e+01, 9.479054e+01,
+              9.479054e+01, 9.479053e+01, 9.641461e+01, 9.641461e+01,
+              9.641461e+01, 9.641461e+01, 9.641461e+01, 9.641461e+01,
+              9.641461e+01, 9.641461e+01, 9.767477e+01, 9.767478e+01,
+              9.767478e+01, 9.767478e+01, 9.767478e+01, 9.767478e+01,
+              9.767478e+01, 9.767477e+01, 9.865258e+01, 9.865258e+01,
+              9.865258e+01, 9.865258e+01, 9.865258e+01, 9.865258e+01,
+              9.865258e+01, 9.865258e+01, 9.941129e+01, 9.941129e+01,
+              9.941129e+01, 9.941129e+01, 9.941129e+01, 9.941129e+01,
+              9.941129e+01, 9.941129e+01, 1.000000e+02, 1.000000e+02,
+              1.000000e+02, 1.000000e+02, 1.000000e+02, 1.000000e+02])
+        y1 = np.around(p[p.settings['quantity']], decimals=5)
+        y2 = np.around(eA[eA.settings['quantity']], decimals=5)
+        y3 = np.around(eB[eB.settings['quantity']], decimals=5)
+        y = np.concatenate((y1, y2, y3))
+        times = ['pore.concentration.Na_mix_01@5000',
+                 'pore.concentration.Cl_mix_01@5000', 'pore.potential@5000',
+                 'pore.concentration.Na_mix_01@10000',
+                 'pore.concentration.Cl_mix_01@10000', 'pore.potential@10000',
+                 'pore.concentration.Na_mix_01@15000',
+                 'pore.concentration.Cl_mix_01@15000', 'pore.potential@15000',
+                 'pore.concentration.Na_mix_01@19500',
+                 'pore.concentration.Cl_mix_01@19500', 'pore.potential@19500']
+        assert np.all(x == y)
+        assert (set(times).issubset(set(self.phase.keys())))
+
+    def teardown_class(self):
+        ws = op.Workspace()
+        ws.clear()
+
+
+if __name__ == '__main__':
+
+    t = TransientIonicTransportTest()
+    t.setup_class()
+    for item in t.__dir__():
+        if item.startswith('test'):
+            print('running test: '+item)
+            t.__getattribute__(item)()
+    self = t