From dee99e0eccb7ce3cccc016cc7eaa343ccf91f3d6 Mon Sep 17 00:00:00 2001 From: Cheng Li Date: Thu, 2 Jul 2026 16:39:48 -0400 Subject: [PATCH 1/2] wip --- src/func_table.cpp | 26 +++++++------- src/func_table.cu | 2 ++ src/vapors/vapor_functions.h | 12 +++++++ tests/CMakeLists.txt | 1 + tests/test_vapor_functions.cpp | 62 ++++++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 12 deletions(-) create mode 100644 tests/test_vapor_functions.cpp diff --git a/src/func_table.cpp b/src/func_table.cpp index c5bab1e0..72aa87a7 100644 --- a/src/func_table.cpp +++ b/src/func_table.cpp @@ -8,20 +8,22 @@ namespace kintera { ///// func1 registry ///// user_func1 func1_table_cpu[] = { - h2o_ideal, h2o_ideal_ddT, nh3_ideal, nh3_ideal_ddT, - nh3_h2s_lewis, nh3_h2s_lewis_ddT, h2s_ideal, h2s_ideal_ddT, - h2s_antoine, h2s_antoine_ddT, ch4_ideal, ch4_ideal_ddT, - so2_antoine, so2_antoine_ddT, co2_antoine, co2_antoine_ddT, - kcl_lodders, kcl_lodders_ddT, na_h2s_visscher, na_h2s_visscher_ddT}; + h2o_ideal, h2o_ideal_ddT, h2o_bryan, h2o_bryan_ddT, + nh3_ideal, nh3_ideal_ddT, nh3_h2s_lewis, nh3_h2s_lewis_ddT, + h2s_ideal, h2s_ideal_ddT, h2s_antoine, h2s_antoine_ddT, + ch4_ideal, ch4_ideal_ddT, so2_antoine, so2_antoine_ddT, + co2_antoine, co2_antoine_ddT, kcl_lodders, kcl_lodders_ddT, + na_h2s_visscher, na_h2s_visscher_ddT}; std::vector func1_names = { - "h2o_ideal", "h2o_ideal_ddT", "nh3_ideal", - "nh3_ideal_ddT", "nh3_h2s_lewis", "nh3_h2s_lewis_ddT", - "h2s_ideal", "h2s_ideal_ddT", "h2s_antoine", - "h2s_antoine_ddT", "ch4_ideal", "ch4_ideal_ddT", - "so2_antoine", "so2_antoine_ddT", "co2_antoine", - "co2_antoine_ddT", "kcl_lodders", "kcl_lodders_ddT", - "na_h2s_visscher", "na_h2s_visscher_ddT"}; + "h2o_ideal", "h2o_ideal_ddT", "h2o_bryan", + "h2o_bryan_ddT", "nh3_ideal", "nh3_ideal_ddT", + "nh3_h2s_lewis", "nh3_h2s_lewis_ddT", "h2s_ideal", + "h2s_ideal_ddT", "h2s_antoine", "h2s_antoine_ddT", + "ch4_ideal", "ch4_ideal_ddT", "so2_antoine", + "so2_antoine_ddT", "co2_antoine", "co2_antoine_ddT", + "kcl_lodders", "kcl_lodders_ddT", "na_h2s_visscher", + "na_h2s_visscher_ddT"}; ///// func2 registry ///// diff --git a/src/func_table.cu b/src/func_table.cu index c5593feb..22482521 100644 --- a/src/func_table.cu +++ b/src/func_table.cu @@ -10,6 +10,8 @@ __device__ user_func1 func1_table_cuda[] = { nullptr, h2o_ideal, h2o_ideal_ddT, + h2o_bryan, + h2o_bryan_ddT, nh3_ideal, nh3_ideal_ddT, nh3_h2s_lewis, diff --git a/src/vapors/vapor_functions.h b/src/vapors/vapor_functions.h index 974b8e3e..ac2b6507 100644 --- a/src/vapors/vapor_functions.h +++ b/src/vapors/vapor_functions.h @@ -46,6 +46,18 @@ inline double h2o_ideal_ddT(double T) { tr; } +DISPATCH_MACRO +inline double h2o_bryan(double T) { + double beta = 24.845, delta = 4.986009, tr = 273.16, pr = 611.7; + return logsvp_ideal(T / tr, beta, delta) + log(pr); +} + +DISPATCH_MACRO +inline double h2o_bryan_ddT(double T) { + double beta = 24.845, delta = 4.986009, tr = 273.16; + return logsvp_ideal_ddT(T / tr, beta, delta) / tr; +} + DISPATCH_MACRO inline double nh3_ideal(double T) { double betal = 20.08, gammal = 5.62, betas = 20.64, gammas = 1.43, tr = 195.4, diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9a1e06c8..5b0e1a60 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,6 +10,7 @@ enable_testing() setup_test(test_reaction) setup_test(test_species) setup_test(test_thermo) +setup_test(test_vapor_functions) setup_test(test_kinetics) setup_test(test_photolysis_options) setup_test(test_photolysis_kinetics) diff --git a/tests/test_vapor_functions.cpp b/tests/test_vapor_functions.cpp new file mode 100644 index 00000000..9d894788 --- /dev/null +++ b/tests/test_vapor_functions.cpp @@ -0,0 +1,62 @@ +// external +#include + +// C/C++ +#include + +// torch +#include + +// kintera +#include +#include + +using namespace kintera; + +namespace { + +double h2o_bryan_expected(double T) { + double beta = 24.845; + double delta = 4.986009; + double tr = 273.16; + double pr = 611.7; + return (1. - tr / T) * beta - delta * std::log(T / tr) + std::log(pr); +} + +double h2o_bryan_ddT_expected(double T) { + double beta = 24.845; + double delta = 4.986009; + double tr = 273.16; + double t = T / tr; + return (beta / (t * t) - delta / t) / tr; +} + +} // namespace + +TEST(VaporFunctions, h2o_bryan_matches_athena_liquid_branch) { + for (double temp : {250.0, 273.16, 289.85, 300.0}) { + EXPECT_NEAR(h2o_bryan(temp), h2o_bryan_expected(temp), 1.e-12); + EXPECT_NEAR(h2o_bryan_ddT(temp), h2o_bryan_ddT_expected(temp), 1.e-12); + } +} + +TEST(VaporFunctions, h2o_bryan_keeps_liquid_branch_below_triple_point) { + double temp = 250.0; + EXPECT_NEAR(h2o_bryan(temp), h2o_bryan_expected(temp), 1.e-12); + EXPECT_GT(std::abs(h2o_bryan(temp) - h2o_ideal(temp)), 1.e-3); +} + +TEST(VaporFunctions, h2o_bryan_dispatches_through_log_svp) { + auto nucleation = NucleationOptionsImpl::create(); + nucleation->logsvp({"h2o_bryan"}); + LogSVPFunc::init(nucleation); + + auto temp = torch::tensor({250.0, 289.85}, torch::kFloat64); + auto logsvp = LogSVPFunc::call(temp).squeeze(-1); + auto grad = LogSVPFunc::grad(temp).squeeze(-1); + + EXPECT_NEAR(logsvp[0].item(), h2o_bryan_expected(250.0), 1.e-12); + EXPECT_NEAR(logsvp[1].item(), h2o_bryan_expected(289.85), 1.e-12); + EXPECT_NEAR(grad[0].item(), h2o_bryan_ddT_expected(250.0), 1.e-12); + EXPECT_NEAR(grad[1].item(), h2o_bryan_ddT_expected(289.85), 1.e-12); +} From 89efd031df1234b4ba8f8f6ab48cca2bcc5296d8 Mon Sep 17 00:00:00 2001 From: Cheng Li Date: Thu, 2 Jul 2026 16:44:27 -0400 Subject: [PATCH 2/2] wip --- src/func_table.cpp | 24 ++++++++++++------------ tests/test_vapor_functions.cpp | 3 ++- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/func_table.cpp b/src/func_table.cpp index 72aa87a7..1ab96a16 100644 --- a/src/func_table.cpp +++ b/src/func_table.cpp @@ -8,21 +8,21 @@ namespace kintera { ///// func1 registry ///// user_func1 func1_table_cpu[] = { - h2o_ideal, h2o_ideal_ddT, h2o_bryan, h2o_bryan_ddT, - nh3_ideal, nh3_ideal_ddT, nh3_h2s_lewis, nh3_h2s_lewis_ddT, - h2s_ideal, h2s_ideal_ddT, h2s_antoine, h2s_antoine_ddT, - ch4_ideal, ch4_ideal_ddT, so2_antoine, so2_antoine_ddT, - co2_antoine, co2_antoine_ddT, kcl_lodders, kcl_lodders_ddT, + h2o_ideal, h2o_ideal_ddT, h2o_bryan, h2o_bryan_ddT, + nh3_ideal, nh3_ideal_ddT, nh3_h2s_lewis, nh3_h2s_lewis_ddT, + h2s_ideal, h2s_ideal_ddT, h2s_antoine, h2s_antoine_ddT, + ch4_ideal, ch4_ideal_ddT, so2_antoine, so2_antoine_ddT, + co2_antoine, co2_antoine_ddT, kcl_lodders, kcl_lodders_ddT, na_h2s_visscher, na_h2s_visscher_ddT}; std::vector func1_names = { - "h2o_ideal", "h2o_ideal_ddT", "h2o_bryan", - "h2o_bryan_ddT", "nh3_ideal", "nh3_ideal_ddT", - "nh3_h2s_lewis", "nh3_h2s_lewis_ddT", "h2s_ideal", - "h2s_ideal_ddT", "h2s_antoine", "h2s_antoine_ddT", - "ch4_ideal", "ch4_ideal_ddT", "so2_antoine", - "so2_antoine_ddT", "co2_antoine", "co2_antoine_ddT", - "kcl_lodders", "kcl_lodders_ddT", "na_h2s_visscher", + "h2o_ideal", "h2o_ideal_ddT", "h2o_bryan", + "h2o_bryan_ddT", "nh3_ideal", "nh3_ideal_ddT", + "nh3_h2s_lewis", "nh3_h2s_lewis_ddT", "h2s_ideal", + "h2s_ideal_ddT", "h2s_antoine", "h2s_antoine_ddT", + "ch4_ideal", "ch4_ideal_ddT", "so2_antoine", + "so2_antoine_ddT", "co2_antoine", "co2_antoine_ddT", + "kcl_lodders", "kcl_lodders_ddT", "na_h2s_visscher", "na_h2s_visscher_ddT"}; ///// func2 registry ///// diff --git a/tests/test_vapor_functions.cpp b/tests/test_vapor_functions.cpp index 9d894788..fe101aea 100644 --- a/tests/test_vapor_functions.cpp +++ b/tests/test_vapor_functions.cpp @@ -8,9 +8,10 @@ #include // kintera -#include #include +#include + using namespace kintera; namespace {