From 508aeda5397a6f8c0a954cba686cd64282f8e50d Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Mon, 2 Dec 2024 23:36:08 -0500 Subject: [PATCH] [Transport] Make fitting errors accessible programmatically --- include/cantera/transport/Transport.h | 15 ++++++++++++++- interfaces/cython/cantera/transport.pxd | 2 +- interfaces/cython/cantera/transport.pyx | 17 +++++++++++++++++ src/transport/GasTransport.cpp | 10 ++++++++-- src/transport/IonGasTransport.cpp | 6 ++++++ test/python/test_transport.py | 6 ++++++ 6 files changed, 52 insertions(+), 4 deletions(-) diff --git a/include/cantera/transport/Transport.h b/include/cantera/transport/Transport.h index 04b6b2ead1..98594a3833 100644 --- a/include/cantera/transport/Transport.h +++ b/include/cantera/transport/Transport.h @@ -20,12 +20,12 @@ #include "cantera/base/ct_defs.h" #include "cantera/base/ctexceptions.h" +#include "cantera/base/AnyMap.h" namespace Cantera { class ThermoPhase; -class AnyMap; /** * @addtogroup tranprops @@ -389,6 +389,16 @@ class Transport //! separately. AnyMap parameters() const; + //! Get error metrics about any functional fits calculated for pure species + //! transport properties. + //! + //! See GasTransport::fitDiffCoeffs and GasTransport::fitProperties. + //! + //! @warning This method is an experimental part of the %Cantera API and may be + //! changed or removed without notice. + //! @since New in %Cantera 3.1. + AnyMap fittingErrors() const { return m_fittingErrors; }; + //! @name Transport manager construction //! //! These methods are used during construction. @@ -421,6 +431,9 @@ class Transport //! Number of species size_t m_nsp = 0; + + //! Maximum errors associated with fitting pure species transport properties. + AnyMap m_fittingErrors; }; } diff --git a/interfaces/cython/cantera/transport.pxd b/interfaces/cython/cantera/transport.pxd index 6e76ba5945..0a57c4894a 100644 --- a/interfaces/cython/cantera/transport.pxd +++ b/interfaces/cython/cantera/transport.pxd @@ -18,7 +18,7 @@ cdef extern from "cantera/transport/Transport.h" namespace "Cantera": void getSpeciesViscosities(double*) except +translate_exception void getCollisionIntegralPolynomial(size_t i, size_t j, double* dataA, double* dataB, double* dataC) except +translate_exception void setCollisionIntegralPolynomial(size_t i, size_t j, double* dataA, double* dataB, double* dataC, cbool flag) except +translate_exception - + CxxAnyMap fittingErrors() cdef extern from "cantera/transport/DustyGasTransport.h" namespace "Cantera": cdef cppclass CxxDustyGasTransport "Cantera::DustyGasTransport": diff --git a/interfaces/cython/cantera/transport.pyx b/interfaces/cython/cantera/transport.pyx index 6fbbded864..600dfb242f 100644 --- a/interfaces/cython/cantera/transport.pyx +++ b/interfaces/cython/cantera/transport.pyx @@ -393,6 +393,23 @@ cdef class Transport(_SolutionBase): self.transport.setCollisionIntegralPolynomial(i, j, &adata[0], &bdata[0], &cdata[0], actualT) + property transport_fitting_errors: + """ + Get error metrics about any functional fits calculated for pure species + transport properties. See {ct}`GasTransport::fitDiffCoeffs` and + {ct}`GasTransport::fitProperties`. + + .. warning:: + + This property is an experimental part of the Cantera API and + may be changed or removed without notice. + + .. versionadded:: 3.1 + """ + def __get__(self): + cdef CxxAnyMap stats = self.transport.fittingErrors() + return anymap_to_py(stats) + cdef class DustyGasTransport(Transport): """ Implements the "dusty gas" model for transport in porous media. diff --git a/src/transport/GasTransport.cpp b/src/transport/GasTransport.cpp index aebccaee91..ab13ea5e77 100644 --- a/src/transport/GasTransport.cpp +++ b/src/transport/GasTransport.cpp @@ -616,6 +616,8 @@ void GasTransport::fitProperties(MMCollisionInt& integrals) mxerr = std::max(mxerr, fabs(err)); mxrelerr = std::max(mxrelerr, fabs(relerr)); } + m_fittingErrors["viscosity-max-abs-error"] = mxerr; + m_fittingErrors["viscosity-max-rel-error"] = mxrelerr; // evaluate max fit errors for conductivity for (size_t n = 0; n < np; n++) { @@ -635,6 +637,8 @@ void GasTransport::fitProperties(MMCollisionInt& integrals) } m_visccoeffs.push_back(c); m_condcoeffs.push_back(c2); + m_fittingErrors["conductivity-max-abs-error"] = mxerr_cond; + m_fittingErrors["conductivity-max-rel-error"] = mxrelerr_cond; if (m_log_level >= 2) { writelog(m_thermo->speciesName(k) + ": [" + vec2str(c) + "]\n"); @@ -690,8 +694,7 @@ void GasTransport::fitDiffCoeffs(MMCollisionInt& integrals) // vector of polynomial coefficients vector c(degree + 1), c2(degree + 1); - double err, relerr, - mxerr = 0.0, mxrelerr = 0.0; + double err, relerr, mxerr = 0.0, mxrelerr = 0.0; vector diff(np + 1); m_diffcoeffs.clear(); @@ -744,6 +747,9 @@ void GasTransport::fitDiffCoeffs(MMCollisionInt& integrals) } } } + + m_fittingErrors["diff-coeff-max-abs-error"] = mxerr; + m_fittingErrors["diff-coeff-max-rel-error"] = mxrelerr; if (m_log_level) { writelogf("Maximum binary diffusion coefficient absolute error:" " %12.6g\n", mxerr); diff --git a/src/transport/IonGasTransport.cpp b/src/transport/IonGasTransport.cpp index f149e94236..3cd12608e9 100644 --- a/src/transport/IonGasTransport.cpp +++ b/src/transport/IonGasTransport.cpp @@ -235,6 +235,12 @@ void IonGasTransport::fitDiffCoeffs(MMCollisionInt& integrals) } } } + m_fittingErrors["diff-coeff-max-abs-error"] = + std::max(m_fittingErrors.getDouble("diff-coeff-max-abs-error", 0.0), + mxerr); + m_fittingErrors["diff-coeff-max-rel-error"] = + std::max(m_fittingErrors.getDouble("diff-coeff-max-rel-error", 0.0), + mxrelerr); if (m_log_level) { writelogf("Maximum binary diffusion coefficient absolute error:" diff --git a/test/python/test_transport.py b/test/python/test_transport.py index 58362c7b3e..62820e2162 100644 --- a/test/python/test_transport.py +++ b/test/python/test_transport.py @@ -71,13 +71,19 @@ def test_mixDiffCoeffsChange(self, phase): def test_CK_mode(self, phase): mu_ct = phase.viscosity + err_ct = phase.transport_fitting_errors phase.transport_model = 'mixture-averaged-CK' assert phase.transport_model == 'mixture-averaged-CK' mu_ck = phase.viscosity + err_ck = phase.transport_fitting_errors # values should be close, but not identical assert abs(mu_ct - mu_ck) / mu_ct > 1e-8 assert abs(mu_ct - mu_ck) / mu_ct < 1e-2 + # Cantera's fits should be an improvement in all cases + for key in err_ct: + assert err_ct[key] < err_ck[key] + def test_ionGas(self, phase): # IonGasTransport gives the same result for a mixture # without ionized species