From 3547ccf9ba9dcc0736f7321b30cc4ae4adffa8e0 Mon Sep 17 00:00:00 2001
From: Ian Bell <ian.bell@nist.gov>
Date: Thu, 18 Aug 2022 12:54:30 -0400
Subject: [PATCH] Back to working with the variants

---
 CMakeLists.txt                  |  4 ++-
 interface/CPP/bench_teqpcpp.cpp | 46 +++++++++++++++++++++++++
 interface/CPP/teqpcpp.cpp       |  7 ++--
 interface/CPP/teqpcpp.hpp       |  7 ++--
 interface/CPP/test_teqpcpp.cpp  | 59 ++++++++-------------------------
 5 files changed, 70 insertions(+), 53 deletions(-)
 create mode 100644 interface/CPP/bench_teqpcpp.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9278fff..463f282 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -84,7 +84,9 @@ target_link_libraries(teqpcpp PUBLIC teqpinterface PUBLIC autodiff)
 
 if (TEQP_TESTTEQPCPP)
   add_executable(test_teqpcpp "${CMAKE_CURRENT_SOURCE_DIR}/interface/CPP/test_teqpcpp.cpp")
-  target_link_libraries(test_teqpcpp PUBLIC teqpcpp PRIVATE Catch2WithMain)
+  target_link_libraries(test_teqpcpp PUBLIC teqpcpp)
+  add_executable(bench_teqpcpp "${CMAKE_CURRENT_SOURCE_DIR}/interface/CPP/bench_teqpcpp.cpp")
+  target_link_libraries(bench_teqpcpp PUBLIC teqpcpp PRIVATE Catch2WithMain)
 endif()
 
 if (TEQP_JAVASCRIPT_MODULE)
diff --git a/interface/CPP/bench_teqpcpp.cpp b/interface/CPP/bench_teqpcpp.cpp
new file mode 100644
index 0000000..3acb69e
--- /dev/null
+++ b/interface/CPP/bench_teqpcpp.cpp
@@ -0,0 +1,46 @@
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/benchmark/catch_benchmark_all.hpp>
+
+#include "teqpcpp.hpp"
+
+using namespace teqp::cppinterface;
+
+#include "teqp/derivs.hpp"
+
+using namespace teqp;
+
+TEST_CASE("Test C++ interface", "[C++]")
+{
+    auto modelnovar = teqp::build_multifluid_model({ "Methane","Ethane" }, "../mycp");
+    teqp::AllowedModels model = modelnovar;
+    auto z = (Eigen::ArrayXd(2) << 0.5, 0.5).finished();
+    SECTION("Ar01") {
+        double Ar01 = get_Arxy(model, 0, 1, 300, 3, z);
+    }
+    SECTION("critical trace") {
+        double Tc1 = modelnovar.redfunc.Tc(0);
+        auto rhovec0 = (Eigen::ArrayXd(2) << 1/modelnovar.redfunc.vc(0), 0).finished();
+        auto cr = trace_critical_arclength_binary(model, Tc1, rhovec0);
+        std::cout << cr.dump(1) << std::endl;
+    }
+}
+
+TEST_CASE("Benchmark C++ interface", "[C++]")
+{
+    teqp::AllowedModels model = teqp::build_multifluid_model({ "Methane", "Ethane"}, "../mycp");
+    auto z = (Eigen::ArrayXd(2) << 0.5, 0.5).finished();
+    
+    auto model1novar = teqp::build_multifluid_model({ "Methane" }, "../mycp");
+    teqp::AllowedModels model1 = model1novar;
+    auto z1 = (Eigen::ArrayXd(1) << 1).finished();
+    
+    BENCHMARK("Ar01 two components") {
+        return get_Arxy(model, 0, 1, 300, 3, z);
+    }; 
+    BENCHMARK("Ar01 one component w/ Arxy (runtime lookup)") {
+        return get_Arxy(model1, 0, 1, 300, 3, z1);
+    }; 
+    BENCHMARK("Ar01 one component w/ Ar01 directly") {
+        return TDXDerivatives<decltype(model1novar)>::get_Arxy<0,1,ADBackends::autodiff>(model1novar, 300, 3, z1);
+    }; 
+}
diff --git a/interface/CPP/teqpcpp.cpp b/interface/CPP/teqpcpp.cpp
index 331bcd6..4706160 100644
--- a/interface/CPP/teqpcpp.cpp
+++ b/interface/CPP/teqpcpp.cpp
@@ -1,20 +1,17 @@
-// Pulls in the AllowedModels variant
 #include "teqp/models/fwd.hpp"
 
 #include "teqpcpp.hpp"
 #include "teqp/derivs.hpp"
 #include "teqp/algorithms/critical_tracing.hpp"
 
