396 auto call(
const Eigen::ArrayXd&x){
398 auto& J =
res.
J; J.setZero();
399 auto& r =
res.
r; r.setZero();
407 std::vector<Eigen::Map<const Eigen::ArrayXd>> rhovecs;
408 for (
auto iphase_ = 0; iphase_ <
Nphases; ++iphase_){
409 rhovecs.push_back(Eigen::Map<const Eigen::ArrayXd>(&x[1 + iphase_*Ncomp],
Ncomponents));
411 const Eigen::Map<const Eigen::ArrayXd> betas(&x[x.size()-
Nphases],
Nphases);
416 auto calculate_required_derivatives = [
this, R](
auto& modelref,
double T,
const Eigen::ArrayXd& rhovec) ->
RequiredPhaseDerivatives{
418 der.
rho = rhovec.sum();
430 std::vector<RequiredPhaseDerivatives> derivatives;
431 for (
auto iphase_ = 0; iphase_ <
Nphases; ++iphase_){
432 derivatives.emplace_back(calculate_required_derivatives(this->residptr, T, rhovecs[iphase_]));
436 std::size_t irow = 0;
437 std::size_t iphase = 0;
439 auto lnf_phase0 = log(rhovecs[iphase]*R*T) + 1/(R*T)*derivatives[iphase].gradient_Psir;
440 auto dlnfdT_phase0 = 1/T + 1/(R*T)*derivatives[iphase].d_gradient_Psir_dT - 1/(R*T*T)*derivatives[iphase].gradient_Psir;
441 Eigen::ArrayXXd dlnfdrho_phase0 = Eigen::MatrixXd::Identity(Ncomp, Ncomp);
442 dlnfdrho_phase0.matrix().diagonal().array() /= rhovecs[iphase];
443 dlnfdrho_phase0 += 1/(R*T)*derivatives[iphase].Hessian_Psir;
445 for (
auto iphasei = 1; iphasei <
Nphases; ++iphasei){
447 auto lnf_phasei = log(rhovecs[iphasei]*R*T) + 1.0/(R*T)*derivatives[iphasei].gradient_Psir;
448 auto dlnfdT_phasei = 1/T + 1.0/(R*T)*derivatives[iphasei].d_gradient_Psir_dT - 1/(R*T*T)*derivatives[iphasei].gradient_Psir;
449 Eigen::ArrayXXd dlnfdrho_phasei = Eigen::MatrixXd::Identity(Ncomp, Ncomp);
450 dlnfdrho_phasei.matrix().diagonal().array() /= rhovecs[iphasei];
451 dlnfdrho_phasei += 1/(R*T)*derivatives[iphasei].Hessian_Psir;
454 r.segment(irow, Ncomp) = lnf_phase0 - lnf_phasei;
457 J.block(irow, 0, Ncomp, 1) = dlnfdT_phase0 - dlnfdT_phasei;
461 for (
auto iphasej = 0; iphasej < Ncomp; ++iphasej){
463 J.block(irow, 1+iphasej*Ncomp, Ncomp, Ncomp) = dlnfdrho_phase0;
466 J.block(irow, 1+iphasej*Ncomp, Ncomp, Ncomp) = -dlnfdrho_phasei;
474 double p_phase0 = derivatives[iphase].p(T, rhovecs[iphase]);
475 double dpdT_phase0 = derivatives[iphase].dpdT(T, rhovecs[iphase]);
476 Eigen::ArrayXd dpdrho_phase0 = derivatives[iphase].dpdrhovec(T, rhovecs[iphase]);
477 for (
auto iphasei = 1; iphasei <
Nphases; ++iphasei){
478 double p_phasei = derivatives[iphasei].p(T, rhovecs[iphasei]);
479 double dpdT_phasei = derivatives[iphasei].dpdT(T, rhovecs[iphasei]);
480 Eigen::ArrayXd dpdrho_phasei = derivatives[iphasei].dpdrhovec(T, rhovecs[iphasei]);
481 r[irow] = p_phase0 - p_phasei;
482 J(irow, 0) = dpdT_phase0 - dpdT_phasei;
483 for (
auto iphasej = 0; iphasej <
Nphases; ++iphasej){
485 J.block(irow, 1+iphasej*Ncomp, 1, Ncomp) = dpdrho_phase0.transpose();
488 J.block(irow, 1+iphasej*Ncomp, 1, Ncomp) = -dpdrho_phasei.transpose();
496 for (
auto icomp = 0; icomp < Ncomp-1; ++icomp){
498 for (iphase = 0; iphase <
Nphases; ++iphase){
499 double rho_phase = rhovecs[iphase].sum();
500 double xj_phk = rhovecs[iphase][icomp]/rho_phase;
501 summer += betas[iphase]*xj_phk;
502 J(irow, J.cols()-
Nphases+iphase) = xj_phk;
503 for (
auto icompj = 0; icompj < Ncomp; ++icompj){
504 auto Kronecker = [](
int i,
int j){
return i==j; };
505 J(irow, 1+iphase*Ncomp + icompj) = betas[iphase]*(Kronecker(icomp,icompj) - rhovecs[iphase][icomp]/rho_phase)/rho_phase;
508 r[irow] = summer -
zbulk[icomp];
513 r[irow] = betas.sum()-1;
528 auto calculate_caloric_derivatives = [
this, R](
auto& modelref,
auto& modelresid,
double T,
const Eigen::ArrayXd& rhovec) ->
CaloricPhaseDerivatives{
530 der.
rho = rhovec.sum();
532 auto molefracs = (rhovec/der.
rho).eval();
533 der.
Psiig = modelref.get_Ar00(T, der.
rho, molefracs)*R*T*der.
rho;
543 der.
gradient_Psiig = modelref.build_Psir_gradient_autodiff(T, rhovec);
547 std::vector<CaloricPhaseDerivatives> caloricderivatives;
548 if (this->idealgasptr){
549 for (
auto iphase_ = 0; iphase_ <
Nphases; ++iphase_){
550 caloricderivatives.emplace_back(calculate_caloric_derivatives(*this->idealgasptr->get(),
residptr, T, rhovecs[iphase_]));
557 auto [r_, J_] = spec->r_Jacobian(x, sidecar);