diff --git a/interfaces/cython/cantera/test/test_kinetics.py b/interfaces/cython/cantera/test/test_kinetics.py index dc5414551..d2f38956b 100644 --- a/interfaces/cython/cantera/test/test_kinetics.py +++ b/interfaces/cython/cantera/test/test_kinetics.py @@ -370,3 +370,95 @@ class ExplicitForwardOrderTest(utilities.CanteraTest): ratio = rop2/rop1 self.assertNear(ratio[0], 2**0.5) # order of R1B is 0.5 self.assertNear(ratio[1], 2**0.2) # order of P1 is 1.0 + + +class TestSofcKinetics(utilities.CanteraTest): + """ Test based on sofc.py """ + def test_sofc(self): + mech = 'sofc-test.xml' + T = 1073.15 # T in K + P = ct.one_atm + TPB_length_per_area = 1.0e7 # TPB length per unit area [1/m] + + def newton_solve(f, xstart, C=0.0): + """ Solve f(x) = C by Newton iteration. """ + x0 = xstart + dx = 1.0e-6 + while True: + f0 = f(x0) - C + x0 -= f0/(f(x0 + dx) - C - f0)*dx + if abs(f0) < 0.00001: + return x0 + + # Anode-side phases + gas_a, anode_bulk, oxide_a = ct.import_phases(mech, + ['gas', 'metal', 'oxide_bulk',]) + anode_surf = ct.Interface(mech, 'metal_surface', [gas_a]) + oxide_surf_a = ct.Interface(mech, 'oxide_surface', [gas_a, oxide_a]) + tpb_a = ct.Interface(mech, 'tpb', [anode_bulk, anode_surf, oxide_surf_a]) + + # Cathode-side phases + gas_c, cathode_bulk, oxide_c = ct.import_phases(mech, + ['gas', 'metal', 'oxide_bulk']) + cathode_surf = ct.Interface(mech, 'metal_surface', [gas_c]) + oxide_surf_c = ct.Interface(mech, 'oxide_surface', [gas_c, oxide_c]) + tpb_c = ct.Interface(mech, 'tpb', [cathode_bulk, cathode_surf, + oxide_surf_c]) + + def anode_curr(E): + anode_bulk.electric_potential = E + w = tpb_a.net_production_rates + return ct.faraday * w[0] * TPB_length_per_area + + def cathode_curr(E): + cathode_bulk.electric_potential = E + oxide_c.electric_potential + w = tpb_c.net_production_rates + return -ct.faraday * w[0] * TPB_length_per_area + + # initialization + gas_a.TPX = T, P, 'H2:0.97, H2O:0.03' + gas_a.equilibrate('TP') + gas_c.TPX = T, P, 'O2:1.0, H2O:0.001' + gas_c.equilibrate('TP') + + for p in [anode_bulk, anode_surf, oxide_surf_a, oxide_a, cathode_bulk, + cathode_surf, oxide_surf_c, oxide_c, tpb_a, tpb_c]: + p.TP = T, P + + for s in [anode_surf, oxide_surf_a, cathode_surf, oxide_surf_c]: + s.advance_coverages(50.0) + + # These values are just a regression test with no theoretical basis + self.assertArrayNear(anode_surf.coverages, + [6.18736755e-01, 3.81123779e-01, 8.63037850e-05, + 2.59274708e-06, 5.05702339e-05]) + self.assertArrayNear(oxide_surf_a.coverages, + [4.99435780e-02, 9.48927983e-01, 1.12840577e-03, + 3.35936530e-08]) + self.assertArrayNear(cathode_surf.coverages, + [1.48180380e-07, 7.57234727e-14, 9.99999827e-01, + 2.49235513e-08, 4.03296469e-13]) + self.assertArrayNear(oxide_surf_c.coverages, + [4.99896947e-02, 9.49804199e-01, 2.06104969e-04, + 1.11970271e-09]) + + Ea0 = newton_solve(anode_curr, xstart=-0.51) + Ec0 = newton_solve(cathode_curr, xstart=0.51) + + data = [] + + # vary the anode overpotential, from cathodic to anodic polarization + for Ea in np.linspace(Ea0 - 0.25, Ea0 + 0.25, 20): + anode_bulk.electric_potential = Ea + curr = anode_curr(Ea) + delta_V = curr * 5.0e-5 / 2.0 + phi_oxide_c = -delta_V + oxide_c.electric_potential = phi_oxide_c + oxide_surf_c.electric_potential = phi_oxide_c + Ec = newton_solve(cathode_curr, xstart=Ec0+0.1, C=curr) + cathode_bulk.electric_potential = phi_oxide_c + Ec + data.append([Ea - Ea0, 0.1*curr, Ec - Ec0, delta_V, + cathode_bulk.electric_potential - + anode_bulk.electric_potential]) + + self.compare(data, '../data/sofc-test.csv') diff --git a/interfaces/cython/cantera/test/utilities.py b/interfaces/cython/cantera/test/utilities.py index d2d2a2ef2..7cc3385bb 100644 --- a/interfaces/cython/cantera/test/utilities.py +++ b/interfaces/cython/cantera/test/utilities.py @@ -38,6 +38,7 @@ class CanteraTest(unittest.TestCase): Compare an array with a reference data file, or generate the reference file if it does not exist. """ + data = np.array(data) if os.path.exists(reference_file): # Compare with existing output file ref = np.genfromtxt(reference_file) diff --git a/test/data/sofc-test.csv b/test/data/sofc-test.csv new file mode 100644 index 000000000..dd04db391 --- /dev/null +++ b/test/data/sofc-test.csv @@ -0,0 +1,20 @@ +-2.5000000000e-01 -1.3798766169e+03 5.2791044253e-01 -3.4496915423e-01 2.2604563283e+00 +-2.2368421053e-01 -1.0432408592e+03 5.0204892914e-01 -2.6081021480e-01 2.1241200860e+00 +-1.9736842105e-01 -7.8701558438e+02 4.7598665116e-01 -1.9675389610e-01 2.0076856998e+00 +-1.7105263158e-01 -5.9105676488e+02 4.4950960410e-01 -1.4776419122e-01 1.9059031584e+00 +-1.4473684211e-01 -4.4005464536e+02 4.2223216105e-01 -1.1001366134e-01 1.8145593960e+00 +-1.1842105263e-01 -3.2229910744e+02 3.9344175087e-01 -8.0574776860e-02 1.7300143119e+00 +-9.2105263158e-02 -2.2873716932e+02 3.6174919496e-01 -5.7184292329e-02 1.6486154820e+00 +-6.5789473684e-02 -1.5224602946e+02 3.2415056354e-01 -3.8061507365e-02 1.5655782761e+00 +-3.9473684211e-02 -8.7062613477e+01 2.7263908630e-01 -2.1765653369e-02 1.4714551554e+00 +-1.3157894737e-02 -2.8323325267e+01 1.7086445717e-01 -7.0808313166e-03 1.3286799147e+00 +1.3157894737e-02 2.8323325267e+01 -1.7086445717e-01 7.0808313166e-03 9.4647354829e-01 +3.9473684211e-02 8.7062613477e+01 -2.7263908630e-01 2.1765653369e-02 8.0369830764e-01 +6.5789473684e-02 1.5224602946e+02 -3.2415056354e-01 3.8061507365e-02 7.0957518693e-01 +9.2105263158e-02 2.2873716932e+02 -3.6174919496e-01 5.7184292329e-02 6.2653798107e-01 +1.1842105263e-01 3.2229910744e+02 -3.9344175086e-01 8.0574776859e-02 5.4513915116e-01 +1.4473684211e-01 4.4005464536e+02 -4.2223216105e-01 1.1001366134e-01 4.6059406702e-01 +1.7105263158e-01 5.9105676488e+02 -4.4950960410e-01 1.4776419122e-01 3.6925030461e-01 +1.9736842105e-01 7.8701558438e+02 -4.7598665116e-01 1.9675389609e-01 2.6746776321e-01 +2.2368421053e-01 1.0432408592e+03 -5.0204892914e-01 2.6081021480e-01 1.5103337706e-01 +2.5000000000e-01 1.3798766169e+03 -5.2791044253e-01 3.4496915423e-01 1.4697134765e-02 diff --git a/test/data/sofc-test.xml b/test/data/sofc-test.xml new file mode 100644 index 000000000..1c5570d3f --- /dev/null +++ b/test/data/sofc-test.xml @@ -0,0 +1,441 @@ + + + + + + + H O N + H2 H2O N2 O2 + + 1073.15 + 101325.0 + H2:0.95, H2O:0.05 + + + + + + + + + E + electron + + 1073.15 + electron:1.0 + + + 9.0 + + + + + + + + O E + Ox VO** + + 1073.15 + 101325.0 + Ox:0.95 VO**:0.05 + + + 0.7 + + + + + + + + H O + (m) H(m) O(m) OH(m) H2O(m) + + + + + 973.0 + (m):0.5 H(m):0.5 + + + 2.6e-09 + + + + gas + + + + + O H E + (ox) O''(ox) OH'(ox) H2O(ox) + + + + + 1073.15 + O''(ox):2.0, (ox):0.0 + + + 2e-09 + + + + gas oxide_bulk + + + + + H O + (tpb) + + + + + 1073.15 + (tpb):1.0 + + + 5e-17 + + + + metal metal_surface oxide_surface + + + + + + + + E:1 + -1 + + + 298.15 + 0.0 + 0.0 + 0.0 + + + + + + + + + + 298.15 + 0.0 + 0.0 + 0.0 + + + + + + + E:2 O:1 + -2 + + + 298.15 + -170.0 + 50.0 + 0.0 + + + + + + + + + + 298.15 + 0.0 + 0.0 + 0.0 + + + + + + + H:1 + + + 298.15 + -35.0 + 37.0 + 0.0 + + + + + + + O:1 + + + 298.15 + -220.0 + 37.0 + 0.0 + + + + + + + H:1 O:1 + + + 298.15 + -198.0 + 102.0 + 0.0 + + + + + + + H:2 O:1 + + + 298.15 + -281.0 + 123.0 + 0.0 + + + + + + + E:2 O:1 + -2 + + + 298.15 + -170.0 + 50.0 + 0.0 + + + + + + + H:1 E:1 O:1 + -1 + + + 298.15 + -220.0 + 87.0 + 0.0 + + + + + + + + + + 298.15 + 0.0 + 0.0 + 0.0 + + + + + + + H:2 O:1 + + + 298.15 + -265.0 + 98.0 + 0.0 + + + + + + + + + + 298.15 + 0.0 + 0.0 + 0.0 + + + + + + + + + H2 + (m) + (m) [=] H(m) + H(m) + + + 1.000000E-01 + 0 + 0.000000 + + + H2:1.0 (m):2 + H(m):2.0 + + + + + O2 + (m) + (m) [=] O(m) + O(m) + + + 1.000000E-01 + 0 + 0.000000 + + + O2:1.0 (m):2 + O(m):2.0 + + + + + H2O + (m) [=] H2O(m) + + + 1.000000E+00 + 0 + 0.000000 + + + H2O:1.0 (m):1 + H2O(m):1.0 + + + + + H(m) + O(m) [=] OH(m) + (m) + + + 5.000000E+21 + 0 + 100.000000 + + + H(m):1.0 O(m):1 + OH(m):1.0 (m):1 + + + + + H(m) + OH(m) [=] H2O(m) + (m) + + + 5.000000E+19 + 0 + 40.000000 + + + H(m):1.0 OH(m):1 + H2O(m):1.0 (m):1 + + + + + OH(m) + OH(m) [=] H2O(m) + O(m) + + + 5.000000E+20 + 0 + 100.000000 + + + OH(m):2.0 + H2O(m):1.0 O(m):1 + + + + + (ox) + Ox [=] VO** + O''(ox) + + + 5.000000E+05 + 0.0 + 0.000000 + + + (ox):1.0 Ox:1 + O''(ox):1 VO**:1.0 + + + + + H2O(ox) [=] H2O + (ox) + + + 1.000000E+14 + 0.0 + 0.000000 + + + H2O(ox):1.0 + H2O:1.0 (ox):1 + + + + + H2O(ox) + O''(ox) [=] OH'(ox) + OH'(ox) + + + 1.000000E+13 + 0.0 + 0.000000 + + + H2O(ox):1.0 O''(ox):1 + OH'(ox):2.0 + + + + + H(m) + O''(ox) [=] (m) + electron + OH'(ox) + + + + 5.000000E+10 + 0.0 + 120.000000 + + + O''(ox):1 H(m):1.0 + OH'(ox):1 electron:1 (m):1.0 + + + + + O(m) + (ox) + 2 electron [=] (m) + O''(ox) + + + + 5.000000E+10 + 0.0 + 120.000000 + + + (ox):1 O(m):1.0 electron:2.0 + O''(ox):1 (m):1.0 + + +