3#if defined(TEQP_COMPLEXSTEP_ENABLED)
14#if defined(TEQP_MULTICOMPLEX_ENABLED)
15#include "MultiComplex/MultiComplex.hpp"
19#include <autodiff/forward/dual.hpp>
20#include <autodiff/forward/dual/eigen.hpp>
21#include <autodiff/forward/real.hpp>
22#include <autodiff/forward/real/eigen.hpp>
32template <
typename TType,
typename ContainerType,
typename FuncType>
33typename ContainerType::value_type
derivT(
const FuncType& f, TType T,
const ContainerType& rho) {
35 return f(std::complex<TType>(T, h), rho).imag() / h;
38#if defined(TEQP_MULTICOMPLEX_ENABLED)
43template <
typename TType,
typename ContainerType,
typename FuncType>
44typename ContainerType::value_type derivTmcx(
const FuncType& f, TType T,
const ContainerType& rho) {
45 using fcn_t = std::function<mcx::MultiComplex<double>(
const mcx::MultiComplex<double>&)>;
46 fcn_t wrapper = [&rho, &f](
const auto& T_) {
return f(T_, rho); };
47 auto ders = diff_mcx1(wrapper, T, 1);
56template <
typename TType,
typename ContainerType,
typename FuncType,
typename Integer>
57typename ContainerType::value_type
derivrhoi(
const FuncType& f, TType T,
const ContainerType& rho, Integer i) {
59 using comtype = std::complex<typename ContainerType::value_type>;
60 Eigen::ArrayX<comtype> rhocom(rho.size());
61 for (
auto j = 0; j < rho.size(); ++j) {
62 rhocom[j] = comtype(rho[j], 0.0);
64 rhocom[i] = comtype(rho[i], h);
65 return f(T, rhocom).imag() / h;
70template<
typename T,
size_t ... I>
72 return std::make_tuple((
static_cast<void>(I), val)...);
76template<
int N,
typename T>
85 template<
typename... Args>
88 return Wrt<Args&&...>{ std::forward_as_tuple(std::forward<Args>(args)...) };
93#if defined(TEQP_MULTICOMPLEX_ENABLED)
96#if defined(TEQP_COMPLEXSTEP_ENABLED)
101template<
typename T,
typename U,
typename V,
typename W>
106template<
typename T,
typename U,
typename V,
typename W>
111template<
typename T,
typename U,
typename V,
typename W>
113 { t.alphar_taudelta(u,v,w) };
116template<
typename Model,
typename Scalar =
double,
typename VectorType = Eigen::ArrayXd>
119 static auto get_Ar00(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
120 return model.alphar(T, rho, molefrac);
123 template<
typename AlphaWrapper,
typename S1,
typename S2,
typename Vec>
125 return w.alpha(T, rho, molefrac);
127 template<
typename AlphaWrapper,
typename S1,
typename S2,
typename Vec>
129 return w.alphar(T, rho, molefrac);
132 template<
typename AlphaWrapper,
typename S1,
typename S2,
typename Vec>
134 return w.alphar_taudelta(T, rho, molefrac);
136 template<
typename AlphaWrapper,
typename S1,
typename S2,
typename Vec>
139 return std::common_type_t<S1, S2, decltype(molefrac[0])>(1e99);
150 template<
int iT,
int iD, ADBackends be = ADBackends::autodiff,
class AlphaWrapper>
151 static auto get_Agenxy(
const AlphaWrapper& w,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
153 if constexpr (iT == 0 && iD == 0){
156 else if constexpr (iT == 0 && iD > 0) {
159 autodiff::Real<iD, Scalar> rho_ = rho;
160 auto f = [&w, &T, &molefrac](
const auto& rho__) {
return AlphaCaller(w, T, rho__, molefrac); };
161 return powi(rho, iD)*derivatives(f, along(1), at(rho_))[iD];
163#if defined(TEQP_COMPLEXSTEP_ENABLED)
164 else if constexpr (iD == 1 && be == ADBackends::complex_step) {
166 auto rho_ = std::complex<Scalar>(rho, h);
170#if defined(TEQP_MULTICOMPLEX_ENABLED)
171 else if constexpr (be == ADBackends::multicomplex) {
172 using fcn_t = std::function<mcx::MultiComplex<Scalar>(
const mcx::MultiComplex<Scalar>&)>;
173 fcn_t f = [&](
const auto& rhomcx) {
return AlphaCaller(w, T, rhomcx, molefrac); };
174 auto ders = diff_mcx1(f, rho, iD,
true );
175 return powi(rho, iD)*ders[iD];
179 throw std::invalid_argument(
"algorithmic differentiation backend is invalid in get_Agenxy for iT == 0");
182 else if constexpr (iT > 0 && iD == 0) {
183 Scalar Trecip = 1.0 / T;
186 autodiff::Real<iT, Scalar> Trecipad = Trecip;
187 auto f = [&w, &rho, &molefrac](
const auto& Trecip__) {
return AlphaCaller(w,
forceeval(1.0/Trecip__), rho, molefrac); };
188 return powi(Trecip, iT)*derivatives(f, along(1), at(Trecipad))[iT];
190#if defined(TEQP_COMPLEXSTEP_ENABLED)
191 else if constexpr (iT == 1 && be == ADBackends::complex_step) {
193 auto Trecipcsd = std::complex<Scalar>(Trecip, h);
194 return powi(Trecip, iT)* w.alpha(1/Trecipcsd, rho, molefrac).imag()/h;
197#if defined(TEQP_MULTICOMPLEX_ENABLED)
198 else if constexpr (be == ADBackends::multicomplex) {
199 using fcn_t = std::function<mcx::MultiComplex<Scalar>(
const mcx::MultiComplex<Scalar>&)>;
200 fcn_t f = [&](
const auto& Trecipmcx) {
return AlphaCaller(w, 1.0/Trecipmcx, rho, molefrac); };
201 auto ders = diff_mcx1(f, Trecip, iT,
true );
202 return powi(Trecip, iT)*ders[iT];
206 throw std::invalid_argument(
"algorithmic differentiation backend is invalid in get_Agenxy for iD == 0");
211 using adtype = autodiff::HigherOrderDual<iT + iD, double>;
212 adtype Trecipad = 1.0 / T, rhoad = rho;
213 auto f = [&w, &molefrac](
const adtype& Trecip,
const adtype& rho_) {
214 adtype T_ = 1.0/Trecip;
215 return eval(
AlphaCaller(w, T_, rho_, molefrac)); };
216 auto wrts = std::tuple_cat(build_duplicated_tuple<iT>(std::ref(Trecipad)), build_duplicated_tuple<iD>(std::ref(rhoad)));
217 auto der = derivatives(f, std::apply(
wrt_helper(), wrts), at(Trecipad, rhoad));
220#if defined(TEQP_MULTICOMPLEX_ENABLED)
221 else if constexpr (be == ADBackends::multicomplex) {
222 using fcn_t = std::function< mcx::MultiComplex<double>(
const std::valarray<mcx::MultiComplex<double>>&)>;
223 const fcn_t func = [&w, &molefrac](
const auto& zs) {
224 auto Trecip = zs[0], rhomolar = zs[1];
225 return AlphaCaller(w, 1.0 / Trecip, rhomolar, molefrac);
227 std::vector<double> xs = { 1.0 / T, rho};
228 std::vector<int> order = { iT, iD };
229 auto der = mcx::diff_mcxN(func, xs, order);
230 return powi(1.0 / T, iT)*
powi(rho, iD)*der;
234 throw std::invalid_argument(
"algorithmic differentiation backend is invalid in get_Agenxy for iD > 0 and iT > 0");
247 template<
int iT,
int iD,
int iXi,
typename AlphaWrapper>
248 static auto get_ATrhoXi(
const AlphaWrapper& w,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac,
int i){
249 using adtype = autodiff::HigherOrderDual<iT + iD + iXi, double>;
250 adtype Trecipad = 1.0 / T, rhoad = rho, xi = molefrac[i];
251 auto f = [&w, &molefrac, &i](
const adtype& Trecip,
const adtype& rho_,
const adtype& xi_) {
252 adtype T_ = 1.0/Trecip;
253 Eigen::ArrayX<adtype> molefracdual = molefrac.template cast<adtype>();
254 molefracdual[i] = xi_;
255 return eval(
AlphaCaller(w, T_, rho_, molefracdual)); };
256 auto wrts = std::tuple_cat(build_duplicated_tuple<iT>(std::ref(Trecipad)), build_duplicated_tuple<iD>(std::ref(rhoad)), build_duplicated_tuple<iXi>(std::ref(xi)));
257 auto der = derivatives(f, std::apply(
wrt_helper(), wrts), at(Trecipad, rhoad, xi));
261 #define get_ATrhoXi_runtime_combinations \
281 template<
typename AlphaWrapper>
282 static auto get_ATrhoXi_runtime(
const AlphaWrapper& w,
const Scalar& T,
int iT,
const Scalar& rho,
int iD,
const VectorType& molefrac,
int i,
int iXi){
283 #define X(a,b,c) if (iT == a && iD == b && iXi == c) { return get_ATrhoXi<a,b,c>(w, T, rho, molefrac, i); }
289 #define get_ATrhoXiXj_runtime_combinations \
306 template<
typename AlphaWrapper>
307 static auto get_ATrhoXiXj_runtime(
const AlphaWrapper& w,
const Scalar& T,
int iT,
const Scalar& rho,
int iD,
const VectorType& molefrac,
int i,
int iXi,
int j,
int iXj){
308 #define X(a,b,c,d) if (iT == a && iD == b && iXi == c && iXj == d) { return get_ATrhoXiXj<a,b,c,d>(w, T, rho, molefrac, i, j); }
314 #define get_ATrhoXiXjXk_runtime_combinations \
328 template<
typename AlphaWrapper>
329 static auto get_ATrhoXiXjXk_runtime(
const AlphaWrapper& w,
const Scalar& T,
int iT,
const Scalar& rho,
int iD,
const VectorType& molefrac,
int i,
int iXi,
int j,
int iXj,
int k,
int iXk){
330 #define X(a,b,c,d,e) if (iT == a && iD == b && iXi == c && iXj == d && iXk == e) { return get_ATrhoXiXjXk<a,b,c,d,e>(w, T, rho, molefrac, i, j, k); }
336 template<
int iT,
int iD,
int iXi,
typename AlphaWrapper>
337 static auto get_AtaudeltaXi(
const AlphaWrapper& w,
const Scalar& tau,
const Scalar& delta,
const VectorType& molefrac,
const int i) {
338 using adtype = autodiff::HigherOrderDual<iT + iD + iXi, double>;
339 adtype tauad = tau, deltaad = delta, xi = molefrac[i];
340 auto f = [&w, &molefrac, &i](
const adtype& tau_,
const adtype& delta_,
const adtype& xi_) {
341 Eigen::ArrayX<adtype> molefracdual = molefrac.template cast<adtype>();
342 molefracdual[i] = xi_;
344 auto wrts = std::tuple_cat(build_duplicated_tuple<iT>(std::ref(tauad)), build_duplicated_tuple<iD>(std::ref(deltaad)), build_duplicated_tuple<iXi>(std::ref(xi)));
345 auto der = derivatives(f, std::apply(
wrt_helper(), wrts), at(tauad, deltaad, xi));
346 return powi(tau, iT) *
powi(delta, iD) * der[der.size() - 1];
349 template<
int iT,
int iD,
int iXi,
int iXj,
typename AlphaWrapper>
350 static auto get_AtaudeltaXiXj(
const AlphaWrapper& w,
const Scalar& tau,
const Scalar& delta,
const VectorType& molefrac,
const int i,
const int j) {
351 using adtype = autodiff::HigherOrderDual<iT + iD + iXi + iXj, double>;
355 adtype tauad = tau, deltaad = delta, xi = molefrac[i], xj = molefrac[j];
356 auto f = [&w, &molefrac, i, j](
const adtype& tau_,
const adtype& delta_,
const adtype& xi_,
const adtype& xj_) {
357 Eigen::ArrayX<adtype> molefracdual = molefrac.template cast<adtype>();
358 molefracdual[i] = xi_;
359 molefracdual[j] = xj_;
361 auto wrts = std::tuple_cat(build_duplicated_tuple<iT>(std::ref(tauad)), build_duplicated_tuple<iD>(std::ref(deltaad)), build_duplicated_tuple<iXi>(std::ref(xi)), build_duplicated_tuple<iXj>(std::ref(xj)));
362 auto der = derivatives(f, std::apply(
wrt_helper(), wrts), at(tauad, deltaad, xi, xj));
363 return powi(tau, iT) *
powi(delta, iD) * der[der.size() - 1];
366 template<
int iT,
int iD,
int iXi,
int iXj,
int iXk,
typename AlphaWrapper>
367 static auto get_AtaudeltaXiXjXk(
const AlphaWrapper& w,
const Scalar& tau,
const Scalar& delta,
const VectorType& molefrac,
const int i,
const int j,
const int k) {
368 using adtype = autodiff::HigherOrderDual<iT + iD + iXi + iXj + iXk, double>;
369 if (i == j || j == k || i == k){
372 adtype tauad = tau, deltaad = delta, xi = molefrac[i], xj = molefrac[j], xk = molefrac[k];
373 auto f = [&w, &molefrac, i, j, k](
const adtype& tau_,
const adtype& delta_,
const adtype& xi_,
const adtype& xj_,
const adtype& xk_) {
374 Eigen::ArrayX<adtype> molefracdual = molefrac.template cast<adtype>();
375 molefracdual[i] = xi_;
376 molefracdual[j] = xj_;
377 molefracdual[k] = xk_;
379 auto wrts = std::tuple_cat(build_duplicated_tuple<iT>(std::ref(tauad)), build_duplicated_tuple<iD>(std::ref(deltaad)), build_duplicated_tuple<iXi>(std::ref(xi)), build_duplicated_tuple<iXj>(std::ref(xj)), build_duplicated_tuple<iXk>(std::ref(xk)));
380 auto der = derivatives(f, std::apply(
wrt_helper(), wrts), at(tauad, deltaad, xi, xj, xk));
381 return powi(tau, iT) *
powi(delta, iD) * der[der.size() - 1];
384 template<
typename AlphaWrapper>
385 static auto get_AtaudeltaXi_runtime(
const AlphaWrapper& w,
const Scalar& tau,
const int iT,
const Scalar& delta,
const int iD,
const VectorType& molefrac,
const int i,
const int iXi){
386 #define X(a,b,c) if (iT == a && iD == b && iXi == c) { return get_AtaudeltaXi<a,b,c>(w, tau, delta, molefrac, i); }
392 template<
typename AlphaWrapper>
393 static auto get_AtaudeltaXiXj_runtime(
const AlphaWrapper& w,
const Scalar& tau,
const int iT,
const Scalar& delta,
const int iD,
const VectorType& molefrac,
const int i,
const int iXi,
const int j,
const int iXj){
394 #define X(a,b,c,d) if (iT == a && iD == b && iXi == c && iXj == d) { return get_AtaudeltaXiXj<a,b,c,d>(w, tau, delta, molefrac, i, j); }
400 template<
typename AlphaWrapper>
401 static auto get_AtaudeltaXiXjXk_runtime(
const AlphaWrapper& w,
const Scalar& tau,
const int iT,
const Scalar& delta,
const int iD,
const VectorType& molefrac,
const int i,
int iXi,
const int j,
const int iXj,
const int k,
const int iXk){
402 #define X(a,b,c,d,e) if (iT == a && iD == b && iXi == c && iXj == d && iXk == e) { return get_AtaudeltaXiXjXk<a,b,c,d,e>(w, tau, delta, molefrac, i, j, k); }
415 template<
int iT,
int iD,
int iXi,
int iXj,
typename AlphaWrapper>
416 static auto get_ATrhoXiXj(
const AlphaWrapper& w,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac,
int i,
int j){
420 using adtype = autodiff::HigherOrderDual<iT + iD + iXi + iXj, double>;
421 adtype Trecipad = 1.0 / T, rhoad = rho, xi = molefrac[i], xj = molefrac[j];
422 auto f = [&w, &molefrac, i, j](
const adtype& Trecip,
const adtype& rho_,
const adtype& xi_,
const adtype& xj_) {
423 adtype T_ = 1.0/Trecip;
424 Eigen::ArrayX<adtype> molefracdual = molefrac.template cast<adtype>();
425 molefracdual[i] = xi_;
426 molefracdual[j] = xj_;
427 return eval(
AlphaCaller(w, T_, rho_, molefracdual)); };
428 auto wrts = std::tuple_cat(build_duplicated_tuple<iT>(std::ref(Trecipad)), build_duplicated_tuple<iD>(std::ref(rhoad)), build_duplicated_tuple<iXi>(std::ref(xi)), build_duplicated_tuple<iXj>(std::ref(xj)));
429 auto der = derivatives(f, std::apply(
wrt_helper(), wrts), at(Trecipad, rhoad, xi, xj));
440 template<
int iT,
int iD,
int iXi,
int iXj,
int iXk,
typename AlphaWrapper>
441 static auto get_ATrhoXiXjXk(
const AlphaWrapper& w,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac,
int i,
int j,
int k){
442 if (i == j || j == k || i == k){
445 using adtype = autodiff::HigherOrderDual<iT + iD + iXi + iXj + iXk, double>;
446 adtype Trecipad = 1.0 / T, rhoad = rho, xi = molefrac[i], xj = molefrac[j], xk = molefrac[k];
447 auto f = [&w, &molefrac, i, j, k](
const adtype& Trecip,
const adtype& rho_,
const adtype& xi_,
const adtype& xj_,
const adtype& xk_) {
448 adtype T_ = 1.0/Trecip;
449 Eigen::ArrayX<adtype> molefracdual = molefrac.template cast<adtype>();
450 molefracdual[i] = xi_;
451 molefracdual[j] = xj_;
452 molefracdual[k] = xk_;
453 return eval(
AlphaCaller(w, T_, rho_, molefracdual)); };
454 auto wrts = std::tuple_cat(build_duplicated_tuple<iT>(std::ref(Trecipad)), build_duplicated_tuple<iD>(std::ref(rhoad)), build_duplicated_tuple<iXi>(std::ref(xi)), build_duplicated_tuple<iXj>(std::ref(xj)), build_duplicated_tuple<iXk>(std::ref(xk)));
455 auto der = derivatives(f, std::apply(
wrt_helper(), wrts), at(Trecipad, rhoad, xi, xj, xk));
467 template<
int iT,
int iD, ADBackends be = ADBackends::autodiff>
468 static auto get_Arxy(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
469 return get_Agenxy<iT, iD, be>(model, T, rho, molefrac);
480 template<
int iT,
int iD, ADBackends be = ADBackends::autodiff>
481 static auto get_Aigxy(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
482 return get_Agenxy<iT, iD, be>(model, T, rho, molefrac);
485 template<ADBackends be = ADBackends::autodiff>
486 static auto get_Ar10(
const Model& model,
const Scalar &T,
const Scalar &rho,
const VectorType& molefrac) {
487 return get_Arxy<1, 0, be>(model, T, rho, molefrac);
490 template<ADBackends be = ADBackends::autodiff>
491 static Scalar
get_Ar01(
const Model& model,
const Scalar&T,
const Scalar &rho,
const VectorType& molefrac){
492 return get_Arxy<0, 1, be>(model, T, rho, molefrac);
495 template<ADBackends be = ADBackends::autodiff>
496 static auto get_Ar02(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
497 return get_Arxy<0, 2, be>(model, T, rho, molefrac);
500 template<ADBackends be = ADBackends::autodiff>
501 static auto get_Ar03(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
502 return get_Arxy<0, 3, be>(model, T, rho, molefrac);
505 template<ADBackends be = ADBackends::autodiff>
506 static auto get_Ar20(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
507 return get_Arxy<2, 0, be>(model, T, rho, molefrac);
510 template<ADBackends be = ADBackends::autodiff>
511 static auto get_Ar30(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
512 return get_Arxy<3, 0, be>(model, T, rho, molefrac);
515 template<ADBackends be = ADBackends::autodiff>
516 static auto get_Ar21(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
517 return get_Arxy<2, 1, be>(model, T, rho, molefrac);
520 template<ADBackends be = ADBackends::autodiff>
521 static auto get_Ar12(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
522 return get_Arxy<1, 2, be>(model, T, rho, molefrac);
525 template<ADBackends be = ADBackends::autodiff>
526 static auto get_Ar11(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
527 return get_Arxy<1, 1, be>(model, T, rho, molefrac);
530 template<ADBackends be = ADBackends::autodiff>
531 static auto get_Aig11(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
532 return get_Aigxy<1, 1, be>(model, T, rho, molefrac);
535 template<
int Nderiv, ADBackends be = ADBackends::autodiff,
class AlphaWrapper>
536 static auto get_Agen0n(
const AlphaWrapper& w,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
537 std::valarray<Scalar> o(Nderiv+1);
540 autodiff::Real<Nderiv, Scalar> rho_ = rho;
541 auto f = [&w, &T, &molefrac](
const auto& rho__) {
return AlphaCaller(w, T, rho__, molefrac); };
542 auto ders = derivatives(f, along(1), at(rho_));
543 for (
auto n = 0; n <= Nderiv; ++n) {
548#if defined(TEQP_MULTICOMPLEX_ENABLED)
550 using fcn_t = std::function<mcx::MultiComplex<Scalar>(
const mcx::MultiComplex<Scalar>&)>;
552 fcn_t f = [&w, &T, &molefrac](
const auto& rhomcx) {
return AlphaCaller(w, T, rhomcx, molefrac); };
553 auto ders = diff_mcx1(f, rho, Nderiv, and_val);
554 for (
auto n = 0; n <= Nderiv; ++n) {
555 o[n] =
powi(rho, n) * ders[n];
563 template<
int Nderiv, ADBackends be = ADBackends::autodiff,
class AlphaWrapper>
564 static auto get_Agenn0(
const AlphaWrapper& w,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
565 std::valarray<Scalar> o(Nderiv+1);
566 Scalar Trecip = 1.0 / T;
569 autodiff::Real<Nderiv, Scalar> Trecipad = Trecip;
570 auto f = [&w, &rho, &molefrac](
const auto& Trecip__) {
return AlphaCaller(w,
forceeval(1.0/Trecip__), rho, molefrac); };
571 auto ders = derivatives(f, along(1), at(Trecipad));
572 for (
auto n = 0; n <= Nderiv; ++n) {
573 o[n] =
powi(Trecip, n) * ders[n];
576#if defined(TEQP_MULTICOMPLEX_ENABLED)
577 else if constexpr (be == ADBackends::multicomplex) {
578 using fcn_t = std::function<mcx::MultiComplex<Scalar>(
const mcx::MultiComplex<Scalar>&)>;
579 fcn_t f = [&](
const auto& Trecipmcx) {
return AlphaCaller(w, 1.0/Trecipmcx, rho, molefrac); };
580 auto ders = diff_mcx1(f, Trecip, Nderiv+1,
true );
581 for (
auto n = 0; n <= Nderiv; ++n) {
582 o[n] =
powi(Trecip, n) * ders[n];
587 throw std::invalid_argument(
"algorithmic differentiation backend is invalid in get_Agenn0");
600 template<
int iT, ADBackends be = ADBackends::autodiff>
601 static auto get_Arn0(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
602 return get_Agenn0<iT, be>(model, T, rho, molefrac);
613 template<
int iD, ADBackends be = ADBackends::autodiff>
614 static auto get_Ar0n(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
615 return get_Agen0n<iD, be>(model, T, rho, molefrac);
619 template<ADBackends be = ADBackends::autodiff>
620 static auto get_Ar(
const int itau,
const int idelta,
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
623 return get_Ar00(model, T, rho, molefrac);
625 else if (idelta == 1) {
626 return get_Ar01(model, T, rho, molefrac);
628 else if (idelta == 2) {
629 return get_Ar02(model, T, rho, molefrac);
631 else if (idelta == 3) {
632 return get_Ar03(model, T, rho, molefrac);
635 throw std::invalid_argument(
"Invalid value for idelta");
640 return get_Ar10(model, T, rho, molefrac);
642 else if (idelta == 1) {
643 return get_Ar11(model, T, rho, molefrac);
645 else if (idelta == 2) {
646 return get_Ar12(model, T, rho, molefrac);
649 throw std::invalid_argument(
"Invalid value for idelta");
652 else if (itau == 2) {
654 return get_Ar20(model, T, rho, molefrac);
656 else if (idelta == 1) {
657 return get_Ar21(model, T, rho, molefrac);
660 throw std::invalid_argument(
"Invalid value for idelta");
663 else if (itau == 3) {
665 return get_Ar30(model, T, rho, molefrac);
668 throw std::invalid_argument(
"Invalid value for idelta");
672 throw std::invalid_argument(
"Invalid value for itau");
676 template<ADBackends be = ADBackends::autodiff>
677 static auto get_neff(
const Model& model,
const Scalar& T,
const Scalar& rho,
const VectorType& molefrac) {
678 auto Ar01 = get_Ar01<be>(model, T, rho, molefrac);
679 auto Ar11 = get_Ar11<be>(model, T, rho, molefrac);
680 auto Ar20 = get_Ar20<be>(model, T, rho, molefrac);
681 return -3*(Ar01-Ar11)/Ar20;
685template<
typename Model,
typename Scalar =
double,
typename VectorType = Eigen::ArrayXd>
688 static auto get_B2vir(
const Model& model,
const Scalar &T,
const VectorType& molefrac) {
691 auto B2 = model.alphar(T, std::complex<Scalar>(0.0, h), molefrac).imag()/h;
705 template <
int Nderiv, ADBackends be = ADBackends::autodiff>
706 static auto get_Bnvir(
const Model& model,
const Scalar &T,
const VectorType& molefrac)
708 std::map<int, double> dnalphardrhon;
710 auto f = [&model, &T, &molefrac](
const auto& rho_) {
return model.alphar(T, rho_, molefrac); };
711 autodiff::Real<Nderiv, Scalar> rhoreal = 0.0;
712 auto derivs = derivatives(f, along(1), at(rhoreal));
714 for (
auto n = 1; n < Nderiv; ++n){
715 dnalphardrhon[n] = derivs[n];
718#if defined(TEQP_MULTICOMPLEX_ENABLED)
719 else if constexpr(be == ADBackends::multicomplex){
721 using fcn_t = std::function<MultiComplex<double>(
const MultiComplex<double>&)>;
722 fcn_t f = [&model, &T, &molefrac](
const auto& rho_) {
return model.alphar(T, rho_, molefrac); };
723 auto derivs = diff_mcx1(f, 0.0, Nderiv,
true );
724 for (
auto n = 1; n < Nderiv; ++n){
725 dnalphardrhon[n] = derivs[n];
731 throw std::invalid_argument(
"algorithmic differentiation backend is invalid in get_Bnvir");
734 std::map<int, Scalar> o;
735 for (
int n = 2; n <= Nderiv; ++n) {
736 o[n] = dnalphardrhon[n-1];
739 auto factorial = [](
int N) {
return tgamma(N + 1); };
740 o[n] /= factorial(n-2);
748 template <ADBackends be = ADBackends::autodiff>
749 static auto get_Bnvir_runtime(
const int Nderiv,
const Model& model,
const Scalar &T,
const VectorType& molefrac) {
751 case 2:
return get_Bnvir<2,be>(model, T, molefrac);
752 case 3:
return get_Bnvir<3,be>(model, T, molefrac);
753 case 4:
return get_Bnvir<4,be>(model, T, molefrac);
754 case 5:
return get_Bnvir<5,be>(model, T, molefrac);
755 case 6:
return get_Bnvir<6,be>(model, T, molefrac);
756 case 7:
return get_Bnvir<7,be>(model, T, molefrac);
757 case 8:
return get_Bnvir<8,be>(model, T, molefrac);
758 case 9:
return get_Bnvir<9,be>(model, T, molefrac);
759 default:
throw std::invalid_argument(
"Only Nderiv up to 9 is supported, get_Bnvir templated function allows more");
775 template <
int Nderiv,
int NTderiv, ADBackends be = ADBackends::autodiff>
776 static auto get_dmBnvirdTm(
const Model& model,
const Scalar& T,
const VectorType& molefrac)
778 std::map<int, Scalar> o;
779 auto factorial = [](
int N) {
return tgamma(N + 1); };
781 autodiff::HigherOrderDual<NTderiv + Nderiv-1,
double> rhodual = 0.0, Tdual = T;
782 auto f = [&model, &molefrac](
const auto& T_,
const auto& rho_) {
return model.alphar(T_, rho_, molefrac); };
783 auto wrts = std::tuple_cat(build_duplicated_tuple<NTderiv>(std::ref(Tdual)), build_duplicated_tuple<Nderiv-1>(std::ref(rhodual)));
784 auto derivs = derivatives(f, std::apply(
wrt_helper(), wrts), at(Tdual, rhodual));
785 return derivs.back() / factorial(Nderiv - 2);
787#if defined(TEQP_MULTICOMPLEX_ENABLED)
788 else if constexpr (be == ADBackends::multicomplex) {
790 using fcn_t = std::function<MultiComplex<double>(
const std::valarray<MultiComplex<double>>&)>;
791 fcn_t f = [&model, &molefrac](
const auto& zs) {
792 auto T_ = zs[0], rho_ = zs[1];
793 return model.alphar(T_, rho_, molefrac);
795 std::valarray<double> at = { T, 0.0 };
796 auto deriv = diff_mcxN(f, at, { NTderiv, Nderiv-1});
797 return deriv / factorial(Nderiv - 2);
802 throw std::invalid_argument(
"algorithmic differentiation backend is invalid in get_Bnvir");
808 template <ADBackends be = ADBackends::autodiff>
809 static auto get_dmBnvirdTm_runtime(
const int Nderiv,
const int NTderiv,
const Model& model,
const Scalar& T,
const VectorType& molefrac) {
812 case 0:
return get_Bnvir<2, be>(model, T, molefrac)[2];
813 case 1:
return get_dmBnvirdTm<2, 1, be>(model, T, molefrac);
814 case 2:
return get_dmBnvirdTm<2, 2, be>(model, T, molefrac);
815 case 3:
return get_dmBnvirdTm<2, 3, be>(model, T, molefrac);
816 default:
throw std::invalid_argument(
"NTderiv is invalid in get_dmBnvirdTm_runtime");
819 else if (Nderiv == 3) {
821 case 0:
return get_Bnvir<3, be>(model, T, molefrac)[3];
822 case 1:
return get_dmBnvirdTm<3, 1, be>(model, T, molefrac);
823 case 2:
return get_dmBnvirdTm<3, 2, be>(model, T, molefrac);
824 case 3:
return get_dmBnvirdTm<3, 3, be>(model, T, molefrac);
825 default:
throw std::invalid_argument(
"NTderiv is invalid in get_dmBnvirdTm_runtime");
828 else if (Nderiv == 4) {
830 case 0:
return get_Bnvir<4, be>(model, T, molefrac)[4];
831 case 1:
return get_dmBnvirdTm<4, 1, be>(model, T, molefrac);
832 case 2:
return get_dmBnvirdTm<4, 2, be>(model, T, molefrac);
833 case 3:
return get_dmBnvirdTm<4, 3, be>(model, T, molefrac);
834 default:
throw std::invalid_argument(
"NTderiv is invalid in get_dmBnvirdTm_runtime");
838 throw std::invalid_argument(
"Nderiv is invalid in get_dmBnvirdTm_runtime");
848 static auto get_B12vir(
const Model& model,
const Scalar &T,
const VectorType& molefrac) {
849 if (molefrac.size() != 2) {
throw std::invalid_argument(
"length of mole fraction vector must be 2 in get_B12vir"); }
851 const auto xpure0 = (Eigen::ArrayXd(2) << 1,0).finished();
852 const auto xpure1 = (Eigen::ArrayXd(2) << 0,1).finished();
855 auto z0 = molefrac[0];
856 auto B12 = (B2 - z0*z0*B20 - (1-z0)*(1-z0)*B21)/(2*z0*(1-z0));
948template<
typename Model,
typename Scalar =
double,
typename VectorType = Eigen::ArrayXd>
954 static auto get_splus(
const Model& model,
const Scalar &T,
const VectorType& rhovec) {
955 auto rhotot = rhovec.sum();
956 auto molefrac = rhovec / rhotot;
957 return model.alphar(T, rhotot, molefrac) -
get_Ar10(model, T, rhovec);
963 static auto get_pr(
const Model& model,
const Scalar &T,
const VectorType& rhovec)
965 auto rhotot_ = rhovec.sum();
966 auto molefrac = (rhovec / rhotot_).eval();
968 auto Ar01 = model.alphar(T, std::complex<double>(rhotot_, h), molefrac).imag() / h * rhotot_;
969 return Ar01*rhotot_*model.R(molefrac)*T;
972 static auto get_Ar00(
const Model& model,
const Scalar& T,
const VectorType& rhovec) {
973 auto rhotot = rhovec.sum();
974 auto molefrac = (rhovec / rhotot).eval();
975 return model.alphar(T, rhotot, molefrac);
978 static auto get_Ar10(
const Model& model,
const Scalar& T,
const VectorType& rhovec) {
979 auto rhotot = rhovec.sum();
980 auto molefrac = (rhovec / rhotot).eval();
981 return -T *
derivT([&model, &rhotot, &molefrac](
const auto& T,
const auto& ) {
return model.alphar(T, rhotot, molefrac); }, T, rhovec);
984 static auto get_Ar01(
const Model& model,
const Scalar &T,
const VectorType& rhovec) {
985 auto rhotot_ = std::accumulate(std::begin(rhovec), std::end(rhovec), (
decltype(rhovec[0]))0.0);
986 decltype(rhovec[0] * T) Ar01 = 0.0;
987 for (
auto i = 0; i < rhovec.size(); ++i) {
988 auto Ar00 = [&model](
const auto &T,
const auto&rhovec) {
989 auto rhotot = rhovec.sum();
990 auto molefrac = rhovec / rhotot;
991 return model.alphar(T, rhotot, molefrac);
993 Ar01 += rhovec[i] *
derivrhoi(Ar00, T, rhovec, i);
1001 static auto get_Psir(
const Model& model,
const Scalar &T,
const VectorType& rhovec) {
1002 auto rhotot_ = rhovec.sum();
1003 auto molefrac = rhovec / rhotot_;
1004 return model.alphar(T, rhotot_, molefrac) * model.R(molefrac) * T * rhotot_;
1011 auto rhotot_ = rhovec.sum();
1012 auto molefrac = (rhovec / rhotot_).eval();
1013 autodiff::Real<1, Scalar> Tad = T;
1014 auto f = [&model, &rhotot_, &molefrac](
const auto& T_) {
return rhotot_*model.R(molefrac)*T_*model.alphar(T_, rhotot_, molefrac); };
1015 return derivatives(f, along(1), at(Tad))[1];
1029 ArrayXdual2nd rhovecc(rho.size());
for (
auto i = 0; i < rho.size(); ++i) { rhovecc[i] = rho[i]; }
1030 auto hfunc = [&model, &T](
const ArrayXdual2nd& rho_) {
1031 auto rhotot_ = rho_.sum();
1032 auto molefrac = (rho_ / rhotot_).eval();
1033 return eval(model.alphar(T, rhotot_, molefrac) * model.R(molefrac) * T * rhotot_);
1035 return autodiff::hessian(hfunc, wrt(rhovecc), at(rhovecc), u, g).eval();
1049 ArrayXdual2nd rhovecc(rho.size());
for (
auto i = 0; i < rho.size(); ++i) { rhovecc[i] = rho[i]; }
1050 auto hfunc = [&model, &T](
const ArrayXdual2nd& rho_) {
1051 auto rhotot_ = rho_.sum();
1052 auto molefrac = (rho_ / rhotot_).eval();
1053 return eval(model.alphar(T, rhotot_, molefrac) * model.R(molefrac) * T * rhotot_);
1056 Eigen::MatrixXd H = autodiff::hessian(hfunc, wrt(rhovecc), at(rhovecc), u, g);
1059 auto gg = g.cast<
double>().eval();
1060 return std::make_tuple(f, gg, H);
1069 auto rhotot_ = rho.sum();
1070 auto molefrac = (rho / rhotot_).eval();
1072 for (
auto i = 0; i < 2; ++i) {
1073 H(i, i) += model.R(molefrac) * T / rho[i];
1078#if defined(TEQP_MULTICOMPLEX_ENABLED)
1084 static auto build_Psir_Hessian_mcx(
const Model& model,
const Scalar& T,
const VectorType& rho) {
1087 using namespace mcx;
1090 using fcn_t = std::function< MultiComplex<double>(
const Eigen::ArrayX<MultiComplex<double>>&)>;
1091 fcn_t func = [&model, &T](
const auto& rhovec) {
1092 auto rhotot_ = rhovec.sum();
1093 auto molefrac = (rhovec / rhotot_).eval();
1094 return model.alphar(T, rhotot_, molefrac) * model.R(molefrac) * T * rhotot_;
1096 using mattype = Eigen::ArrayXXd;
1097 auto H = get_Hessian<mattype, fcn_t, VectorType, HessianMethods::Multiple>(func, rho);
1108 ArrayXdual rhovecc(rho.size());
for (
auto i = 0; i < rho.size(); ++i) { rhovecc[i] = rho[i]; }
1109 auto psirfunc = [&model, &T](
const ArrayXdual& rho_) {
1110 auto rhotot_ = rho_.sum();
1111 auto molefrac = (rho_ / rhotot_).eval();
1112 return eval(model.alphar(T, rhotot_, molefrac) * model.R(molefrac) * T * rhotot_);
1114 auto val = autodiff::gradient(psirfunc, wrt(rhovecc), at(rhovecc)).eval();
1118#if defined(TEQP_MULTICOMPLEX_ENABLED)
1124 static auto build_Psir_gradient_multicomplex(
const Model& model,
const Scalar& T,
const VectorType& rho) {
1125 using rho_type =
typename VectorType::value_type;
1126 Eigen::ArrayX<mcx::MultiComplex<rho_type>> rhovecc(rho.size());
1127 auto psirfunc = [&model](
const auto &T,
const auto& rho_) {
1128 auto rhotot_ = rho_.sum();
1129 auto molefrac = (rho_ / rhotot_).eval();
1130 return eval(model.alphar(T, rhotot_, molefrac) * model.R(molefrac) * T * rhotot_);
1132 VectorType out(rho.size());
1133 for (
int i = 0; i < rho.size(); ++i) {
1134 out[i] =
derivrhoi(psirfunc, T, rho, i);
1145 using rho_type =
typename VectorType::value_type;
1146 Eigen::ArrayX<std::complex<rho_type>> rhovecc(rho.size());
for (
auto i = 0; i < rho.size(); ++i) { rhovecc[i] = rho[i]; }
1147 auto psirfunc = [&model](
const auto& T,
const auto& rho_) {
1148 auto rhotot_ = rho_.sum();
1149 auto molefrac = (rho_ / rhotot_).eval();
1150 return forceeval(model.alphar(T, rhotot_, molefrac) * model.R(molefrac) * T * rhotot_);
1152 VectorType out(rho.size());
1153 for (
int i = 0; i < rho.size(); ++i) {
1154 auto rhocopy = rhovecc;
1155 rho_type h = 1e-100;
1156 rhocopy[i] = rhocopy[i] + std::complex<rho_type>(0,h);
1157 auto calc = psirfunc(T, rhocopy);
1158 out[i] = calc.imag /
static_cast<double>(h);
1164 template<ADBackends be = ADBackends::autodiff>
1169#if defined(TEQP_MULTICOMPLEX_ENABLED)
1170 else if constexpr (be == ADBackends::multicomplex) {
1171 return build_Psir_gradient_multicomplex(model, T, rho);
1174#if defined(TEQP_COMPLEXSTEP_ENABLED)
1175 else if constexpr (be == ADBackends::complex_step) {
1189 typename VectorType::value_type rhotot = rho.sum();
1190 auto molefrac = (rho / rhotot).eval();
1191 auto rhorefideal = 1.0;
1200 template<ADBackends be = ADBackends::autodiff>
1202 VectorType lnphi = get_ln_fugacity_coefficients<be>(model, T, rhovec);
1203 return exp(lnphi).eval();
1211 template<ADBackends be = ADBackends::autodiff>
1214 auto molefrac = (rhovec / rhotot).eval();
1215 auto R = model.R(molefrac);
1217 auto Z = 1.0 + tdx::template get_Ar01<be>(model, T, rhotot, molefrac);
1218 auto grad = build_Psir_gradient<be>(model, T, rhovec).eval();
1220 auto lnphi = ((grad / RT).array() - log(Z)).eval();
1224 template<ADBackends be = ADBackends::autodiff>
1226 auto R = model.R(molefrac);
1228 auto Z = 1.0 + tdx::template get_Ar01<be>(model, T, rhotot, molefrac);
1229 auto rhovec = (rhotot*molefrac).eval();
1230 auto grad = build_Psir_gradient<be>(model, T, rhovec).eval();
1232 auto lnphi = ((grad / RT).array() - log(Z)).eval();
1236 template<ADBackends be = ADBackends::autodiff>
1239 auto molefrac = (rhovec / rhotot).eval();
1240 auto R = model.R(molefrac);
1241 auto grad = build_Psir_gradient<be>(model, T, rhovec).eval();
1243 auto lnphi = ((grad / RT).array()).eval();
1247 template<ADBackends be = ADBackends::autodiff>
1250 auto molefrac = (rhovec / rhotot).eval();
1252 auto Z = 1.0 + tdx::template get_Ar01<be>(model, T, rhotot, molefrac);
1257 Eigen::ArrayXd deriv(rho.size());
1259 for (
auto i = 0; i < rho.size(); ++i) {
1260 auto psirfunc = [&model, &rho, i](
const auto& T,
const auto& rhoi) {
1261 ArrayXdual2nd rhovecc(rho.size());
for (
auto j = 0; j < rho.size(); ++j) { rhovecc[j] = rho[j]; }
1263 auto rhotot_ = rhovecc.sum();
1264 auto molefrac = (rhovecc / rhotot_).eval();
1265 return eval(model.alphar(T, rhotot_, molefrac) * model.R(molefrac) * T * rhotot_);
1267 dual2nd Tdual = T, rhoidual = rho[i];
1268 auto [u00, u10, u11] = derivatives(psirfunc, wrt(Tdual, rhoidual), at(Tdual, rhoidual));
1275 Eigen::ArrayXd deriv(molefrac.size());
1277 for (
auto i = 0; i < molefrac.size(); ++i) {
1278 auto alpharfunc = [&model, &T, &molefrac, i](
const auto& rho,
const auto& xi) {
1279 ArrayXdual2nd molefracdual = molefrac.template cast<autodiff::dual2nd>();
1280 molefracdual[i] = xi;
1281 return forceeval(model.alphar(T, rho, molefracdual));
1283 dual2nd rhodual = rhomolar, xidual = molefrac[i];
1284 auto [u00, u10, u11] = derivatives(alpharfunc, wrt(rhodual, xidual), at(rhodual, xidual));
1298 template<ADBackends be = ADBackends::autodiff>
1301 auto molefrac = (rhovec / rhotot).eval();
1302 auto R = model.R(molefrac);
1304 auto Z = 1.0 + tdx::template get_Ar01<be>(model, T, rhotot, molefrac);
1305 auto dZdT_Z = tdx::template get_Ar11<be>(model, T, rhotot, molefrac)/(-T)/Z;
1306 VectorType grad = build_Psir_gradient<be>(model, T, rhovec).eval();
1308 return forceeval((1/(R*T)*(Tgrad - 1.0/T*grad)-dZdT_Z).eval());
1316 template<ADBackends be = ADBackends::autodiff>
1319 auto molefrac = (rhovec / rhotot).eval();
1321 auto Ar01 = tdx::template get_Ar01<be>(model, T, rhotot, molefrac);
1322 auto Ar02 = tdx::template get_Ar02<be>(model, T, rhotot, molefrac);
1323 auto Z = 1.0 + Ar01;
1324 auto dZdrho = (Ar01 + Ar02)/rhotot;
1325 return std::make_tuple(log(Z), Z, dZdrho);
1335 template<ADBackends be = ADBackends::autodiff>
1338 auto molefrac = (rhovec / rhotot).eval();
1339 auto R = model.R(molefrac);
1342 return forceeval((1/(R*T)*(hessian*molefrac.matrix()).array() - dZdrho/Z).eval());
1352 template<ADBackends be = ADBackends::autodiff>
1355 auto drhodv = -rhotot*rhotot;
1366 template<ADBackends be = ADBackends::autodiff>
1369 auto molefrac = (rhovec / rhotot).eval();
1370 auto R = model.R(molefrac);
1373 auto Ar01 = tdx::template get_Ar01<be>(model, T, rhotot, molefrac);
1374 auto Z = 1.0 + Ar01;
1376 Eigen::RowVector<
decltype(rhotot), Eigen::Dynamic> dZdx_Z = dZdx/Z;
1380 Eigen::ArrayXXd out = rhotot/(R*T)*hessian;
1383 out.rowwise() -= dZdx_Z.array();
1387 template<ADBackends be = ADBackends::autodiff>
1390 auto molefrac = (rhovec / rhotot).eval();
1391 auto R = model.R(molefrac);
1395 Eigen::ArrayXXd out = 1/(R*T)*rhotot*hessian;
1404 auto rhotot = rhovec.sum();
1405 auto molefrac = (rhovec / rhotot).eval();
1406 auto rhorefideal = 1.0;
1414 auto rhotot = rhovec.sum();
1415 auto molefrac = (rhovec / rhotot).eval();
1424 auto rhotot = rhovec.sum();
1425 auto molefrac = (rhovec / rhotot).eval();
1426 auto RT = model.R(molefrac)*T;
1428 return (RT + (hessian*rhovec.matrix()).array()).eval();
1475 auto rhotot = rhovec.sum();
1476 auto molefrac = (rhovec / rhotot).eval();
1478 auto RT = model.R(molefrac)*T;
1481 auto numerator = -rhotot*dpdrhovec;
1483 auto ders = tdx::template get_Ar0n<2>(model, T, rhotot, molefrac);
1484 auto denominator = -
pow2(rhotot)*RT*(1 + 2*ders[1] + ders[2]);
1485 return (numerator/denominator).eval();
1488 static VectorType
get_Psir_sigma_derivs(
const Model& model,
const Scalar& T,
const VectorType& rhovec,
const VectorType& v) {
1489 autodiff::Real<4, double> sigma = 0.0;
1490 auto rhovecad = rhovec.template cast<decltype(sigma)>(),
vad = v.template cast<decltype(sigma)>();
1491 auto wrapper = [&rhovecad, &
vad, &T, &model](
const auto& sigma_1) {
1492 auto rhovecused = (rhovecad + sigma_1 *
vad).eval();
1493 auto rhotot = rhovecused.sum();
1494 auto molefrac = (rhovecused / rhotot).eval();
1495 return forceeval(model.alphar(T, rhotot, molefrac) * model.R(molefrac) * T * rhotot);
1497 auto der = derivatives(wrapper, along(1), at(sigma));
1498 VectorType ret(der.size());
1499 for (
auto i = 0; i < ret.size(); ++i){ ret[i] = der[i];}
1504template<
int Nderivsmax>
1508 Eigen::Array<double, Nderivsmax+1, Nderivsmax+1>
derivs;
1510 template<
typename Model,
typename Scalar,
typename VecType>
1513 static_assert(Nderivsmax == 2,
"It's gotta be 2 for now");
1516 auto AX02 = tdx::template get_Agen0n<2>(model, T, rho, z);
1521 auto AX20 = tdx::template get_Agenn0<2>(model, T, rho, z);
1526 derivs(1, 1) = tdx::template get_Agenxy<1,1>(model, T, rho, z);
DerivativeHolderSquare(const Model &model, const Scalar &T, const Scalar &rho, const VecType &z)
Eigen::Array< double, Nderivsmax+1, Nderivsmax+1 > derivs
#define get_ATrhoXiXjXk_runtime_combinations
#define get_ATrhoXi_runtime_combinations
#define get_ATrhoXiXj_runtime_combinations
ContainerType::value_type derivT(const FuncType &f, TType T, const ContainerType &rho)
Given a function, use complex step derivatives to calculate the derivative with respect to the first ...
auto getbaseval(const T &expr)
T powi(const T &x, int n)
From Ulrich Deiters.
auto build_duplicated_tuple_impl(const T &val, std::index_sequence< I... >)
auto build_duplicated_tuple(const T &val)
A function to generate a tuple of N repeated copies of argument val at compile-time.
ContainerType::value_type derivrhoi(const FuncType &f, TType T, const ContainerType &rho, Integer i)
Given a function, use complex step derivatives to calculate the derivative with respect to the given ...
std::valarray< double > vad
static auto get_dPsirdT_constrhovec(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate derivative w.r.t. T at constant molar concentrations.
static auto get_partial_molar_volumes(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate the partial molar volumes of each component.
static auto build_Psir_Hessian_autodiff(const Model &model, const Scalar &T, const VectorType &rho)
Calculate the Hessian of w.r.t. the molar concentrations.
static auto get_d_ln_fugacity_coefficients_dv_constTmolefracs(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate the derivative of the natural logarithm of fugacity coefficient of each component w....
static Eigen::ArrayXd build_d2alphardrhodxi_constT(const Model &model, const Scalar &T, const Scalar &rhomolar, const VectorType &molefrac)
static auto get_d_ln_fugacity_coefficients_dmolefracs_constTrho1(const Model &model, const Scalar &T, const VectorType &rhovec)
static auto get_ln_fugacity_coefficients(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate the natural logarithm of fugacity coefficient of each component.
static auto get_splus(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate the residual entropy ( ) from derivatives of alphar.
static Eigen::ArrayXd build_d2PsirdTdrhoi_autodiff(const Model &model, const Scalar &T, const VectorType &rho)
static auto build_Psi_Hessian_autodiff(const Model &model, const Scalar &T, const VectorType &rho)
Calculate the Hessian of w.r.t. the molar concentrations.
static auto get_d_ln_fugacity_coefficients_drho_constTmolefracs(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate the derivative of the natural logarithm of fugacity coefficient of each component w....
static auto build_Psir_fgradHessian_autodiff(const Model &model, const Scalar &T, const VectorType &rho)
Calculate the function value, gradient, and Hessian of w.r.t. the molar concentrations.
static auto get_Ar10(const Model &model, const Scalar &T, const VectorType &rhovec)
static auto build_Psir_gradient_autodiff(const Model &model, const Scalar &T, const VectorType &rho)
Gradient of Psir = ar*rho w.r.t. the molar concentrations.
static auto get_d_ln_fugacity_coefficients_dmolefracs_constTrho(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate the derivative of the natural logarithm of fugacity coefficient of each component w....
static auto get_pr(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate the residual pressure from derivatives of alphar.
static auto get_lnZ_Z_dZdrho(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate ln(Z), Z, and dZ/drho at constant temperature and mole fractions.
static auto get_Psir(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate .
static auto build_Psir_gradient_complex_step(const Model &model, const Scalar &T, const VectorType &rho)
Gradient of Psir = ar*rho w.r.t. the molar concentrations.
static auto get_d_ln_fugacity_coefficients_dT_constrhovec(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate the derivative of the natural logarithm of fugacity coefficient of each component w....
static auto get_Ar01(const Model &model, const Scalar &T, const VectorType &rhovec)
static auto get_dpdT_constrhovec(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate the temperature derivative of the pressure at constant molar concentrations.
static auto get_ln_fugacity_coefficients2(const Model &model, const Scalar &T, const VectorType &rhovec)
static auto get_dpdrhovec_constT(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate the molar concentration derivatives of the pressure at constant temperature.
static auto get_fugacity_coefficients(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate the fugacity coefficient of each component.
static auto get_Ar00(const Model &model, const Scalar &T, const VectorType &rhovec)
static auto get_ln_fugacity_coefficients_Trhomolefracs(const Model &model, const Scalar &T, const Scalar &rhotot, const VectorType &molefrac)
static auto get_ln_fugacity_coefficients1(const Model &model, const Scalar &T, const VectorType &rhovec)
static auto get_chempotVLE_autodiff(const Model &model, const Scalar &T, const VectorType &rho)
Calculate the chemical potential of each component.
static auto get_dchempotdT_autodiff(const Model &model, const Scalar &T, const VectorType &rhovec)
Calculate the temperature derivative of the chemical potential of each component.
static VectorType get_Psir_sigma_derivs(const Model &model, const Scalar &T, const VectorType &rhovec, const VectorType &v)
static auto build_Psir_gradient(const Model &model, const Scalar &T, const VectorType &rho)
static auto get_ATrhoXiXj_runtime(const AlphaWrapper &w, const Scalar &T, int iT, const Scalar &rho, int iD, const VectorType &molefrac, int i, int iXi, int j, int iXj)
static auto get_Agen0n(const AlphaWrapper &w, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_Ar11(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_ATrhoXiXj(const AlphaWrapper &w, const Scalar &T, const Scalar &rho, const VectorType &molefrac, int i, int j)
static auto get_Agenn0(const AlphaWrapper &w, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_Aig11(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_Aigxy(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_ATrhoXiXjXk(const AlphaWrapper &w, const Scalar &T, const Scalar &rho, const VectorType &molefrac, int i, int j, int k)
static auto get_Ar03(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_AtaudeltaXiXj_runtime(const AlphaWrapper &w, const Scalar &tau, const int iT, const Scalar &delta, const int iD, const VectorType &molefrac, const int i, const int iXi, const int j, const int iXj)
static auto get_Ar20(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_ATrhoXi_runtime(const AlphaWrapper &w, const Scalar &T, int iT, const Scalar &rho, int iD, const VectorType &molefrac, int i, int iXi)
static auto AlphaCaller(const AlphaWrapper &w, const S1 &T, const S2 &rho, const Vec &molefrac)
static auto get_Ar(const int itau, const int idelta, const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_Ar12(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_AtaudeltaXiXjXk_runtime(const AlphaWrapper &w, const Scalar &tau, const int iT, const Scalar &delta, const int iD, const VectorType &molefrac, const int i, int iXi, const int j, const int iXj, const int k, const int iXk)
static auto get_AtaudeltaXi_runtime(const AlphaWrapper &w, const Scalar &tau, const int iT, const Scalar &delta, const int iD, const VectorType &molefrac, const int i, const int iXi)
static auto AlphaCaller(const AlphaWrapper &w, const S1 &T, const S2 &rho, const Vec &molefrac)
static auto AlpharTauDeltaCaller(const AlphaWrapper &, const S1 &, const S2 &, const Vec &molefrac)
static Scalar get_Ar01(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_neff(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_Arn0(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_AtaudeltaXi(const AlphaWrapper &w, const Scalar &tau, const Scalar &delta, const VectorType &molefrac, const int i)
static auto get_Ar02(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto AlpharTauDeltaCaller(const AlphaWrapper &w, const S1 &T, const S2 &rho, const Vec &molefrac)
static auto get_AtaudeltaXiXj(const AlphaWrapper &w, const Scalar &tau, const Scalar &delta, const VectorType &molefrac, const int i, const int j)
static auto get_ATrhoXi(const AlphaWrapper &w, const Scalar &T, const Scalar &rho, const VectorType &molefrac, int i)
static auto get_Ar0n(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_Ar10(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_Arxy(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_Ar00(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_AtaudeltaXiXjXk(const AlphaWrapper &w, const Scalar &tau, const Scalar &delta, const VectorType &molefrac, const int i, const int j, const int k)
static auto get_ATrhoXiXjXk_runtime(const AlphaWrapper &w, const Scalar &T, int iT, const Scalar &rho, int iD, const VectorType &molefrac, int i, int iXi, int j, int iXj, int k, int iXk)
static auto get_Ar30(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_Ar21(const Model &model, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_Agenxy(const AlphaWrapper &w, const Scalar &T, const Scalar &rho, const VectorType &molefrac)
static auto get_dmBnvirdTm(const Model &model, const Scalar &T, const VectorType &molefrac)
Temperature derivatives of a virial coefficient.
static auto get_B12vir(const Model &model, const Scalar &T, const VectorType &molefrac)
Calculate the cross-virial coefficient .
static auto get_dmBnvirdTm_runtime(const int Nderiv, const int NTderiv, const Model &model, const Scalar &T, const VectorType &molefrac)
static auto get_Bnvir(const Model &model, const Scalar &T, const VectorType &molefrac)
static auto get_B2vir(const Model &model, const Scalar &T, const VectorType &molefrac)
static auto get_Bnvir_runtime(const int Nderiv, const Model &model, const Scalar &T, const VectorType &molefrac)
auto operator()(Args &&... args) const