-double teqp::cppinterface::get_Arxy(const void* modelptr, const int NT, const int ND, const double T, const double rho, const Eigen::ArrayXd &molefracs){
-    const teqp::AllowedModels& model = *static_cast<const teqp::AllowedModels*>(modelptr);
+double teqp::cppinterface::get_Arxy(const teqp::AllowedModels& model, const int NT, const int ND, const double T, const double rho, const Eigen::ArrayXd &molefracs){
     return std::visit([&](const auto& model) {
         using tdx = teqp::TDXDerivatives<decltype(model), double, std::decay_t<decltype(molefracs)>>;
         return tdx::template get_Ar(NT, ND, model, T, rho, molefracs);
     }, model);
 }
 
-nlohmann::json teqp::cppinterface::trace_critical_arclength_binary(const void* modelptr, const double T0, const Eigen::ArrayXd &rhovec0) {
-    const teqp::AllowedModels& model = *static_cast<const teqp::AllowedModels*>(modelptr);
+nlohmann::json teqp::cppinterface::trace_critical_arclength_binary(const teqp::AllowedModels& model, const double T0, const Eigen::ArrayXd &rhovec0) {
     return std::visit([&](const auto& model) {
         using crit = teqp::CriticalTracing<decltype(model), double, std::decay_t<decltype(rhovec0)>>;
         return crit::trace_critical_arclength_binary(model, T0, rhovec0, "");
diff --git a/interface/CPP/teqpcpp.hpp b/interface/CPP/teqpcpp.hpp
index 628c847..2b0de35 100644
--- a/interface/CPP/teqpcpp.hpp
+++ b/interface/CPP/teqpcpp.hpp
@@ -3,11 +3,14 @@
 #include <Eigen/Dense>
 #include "nlohmann/json.hpp"
 
+// Pulls in the AllowedModels variant
+#include "teqp/models/fwd.hpp"
+
 namespace teqp {
     namespace cppinterface {
 
         // Wrapper functions
-        double get_Arxy(const void* model, const int NT, const int ND, const double T, const double rho, const Eigen::ArrayXd& molefracs);
-        nlohmann::json trace_critical_arclength_binary(const void* model, const double T0, const Eigen::ArrayXd& rhovec0);
+        double get_Arxy(const teqp::AllowedModels& model, const int NT, const int ND, const double T, const double rho, const Eigen::ArrayXd& molefracs);
+        nlohmann::json trace_critical_arclength_binary(const teqp::AllowedModels& model, const double T0, const Eigen::ArrayXd& rhovec0);
     }
 }
\ No newline at end of file
diff --git a/interface/CPP/test_teqpcpp.cpp b/interface/CPP/test_teqpcpp.cpp
index 2644aca..326ed77 100644
--- a/interface/CPP/test_teqpcpp.cpp
+++ b/interface/CPP/test_teqpcpp.cpp
@@ -1,49 +1,18 @@
-#include <catch2/catch_test_macros.hpp>
-#include <catch2/benchmark/catch_benchmark_all.hpp>
+/**
+* This is a minimal example of the use of the C++ interface around teqp
+* 
+* The point of the interface is to reduce compilation time, as compilation 
+* of this file should be MUCH faster than compilation with the full set of 
+* algorithms and models because the template instantiations are all included in the 
+* library that this file is linked against and the compiler does not need to resolve
+* all the templates every time this file is compiled
+*/
 
-#include "teqpcpp.hpp"
-
-using namespace teqp::cppinterface;
-
-// Pulls in the AllowedModels variant
-#include "teqp/models/fwd.hpp"
-
-#include "teqp/derivs.hpp"
 
-using namespace teqp;
-
-TEST_CASE("Test C++ interface", "[C++]")
-{
-    auto modelnovar = teqp::build_multifluid_model({ "Methane","Ethane" }, "../mycp");
-    teqp::AllowedModels model = modelnovar;
-    auto z = (Eigen::ArrayXd(2) << 0.5, 0.5).finished();
-    SECTION("Ar01") {
-        double Ar01 = get_Arxy(&model, 0, 1, 300, 3, z);
-    }
-    SECTION("critical trace") {
-        double Tc1 = modelnovar.redfunc.Tc(0);
-        auto rhovec0 = (Eigen::ArrayXd(2) << 1/modelnovar.redfunc.vc(0), 0).finished();
-        auto cr = trace_critical_arclength_binary(&model, Tc1, z);
-        std::cout << cr.dump(1) << std::endl;
-    }
-}
+#include "teqpcpp.hpp"
 
-TEST_CASE("Benchmark C++ interface", "[C++]")
-{
-    teqp::AllowedModels model = teqp::build_multifluid_model({ "Methane", "Ethane"}, "../mycp");
+int main() {
+    teqp::AllowedModels model = teqp::build_multifluid_model({ "Methane", "Ethane" }, "../mycp");
     auto z = (Eigen::ArrayXd(2) << 0.5, 0.5).finished();
-    
-    auto model1novar = teqp::build_multifluid_model({ "Methane" }, "../mycp");
-    teqp::AllowedModels model1 = model1novar;
-    auto z1 = (Eigen::ArrayXd(1) << 1).finished(); 
-    
-    BENCHMARK("Ar01 two components") {
-        return get_Arxy(&model, 0, 1, 300, 3, z);
-    }; 
-    BENCHMARK("Ar01 one component w/ Arxy (runtime lookup)") {
-        return get_Arxy(&model1, 0, 1, 300, 3, z1);
-    }; 
-    BENCHMARK("Ar01 one component w/ Ar01 directly") {
-        return TDXDerivatives<decltype(model1novar)>::get_Arxy<0,1,ADBackends::autodiff>(model1novar, 300, 3, z1);
-    }; 
-}
+    double Ar01 = teqp::cppinterface::get_Arxy(model, 0, 1, 300, 3, z);
+}
\ No newline at end of file
-- 
GitLab