From 5906e094d77fd772889cfd27748a11ba0327e59c Mon Sep 17 00:00:00 2001 From: Ian Bell <ian.bell@nist.gov> Date: Thu, 25 Feb 2021 13:58:49 -0500 Subject: [PATCH] Re-organize to prep for tracing --- include/teqp/critical_tracing.hpp | 226 ++++++++++++++++++++++++++++ include/teqp/models/multifluid.hpp | 25 ++-- src/multifluid.cpp | 21 +++ src/trace_critical.cpp | 227 +---------------------------- 4 files changed, 259 insertions(+), 240 deletions(-) create mode 100644 include/teqp/critical_tracing.hpp diff --git a/include/teqp/critical_tracing.hpp b/include/teqp/critical_tracing.hpp new file mode 100644 index 0000000..a618f2c --- /dev/null +++ b/include/teqp/critical_tracing.hpp @@ -0,0 +1,226 @@ +#pragma once + +/*** +* \brief Simple wrapper to sort the eigenvalues(and associated eigenvectors) in increasing order +* \param H The matrix, in this case, the Hessian matrix of Psi w.r.t.the molar concentrations +* \param values The eigenvalues +* \returns vectors The eigenvectors, as columns +* +* See https://stackoverflow.com/a/56327853 +* +* \note The input Matrix is symmetric, thus the SelfAdjointEigenSolver can be used, and returned eigenvalues +* will be real and sorted already with corresponding eigenvectors as columns +*/ +auto sorted_eigen(const Eigen::MatrixXd& H) { + Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(H); + return std::make_tuple(es.eigenvalues(), es.eigenvectors()); +} + +struct EigenData { + Eigen::ArrayXd v0, v1, eigenvalues; + Eigen::MatrixXd eigenvectorscols; +}; + +template<typename Model, typename TType, typename RhoType> +auto eigen_problem(const Model& model, const TType T, const RhoType& rhovec) { + + EigenData ed; + + auto N = rhovec.size(); + auto mask = (rhovec != 0); + + // Build the Hessian for the residual part; + auto H = build_Psir_Hessian(model, T, rhovec); + // ... and add ideal-gas terms to H + for (auto i = 0; i < N; ++i) { + if (mask[i]) { + H(i, i) += model.R * T / rhovec[i]; + } + } + + int nonzero_count = 0; + for (auto& m : mask) { + nonzero_count += (m == 1); + } + auto zero_count = N - nonzero_count; + + if (zero_count == 0) { + // Not an infinitely dilute mixture, nothing special + std::tie(ed.eigenvalues, ed.eigenvectorscols) = sorted_eigen(H); + } + else if (zero_count == 1) { + // Extract Hessian matrix without entries where rho is exactly zero + std::vector<int> indicesToKeep; + + int badindex = -1; + for (auto i = 0; i < N; ++i) { + if (mask[i]) { + indicesToKeep.push_back(i); + } + else { + badindex = i; + } + } + Eigen::MatrixXd Hprime = H(indicesToKeep, indicesToKeep); + std::cout << H << std::endl; + std::cout << Hprime << std::endl; + auto [eigenvalues, eigenvectors] = sorted_eigen(Hprime); + + // Inject values into the U^T and v0 vectors + // + // Make a padded matrix for U (with eigenvectors as rows) + Eigen::MatrixXd U = H; U.setZero(); + + // Fill in the associated elements corresponding to eigenvectors + for (auto i = 0; i < N - nonzero_count; ++i) { + U(i, indicesToKeep) = eigenvectors.col(i); // Put in the row, leaving a hole for the zero value + } + + // The last row has a 1 in the column corresponding to the pure fluid entry + // We insist that there must be only one non-zero entry + U.row(U.rows() - 1)(badindex) = 1.0; + + ed.eigenvalues = eigenvalues; + ed.eigenvectorscols = U.transpose(); + } + else { + throw std::invalid_argument("More than one non-zero concentration value found; not currently supported"); + } + ed.v0 = ed.eigenvectorscols.col(0); + ed.v1 = ed.eigenvectorscols.col(1); + return ed; +} + +struct psi1derivs { + std::valarray<double> psir, psi0, tot; + EigenData ei; +}; + +template<typename Model, typename TType, typename RhoType> +auto get_derivs(const Model& model, const TType T, const RhoType& rhovec) { + auto R = model.R; + + // Solve the complete eigenvalue problem + auto ei = eigen_problem(model, T, rhovec); + + // Ideal-gas contributions of psi0 w.r.t. sigma_1, in the same form as the residual part + std::valarray<double> psi0_derivs(0.0, 5); + psi0_derivs[0] = -1; // Placeholder, not needed + psi0_derivs[1] = -1; // Placeholder, not needed + for (auto i = 0; i < rhovec.size(); ++i) { + if (rhovec[i] != 0) { + psi0_derivs[2] += R * T * pow(ei.v0[i], 2) / rhovec[i]; // second derivative + psi0_derivs[3] += -R * T * pow(ei.v0[i], 3) / pow(rhovec[i], 2); // third derivative + psi0_derivs[4] += 2 * R * T * pow(ei.v0[i], 4) / pow(rhovec[i], 3); // fourth derivative + } + } + + // Calculate the first through fourth derivative of Psi^r w.r.t. sigma_1 + std::valarray<MultiComplex<double>> v0(ei.v0.size()); for (auto i = 0; i < ei.v0.size(); ++i) { v0[i] = ei.v0[i]; } + std::valarray<MultiComplex<double>> rhovecmcx(rhovec.size()); for (auto i = 0; i < rhovec.size(); ++i) { rhovecmcx[i] = rhovec[i]; } + using fcn_t = std::function<MultiComplex<double>(const MultiComplex<double>&)>; + fcn_t wrapper = [&rhovecmcx, &v0, &T, &model](const MultiComplex<double>& sigma_1) { + auto rhovecused = rhovecmcx + sigma_1 * v0; + return get_Psir(model, T, rhovecused); + }; + auto psir_derivs_ = diff_mcx1(wrapper, 0.0, 4, true); + auto psir_derivs = std::valarray<double>(&psir_derivs_[0], psir_derivs_.size()); + + // As a sanity check, the minimum eigenvalue of the Hessian constructed based on the molar concentrations + // must match the second derivative of psi_tot w.r.t. sigma_1. This is not always satisfied for derivatives + // with Cauchy method + //if (abs(np.min(ei.eigvals) - psitot_derivs[2]) > 1e-3){ + // print(np.min(ei.eigvals), psitot_derivs[2], rhovec) + //} + + psi1derivs psi1; + psi1.psir = psir_derivs; + psi1.psi0 = psi0_derivs; + psi1.tot = psi0_derivs + psir_derivs; + psi1.ei = ei; + return psi1; +} + +template <typename Iterable> +bool all(const Iterable& foo) { + return std::all_of(std::begin(foo), std::end(foo), [](const auto x) { return x; }); +} +template <typename Iterable> +bool any(const Iterable& foo) { + return std::any_of(std::begin(foo), std::end(foo), [](const auto x) { return x; }); +} + +template<typename Model, typename TType, typename RhoType> +auto get_drhovec_dT_crit(const Model& model, const TType T, const RhoType& rhovec) { + + // The derivatives of total Psi w.r.t.sigma_1(mcx for residual, analytic for ideal) + // Returns a tuple, with residual, ideal, total dicts with of number of derivatives, value of derivative + auto all_derivs = get_derivs(model, T, rhovec); + auto derivs = all_derivs.tot; + + // The temperature derivative of total Psi w.r.t.T from a centered finite difference in T + auto dT = 1e-7; + auto plusT = get_derivs(model, T + dT, rhovec).tot; + auto minusT = get_derivs(model, T - dT, rhovec).tot; + auto derivT = (plusT - minusT) / (2.0 * dT); + + // Solve the eigenvalue problem for the given T & rho + auto ei = all_derivs.ei; + + auto sigma2 = 2e-5 * rhovec.sum(); // This is the perturbation along the second eigenvector + + auto v1 = std::valarray<double>(&ei.v1[0], ei.v1.size()); + auto rhovec_plus = rhovec + v1 * sigma2; + auto rhovec_minus = rhovec - v1 * sigma2; + std::string stepping_desc = ""; + auto deriv_sigma2 = 0.0 * all_derivs.tot; + if (all(rhovec_minus > 0) && all(rhovec_plus > 0)) { + // Conventional centered derivative + auto plus_sigma2 = get_derivs(model, T, rhovec_plus); + auto minus_sigma2 = get_derivs(model, T, rhovec_minus); + deriv_sigma2 = (plus_sigma2.tot - minus_sigma2.tot) / (2.0 * sigma2); + stepping_desc = "conventional centered"; + } + else if (any(rhovec_minus < 0)) { + // Forward derivative in the direction of v1 + auto plus_sigma2 = get_derivs(model, T, rhovec_plus); + auto rhovec_2plus = rhovec + 2 * v1 * sigma2; + auto plus2_sigma2 = get_derivs(model, T, rhovec_2plus); + deriv_sigma2 = (-3 * derivs + 4 * plus_sigma2.tot - plus2_sigma2.tot) / (2.0 * sigma2); + stepping_desc = "forward"; + } + else if (any(rhovec_minus > 0)) { + // Negative derivative in the direction of v1 + auto minus_sigma2 = get_derivs(model, T, rhovec_minus); + auto rhovec_2minus = rhovec - 2 * v1 * sigma2; + auto minus2_sigma2 = get_derivs(model, T, rhovec_2minus); + deriv_sigma2 = (-3 * derivs + 4 * minus_sigma2.tot - minus2_sigma2.tot) / (-2.0 * sigma2); + stepping_desc = "backwards"; + } + else { + throw std::invalid_argument("This is not possible I think."); + } + + // The columns of b are from Eq. 31 and Eq. 33 + Eigen::MatrixXd b(2, 2); + b << derivs[3], derivs[4], // row is d^3\Psi/d\sigma_1^3, d^4\Psi/d\sigma_1^4 + deriv_sigma2[2], deriv_sigma2[3]; // row is d/d\sigma_2(d^3\Psi/d\sigma_1^3), d/d\sigma_2(d^3\Psi/d\sigma_1^3) + + auto LHS = (ei.eigenvectorscols * b).transpose(); + Eigen::MatrixXd RHS(2, 1); RHS << -derivT[2], -derivT[3]; + Eigen::MatrixXd drhovec_dT = LHS.colPivHouseholderQr().solve(RHS); + + // if debug: + // print('Conventional Psi^r derivs w.r.t. sigma_1:', all_derivs.psir) + // print('Conventional Psi derivs w.r.t. sigma_1:', all_derivs.tot) + // print('Derivs w.r.t. T', derivT) + // print('sigma_2', sigma2) + // print('Finite Psi derivs w.r.t. sigma_2:', deriv_sigma2) + // print('stepping', stepping) + // print("U (rows as eigenvalues)", ei.U_T.T) + // print("LHS", LHS) + // print("RHS", RHS) + // print("drhovec_dT", drhovec_dT) + + return std::valarray<double>(&drhovec_dT(0), drhovec_dT.size()); +} \ No newline at end of file diff --git a/include/teqp/models/multifluid.hpp b/include/teqp/models/multifluid.hpp index 39e9b28..8443499 100644 --- a/include/teqp/models/multifluid.hpp +++ b/include/teqp/models/multifluid.hpp @@ -49,13 +49,14 @@ public: }; template<typename ReducingFunction, typename CorrespondingTerm, typename DepartureTerm> -class MultiFluid { -private: +class MultiFluid { + +public: const ReducingFunction redfunc; const CorrespondingTerm corr; const DepartureTerm dep; -public: + const double R = get_R_gas<double>(); MultiFluid(ReducingFunction&& redfunc, CorrespondingTerm&& corr, DepartureTerm&& dep) : redfunc(redfunc), corr(corr), dep(dep) {}; @@ -79,7 +80,7 @@ public: class MultiFluidReducingFunction { private: Eigen::MatrixXd betaT, gammaT, betaV, gammaV, YT, Yv; - Eigen::ArrayXd Tc, vc; + template <typename Num> auto cube(Num x) const { @@ -91,6 +92,7 @@ private: } public: + Eigen::ArrayXd Tc, vc; template<typename ArrayLike> MultiFluidReducingFunction( @@ -125,7 +127,7 @@ public: MoleFractions::value_type sum2 = 0.0; for (auto i = 0; i < N-1; ++i){ for (auto j = i+1; j < N; ++j) { - sum2 = sum2 + 2*z[i]*z[j]*(z[i] + z[j])/(square(beta(i, j))*z[i] + z[j]) * Yij(i, j); + sum2 = sum2 + 2*z[i]*z[j]*(z[i] + z[j])/(square(beta(i, j))*z[i] + z[j])*Yij(i, j); } } @@ -329,7 +331,7 @@ private: public: Eigen::ArrayXd n, t, d, c, l, eta, beta, gamma, epsilon; - void allocate(int N) { + void allocate(std::size_t N) { auto go = [&N](Eigen::ArrayXd &v){ v.resize(N); v.setZero(); }; go(n); go(t); go(d); go(l); go(c); go(eta); go(beta); go(gamma); go(epsilon); } @@ -349,11 +351,6 @@ public: template<typename TauType, typename DeltaType> auto alphar(const TauType& tau, const DeltaType& delta) const { return (n * pow(tau, t) * pow(delta, d) * exp(-c * pow(delta, l)) * exp(-eta * (delta - epsilon).square() - beta * (tau - gamma).square())).sum(); - /*case (types::GERG2004): - return (n * pow(tau, t) * pow(delta, d) * exp(-eta * (delta - epsilon).square() - beta * (delta - gamma))).sum(); - default: - throw - 1; - }*/ } }; @@ -363,7 +360,7 @@ auto get_EOS(const std::string& coolprop_root, const std::string& name) auto j = json::parse(std::ifstream(coolprop_root + "/dev/fluids/" + name + ".json")); auto alphar = j["EOS"][0]["alphar"]; - auto ncoeff = 0; + std::size_t ncoeff = 0; const std::vector<std::string> allowable_types = {"ResidualHelmholtzPower", "ResidualHelmholtzGaussian"}; auto isallowed = [&allowable_types](const std::string &name){ for (auto &a : allowable_types){ if (name == a){return true;};} return false;}; @@ -382,9 +379,9 @@ auto get_EOS(const std::string& coolprop_root, const std::string& name) auto toeig = [](const std::vector<double>& v) -> Eigen::ArrayXd { return Eigen::Map<const Eigen::ArrayXd>(&(v[0]), v.size()); }; - auto offset = 0; + std::size_t offset = 0; for (auto &term: alphar){ - auto N = term["n"].size(); + std::size_t N = term["n"].size(); auto eigorzero = [&term, &toeig, &N](const std::string& name) -> Eigen::ArrayXd { if (!term[name].empty()) { diff --git a/src/multifluid.cpp b/src/multifluid.cpp index a6f30b1..c1fc264 100644 --- a/src/multifluid.cpp +++ b/src/multifluid.cpp @@ -1,5 +1,6 @@ #include "teqp/core.hpp" #include "teqp/models/multifluid.hpp" +#include "teqp/critical_tracing.hpp" auto build_multifluid_model(const std::vector<std::string>& components) { using namespace nlohmann; @@ -21,8 +22,28 @@ auto build_multifluid_model(const std::vector<std::string>& components) { ); } +//void trace() { +// auto model = build_multifluid_model({ "methane", "ethane" }); +// auto rhoc0 = 1.0/model.redfunc.vc[0]; +// auto T = model.redfunc.Tc[0]; +// const auto dT = 1; +// std::valarray<double> rhovec = { rhoc0, 0.0 }; +// for (auto iter = 0; iter < 1000; ++iter) { +// auto drhovecdT = get_drhovec_dT_crit(model, T, rhovec); +// rhovec += drhovecdT * dT; +// T += dT; +// int rr = 0; +// auto z0 = rhovec[0] / rhovec.sum(); +// std::cout << z0 << " ," << rhovec[0] << "," << T << std::endl; +// if (z0 < 0) { +// break; +// } +// } +//} + int main(){ //test_dummy(); + //trace(); auto model = build_multifluid_model({ "methane", "ethane" }); std::valarray<double> rhovec = { 1.0, 2.0 }; auto alphar = model.alphar(300.0, rhovec); diff --git a/src/trace_critical.cpp b/src/trace_critical.cpp index 6b21b10..da907fa 100644 --- a/src/trace_critical.cpp +++ b/src/trace_critical.cpp @@ -4,231 +4,7 @@ #include <iostream> #include "teqp/core.hpp" - -/*** -* \brief Simple wrapper to sort the eigenvalues(and associated eigenvectors) in increasing order -* \param H The matrix, in this case, the Hessian matrix of Psi w.r.t.the molar concentrations -* \param values The eigenvalues -* \returns vectors The eigenvectors, as columns -* -* See https://stackoverflow.com/a/56327853 -* -* \note The input Matrix is symmetric, thus the SelfAdjointEigenSolver can be used, and returned eigenvalues -* will be real and sorted already with corresponding eigenvectors as columns -*/ -auto sorted_eigen(const Eigen::MatrixXd& H) { - Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(H); - return std::make_tuple(es.eigenvalues(), es.eigenvectors()); -} - -struct EigenData { - Eigen::ArrayXd v0, v1, eigenvalues; - Eigen::MatrixXd eigenvectorscols; -}; - -template<typename Model, typename TType, typename RhoType> -auto eigen_problem(const Model& model, const TType T, const RhoType& rhovec) { - - EigenData ed; - - auto N = rhovec.size(); - auto mask = (rhovec != 0); - - // Build the Hessian for the residual part; - auto H = build_Psir_Hessian(model, T, rhovec); - // ... and add ideal-gas terms to H - for (auto i = 0; i < N; ++i) { - if (mask[i]) { - H(i, i) += model.R*T/rhovec[i]; - } - } - - int nonzero_count = 0; - for (auto& m : mask) { - nonzero_count += (m == 1); - } - auto zero_count = N - nonzero_count; - - if (zero_count == 0) { - // Not an infinitely dilute mixture, nothing special - std::tie(ed.eigenvalues, ed.eigenvectorscols) = sorted_eigen(H); - } - else if (zero_count == 1) { - // Extract Hessian matrix without entries where rho is exactly zero - std::vector<int> indicesToKeep; - - int badindex = -1; - for (auto i = 0; i < N; ++i) { - if (mask[i]) { - indicesToKeep.push_back(i); - } - else { - badindex = i; - } - } - Eigen::MatrixXd Hprime = H(indicesToKeep, indicesToKeep); - std::cout << H << std::endl; - std::cout << Hprime << std::endl; - auto [eigenvalues, eigenvectors] = sorted_eigen(Hprime); - - // Inject values into the U^T and v0 vectors - // - // Make a padded matrix for U (with eigenvectors as rows) - Eigen::MatrixXd U = H; U.setZero(); - - // Fill in the associated elements corresponding to eigenvectors - for (auto i = 0; i < N - nonzero_count; ++i) { - U(i, indicesToKeep) = eigenvectors.col(i); // Put in the row, leaving a hole for the zero value - } - - // The last row has a 1 in the column corresponding to the pure fluid entry - // We insist that there must be only one non-zero entry - U.row(U.rows() - 1)(badindex) = 1.0; - - ed.eigenvalues = eigenvalues; - ed.eigenvectorscols = U.transpose(); - } - else { - throw std::invalid_argument("More than one non-zero concentration value found; not currently supported"); - } - ed.v0 = ed.eigenvectorscols.col(0); - ed.v1 = ed.eigenvectorscols.col(1); - return ed; -} - -struct psi1derivs{ - std::valarray<double> psir, psi0, tot; - EigenData ei; -}; - -template<typename Model, typename TType, typename RhoType> -auto get_derivs(const Model& model, const TType T, const RhoType& rhovec) { - auto R = model.R; - - // Solve the complete eigenvalue problem - auto ei = eigen_problem(model, T, rhovec); - - // Ideal-gas contributions of psi0 w.r.t. sigma_1, in the same form as the residual part - std::valarray<double> psi0_derivs(0.0, 5); - psi0_derivs[0] = -1; // Placeholder, not needed - psi0_derivs[1] = -1; // Placeholder, not needed - for (auto i = 0; i < rhovec.size(); ++i) { - if (rhovec[i] != 0){ - psi0_derivs[2] += R*T*pow(ei.v0[i],2)/rhovec[i]; // second derivative - psi0_derivs[3] += -R*T*pow(ei.v0[i],3)/pow(rhovec[i],2); // third derivative - psi0_derivs[4] += 2*R*T*pow(ei.v0[i],4)/pow(rhovec[i],3); // fourth derivative - } - } - - // Calculate the first through fourth derivative of Psi^r w.r.t. sigma_1 - std::valarray<MultiComplex<double>> v0(ei.v0.size()); for(auto i = 0; i < ei.v0.size(); ++i){ v0[i] = ei.v0[i]; } - std::valarray<MultiComplex<double>> rhovecmcx(rhovec.size()); for (auto i = 0; i < rhovec.size(); ++i) { rhovecmcx[i] = rhovec[i]; } - using fcn_t = std::function<MultiComplex<double>(const MultiComplex<double>&)>; - fcn_t wrapper = [&rhovecmcx, &v0, &T, &model](const MultiComplex<double>& sigma_1) { - auto rhovecused = rhovecmcx + sigma_1*v0; - return get_Psir(model, T, rhovecused); - }; - auto psir_derivs_ = diff_mcx1(wrapper, 0.0, 4, true); - auto psir_derivs = std::valarray<double>(&psir_derivs_[0], psir_derivs_.size()); - - // As a sanity check, the minimum eigenvalue of the Hessian constructed based on the molar concentrations - // must match the second derivative of psi_tot w.r.t. sigma_1. This is not always satisfied for derivatives - // with Cauchy method - //if (abs(np.min(ei.eigvals) - psitot_derivs[2]) > 1e-3){ - // print(np.min(ei.eigvals), psitot_derivs[2], rhovec) - //} - - psi1derivs psi1; - psi1.psir = psir_derivs; - psi1.psi0 = psi0_derivs; - psi1.tot = psi0_derivs + psir_derivs; - psi1.ei = ei; - return psi1; -} - -template <typename Iterable> -bool all(const Iterable &foo) { - return std::all_of(std::begin(foo), std::end(foo), [](const auto x){ return x;}); -} -template <typename Iterable> -bool any(const Iterable& foo) { - return std::any_of(std::begin(foo), std::end(foo), [](const auto x) { return x;}); -} - -template<typename Model, typename TType, typename RhoType> -auto get_drhovec_dT_crit(const Model& model, const TType T, const RhoType& rhovec) { - - // The derivatives of total Psi w.r.t.sigma_1(mcx for residual, analytic for ideal) - // Returns a tuple, with residual, ideal, total dicts with of number of derivatives, value of derivative - auto all_derivs = get_derivs(model, T, rhovec); - auto derivs = all_derivs.tot; - - // The temperature derivative of total Psi w.r.t.T from a centered finite difference in T - auto dT = 1e-7; - auto plusT = get_derivs(model, T + dT, rhovec).tot; - auto minusT = get_derivs(model, T - dT, rhovec).tot; - auto derivT = (plusT - minusT)/(2.0*dT); - - // Solve the eigenvalue problem for the given T & rho - auto ei = all_derivs.ei; - - auto sigma2 = 2e-5*rhovec.sum(); // This is the perturbation along the second eigenvector - - auto v1 = std::valarray<double>(&ei.v1[0], ei.v1.size()); - auto rhovec_plus = rhovec + v1*sigma2; - auto rhovec_minus = rhovec - v1*sigma2; - std::string stepping_desc = ""; - auto deriv_sigma2 = 0.0*all_derivs.tot; - if (all(rhovec_minus > 0) && all(rhovec_plus > 0)){ - // Conventional centered derivative - auto plus_sigma2 = get_derivs(model, T, rhovec_plus); - auto minus_sigma2 = get_derivs(model, T, rhovec_minus); - deriv_sigma2 = (plus_sigma2.tot - minus_sigma2.tot)/(2.0 * sigma2); - stepping_desc = "conventional centered"; - } - else if (any(rhovec_minus < 0)) { - // Forward derivative in the direction of v1 - auto plus_sigma2 = get_derivs(model, T, rhovec_plus); - auto rhovec_2plus = rhovec + 2*v1*sigma2; - auto plus2_sigma2 = get_derivs(model, T, rhovec_2plus); - deriv_sigma2 = (-3*derivs + 4*plus_sigma2.tot - plus2_sigma2.tot)/(2.0 * sigma2); - stepping_desc = "forward"; - } - else if (any(rhovec_minus > 0)) { - // Negative derivative in the direction of v1 - auto minus_sigma2 = get_derivs(model, T, rhovec_minus); - auto rhovec_2minus = rhovec - 2*v1*sigma2; - auto minus2_sigma2 = get_derivs(model, T, rhovec_2minus); - deriv_sigma2 = (-3*derivs + 4*minus_sigma2.tot - minus2_sigma2.tot) / (-2.0 * sigma2); - stepping_desc = "backwards"; - } - else { - throw std::invalid_argument("This is not possible I think."); - } - - // The columns of b are from Eq. 31 and Eq. 33 - Eigen::MatrixXd b(2,2); - b << derivs[3], derivs[4], // row is d^3\Psi/d\sigma_1^3, d^4\Psi/d\sigma_1^4 - deriv_sigma2[2], deriv_sigma2[3]; // row is d/d\sigma_2(d^3\Psi/d\sigma_1^3), d/d\sigma_2(d^3\Psi/d\sigma_1^3) - - auto LHS = (ei.eigenvectorscols*b).transpose(); - Eigen::MatrixXd RHS(2,1); RHS << -derivT[2], -derivT[3]; - Eigen::MatrixXd drhovec_dT = LHS.colPivHouseholderQr().solve(RHS); - - // if debug: - // print('Conventional Psi^r derivs w.r.t. sigma_1:', all_derivs.psir) - // print('Conventional Psi derivs w.r.t. sigma_1:', all_derivs.tot) - // print('Derivs w.r.t. T', derivT) - // print('sigma_2', sigma2) - // print('Finite Psi derivs w.r.t. sigma_2:', deriv_sigma2) - // print('stepping', stepping) - // print("U (rows as eigenvalues)", ei.U_T.T) - // print("LHS", LHS) - // print("RHS", RHS) - // print("drhovec_dT", drhovec_dT) - - return std::valarray<double>(&drhovec_dT(0), drhovec_dT.size()); -} +#include "teqp/critical_tracing.hpp" void trace() { // Argon + Xenon @@ -252,7 +28,6 @@ void trace() { } } int rr = 0; - } int main() { trace(); -- GitLab