diff --git a/include/teqp/derivs.hpp b/include/teqp/derivs.hpp
index c2bd36da96c488eac4db372e49a784b9620d51b1..0cd43582519d8c44df2681b03456109d1d22d5e1 100644
--- a/include/teqp/derivs.hpp
+++ b/include/teqp/derivs.hpp
@@ -6,37 +6,29 @@ caller(const FuncType& f, TType T, const ContainerType& rho) {
     return f(T, rho);
 }
 
-/// Given a 
+/// Given a function, use complex step derivatives to calculate the derivative with respect to the first variable
+/// which here is temperature
 template <typename TType, typename ContainerType, typename FuncType>
 typename std::enable_if<is_container<ContainerType>::value, typename ContainerType::value_type>::type
-deriv1(const FuncType& f, TType T, const ContainerType& rho) {
+derivT(const FuncType& f, TType T, const ContainerType& rho) {
     double h = 1e-100;
     return f(std::complex<TType>(T, h), rho).imag() / h;
 }
 
-template <typename TType, typename ContainerType, typename FuncType>
+/// Given a function, use complex step derivatives to calculate the derivative with respect to the first composition variable
+template <typename TType, typename ContainerType, typename FuncType, typename Integer>
 typename std::enable_if<is_container<ContainerType>::value, typename ContainerType::value_type>::type
-deriv2(const FuncType& f, TType T, const ContainerType& rho) {
+derivrhoi(const FuncType& f, TType T, const ContainerType& rho, Integer j) {
     double h = 1e-100;
     using comtype = std::complex<ContainerType::value_type>;
     std::valarray<comtype> rhocom(rho.size());
-    rhocom[0] = comtype(rho[0], h);
-    for (auto i = 1; i < rho.size(); ++i) {
+    for (auto i = 0; i < rho.size(); ++i) {
         rhocom[i] = comtype(rho[i], 0.0);
     }
+    rhocom[j] = comtype(rho[j], h);
     return f(T, rhocom).imag() / h;
 }
 
-template <typename TType, typename ContainerType, typename FuncType>
-typename std::enable_if<is_container<ContainerType>::value, typename ContainerType::value_type>::type
-deriv3(const FuncType& f, TType T, const ContainerType& rho) {
-    double h = 1e-100;
-    using comtype = std::complex<ContainerType::value_type>;
-    std::valarray<comtype> rhocom(rho.size());
-    rhocom[0] = comtype(rho[0], 0.0);
-    rhocom[1] = comtype(rho[1], h);
-    return f(T, rhocom).imag() / h;
-}
 
 template<typename Model, typename TType, typename RhoType>
 auto build_Psir_Hessian(const Model& model, const TType T, const RhoType& rho) {
diff --git a/src/main.cpp b/src/main.cpp
index 9a42ddc2d37ec270519a3d4bab7008a84b8b0063..5f58eea6564774fc74150a683248fbf33473e656 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -33,8 +33,8 @@ void test_vdW() {
     auto t21 = std::chrono::steady_clock::now();
     
     auto Psir = vdW.Psir(T, rhovec);
-    auto dPsirdrho0 = rhovec[0] * deriv2([&vdW](const auto& T, const auto& rhovec) { return vdW.Psir(T, rhovec); }, T, rhovec);
-    auto dPsirdrho1 = rhovec[1] * deriv3([&vdW](const auto& T, const auto& rhovec) { return vdW.Psir(T, rhovec); }, T, rhovec);
+    auto dPsirdrho0 = rhovec[0] * derivrhoi([&vdW](const auto& T, const auto& rhovec) { return vdW.Psir(T, rhovec); }, T, rhovec, 0);
+    auto dPsirdrho1 = rhovec[1] * derivrhoi([&vdW](const auto& T, const auto& rhovec) { return vdW.Psir(T, rhovec); }, T, rhovec, 1);
     auto pfromderiv = rho * R * T - Psir + dPsirdrho0 + dPsirdrho1;
 
     auto t31 = std::chrono::steady_clock::now();
@@ -58,12 +58,12 @@ void test_vdwMix() {
     auto t2 = std::chrono::steady_clock::now();
 
     auto Psir = vdW.Psir(T, rhovec);
-    auto dPsirdrho0 = rhovec[0] * deriv2([&vdW, rhotot](const auto& T, const auto& rhovec) { return vdW.Psir(T, rhovec); }, T, rhovec);
-    auto dPsirdrho1 = rhovec[1] * deriv3([&vdW, rhotot](const auto& T, const auto& rhovec) { return vdW.Psir(T, rhovec); }, T, rhovec);
+    auto dPsirdrho0 = rhovec[0] * derivrhoi([&vdW, rhotot](const auto& T, const auto& rhovec) { return vdW.Psir(T, rhovec); }, T, rhovec, 0);
+    auto dPsirdrho1 = rhovec[1] * derivrhoi([&vdW, rhotot](const auto& T, const auto& rhovec) { return vdW.Psir(T, rhovec); }, T, rhovec, 1);
     auto pfromderiv = rho*R*T - Psir + dPsirdrho0 + dPsirdrho1;
     {
-        auto term0 = rhovec[0] * deriv2([&vdW, rhotot](const auto& T, const auto& rhovec) { return vdW.alphar(T, rhovec); }, T, rhovec);
-        auto term1 = rhovec[1] * deriv3([&vdW, rhotot](const auto& T, const auto& rhovec) { return vdW.alphar(T, rhovec); }, T, rhovec);
+        auto term0 = rhovec[0] * derivrhoi([&vdW, rhotot](const auto& T, const auto& rhovec) { return vdW.alphar(T, rhovec); }, T, rhovec, 0);
+        auto term1 = rhovec[1] * derivrhoi([&vdW, rhotot](const auto& T, const auto& rhovec) { return vdW.alphar(T, rhovec); }, T, rhovec, 1);
         auto pr = (term0 + term1)*rhotot*R*T;
         auto pfromderiv2 = rho*R*T + pr;
         auto err2 = pfromderiv / pfromderiv2 - 1;