9#include <boost/multiprecision/cpp_bin_float.hpp>
14using namespace cppinterface;
25 const Eigen::Array2d&
x;
26 const Eigen::Array2d&
dx;
27 const Eigen::Array2d&
r;
40 virtual std::string
desc() = 0;
50 return (data.
r.abs().maxCoeff() < threshold) ? s::success : s::keep_going;
52 std::string
desc()
override{
53 return "MaxAbsErrorCondition";
70 double val = std::abs(data.
dx(idx)/data.
x(idx));
71 minval = std::min(val, minval);
73 return (minval < threshold) ? s::success : s::keep_going;
75 std::string
desc()
override{
76 return "MinRelStepsizeCondition";
87 bool allfinite =
true;
89 if (!std::isfinite(data.
x(idx)) || !std::isfinite(data.
dx(idx))){
90 allfinite =
false;
break;
93 return (!allfinite) ? s::fatal : s::keep_going;
95 std::string
desc()
override{
96 return "NanXDXErrorCondition";
107 return "NegativeXErrorCondition";
113 const std::size_t Nmax;
118 return (data.
N >= Nmax) ? s::fatal : s::keep_going;
121 return "StepCountErrorCondition";
137 auto get_R(
const std::vector<double>& z)
const{
138 const auto zz = Eigen::Map<const Eigen::ArrayXd>(&z[0], z.size());
147 Eigen::Array33d
get_deriv_mat2(
double T,
double rho,
const std::vector<double>& z)
const{
148 const auto zz = Eigen::Map<const Eigen::ArrayXd>(&z[0], z.size());
156 return std::make_tuple(A00A01[0], A10, A00A01[1]);
169 template<
typename Array>
170 auto get_vals(
const std::vector<char>& vars,
const double R,
const double T,
const double rho,
const Array &z)
const{
174 auto dTrecipdT = -Trecip*Trecip;
185 auto alpha = [&](){
return A00; };
186 auto dalphadTrecip = [&](){
return A10/Trecip; };
187 auto dalphadrho = [&](){
return A01/rho; };
190 auto a = [&](){
return alpha()*R*T; };
191 auto dadTrecip = [&](){
return R/(Trecip*Trecip)*(Trecip*dalphadTrecip()-alpha()); };
192 auto dadrho = [&](){
return R/Trecip*(dalphadrho()); };
194 for (
auto i = 0; i < vars.size(); ++i){
201 v(i) = rho*rho*dadrho();
break;
203 v(i) = Trecip*Trecip*dadTrecip();
break;
205 v(i) = a() + Trecip*dadTrecip() + rho*dadrho();
break;
207 v(i) = a() + Trecip*dadTrecip();
break;
209 throw std::invalid_argument(
"bad var: " + std::to_string(vars[i]));
215static_assert(std::is_copy_constructible_v<AlphaModel>);
231 const std::vector<char> vars;
232 const Eigen::Array2d vals;
234 const Eigen::ArrayXd z;
238 std::tuple<bool, bool> relative_error;
239 const std::vector<std::shared_ptr<StoppingCondition>> stopping_conditions;
241 int step_counter = 0;
243 std::vector<int> nonconstant_indices;
247 NRIterator(
const AlphaModel& alphamodel,
const std::vector<char>& vars,
const Eigen::Array2d& vals,
double T,
double rho,
const Eigen::Ref<const Eigen::ArrayXd>& z,
const std::tuple<bool, bool> &relative_error,
const std::vector<std::shared_ptr<StoppingCondition>> stopping_conditions) : alphamodel(alphamodel), vars(vars), vals(vals), Trho((Eigen::Array2d() << T,rho).finished()), z(z), R(alphamodel.get_R(z)), relative_error(relative_error), stopping_conditions(stopping_conditions) {
248 if(!(vars[0] ==
'T' || vars[1] ==
'T')){ nonconstant_indices.push_back(0); }
249 if(!(vars[0] ==
'D' || vars[1] ==
'D')){ nonconstant_indices.push_back(1); }
250 isTD = (nonconstant_indices.size() == 0);
255 std::vector<char>
get_vars()
const {
return vars; }
259 auto get_T()
const {
return Trho(0); }
272 Trho = (Eigen::Array2d() << T, rho).finished();
287 return std::make_tuple((im.J.matrix().colPivHouseholderQr().solve((-(im.v-vals)).matrix())).eval(), im);
297 Eigen::Array2d r = im.v-vals;
298 if (std::get<0>(relative_error)){ r(0) /= vals(0);}
299 if (std::get<1>(relative_error)){ r(1) /= vals(1);}
304 if (std::get<0>(relative_error)){ im.J.row(0) /= vals(0);}
305 if (std::get<1>(relative_error)){ im.J.row(1) /= vals(1);}
310 Eigen::Array2d r = alphamodel.
get_vals(vars, R, T, rho, z)-vals;
311 if (std::get<0>(relative_error)){ r(0) /= vals(0);}
312 if (std::get<1>(relative_error)){ r(1) /= vals(1);}
313 return r.abs().maxCoeff();
323 auto tic = std::chrono::steady_clock::now();
325 for (
auto K = 0; K < N; ++K){
327 Eigen::Array2d r = im.v-vals;
329 if (std::get<0>(relative_error)){ r(0) /= vals(0); im.J.row(0) /= vals(0); }
330 if (std::get<1>(relative_error)){ r(1) /= vals(1); im.J.row(1) /= vals(1); }
332 Eigen::Array2d dTrho = im.J.matrix().fullPivLu().solve((-r).matrix());
343 const StoppingData data{N, Trho, dTrho, r, nonconstant_indices};
344 for (
auto& condition : stopping_conditions){
346 auto this_reason = condition->stop(data);
347 if (this_reason != s::keep_going){
348 stop =
true; reason = this_reason; msg = condition->desc();
break;
358 auto toc = std::chrono::steady_clock::now();
371 auto tic = std::chrono::steady_clock::now();
374 for (
auto K = 0; K < N; ++K){
376 Eigen::Array2d r = im.v-vals;
378 im.J.col(1) *= Trho(1);
379 if (std::get<0>(relative_error)){ r(0) /= vals(0); im.J.row(0) /= vals(0); }
380 if (std::get<1>(relative_error)){ r(1) /= vals(1); im.J.row(1) /= vals(1); }
392 using my_float = boost::multiprecision::number<boost::multiprecision::cpp_bin_float<164U>>;
393 Eigen::Matrix<my_float, 2, 2> Jmp = im.J.cast<my_float>();
394 Eigen::Vector<my_float, 2> rmp = r.cast<my_float>();
395 step = Jmp.fullPivLu().solve(-rmp).cast<
double>();
396 Eigen::Array<my_float, 2, -1> newvals = (Trho.cast<my_float>() + Jmp.fullPivLu().solve(-rmp).array());
398 Eigen::Array2d new_double = (Trho + im.J.matrix().fullPivLu().solve((-r).matrix()).array());
399 std::cout <<
"-- " << ((newvals-new_double.cast<my_float>())/Trho.cast<my_float>()).cast<
double>() << std::endl;
402 step = im.J.matrix().fullPivLu().solve((-r).matrix());
404 Eigen::Array2d dTrho = (Eigen::Array2d() << step(0), Trho(1)*(exp(step(1))-1)).finished();
408 const StoppingData data{N, Trho, dTrho, r, nonconstant_indices};
409 for (
auto& condition : stopping_conditions){
411 auto this_reason = condition->stop(data);
412 if (this_reason != s::keep_going){
413 stop =
true; reason = this_reason; msg = condition->desc();
break;
420 if(nonconstant_indices.size() == 0){
444 auto toc = std::chrono::steady_clock::now();
454 Eigen::Array2d vals_current = im.v;
455 double x_current = vals_current(0);
456 double y_current = vals_current(1);
459 double x_target = vals(0);
460 double y_target = vals(1);
461 auto dxdt = (x_target-x_current)/(1.0-0.0);
462 auto dydt = (y_target-y_current)/(1.0-0.0);
466 for (
auto i = 0U; i < N; ++i){
468 auto dxdT__rho = im.J(0, 0);
469 auto dxdrho__T = im.J(0, 1);
470 auto dydT__rho = im.J(1, 0);
471 auto dydrho__T = im.J(1, 1);
473 auto dxdT__y = dxdT__rho - dxdrho__T*dydT__rho/dydrho__T;
474 auto dxdrho__y = dxdrho__T - dxdT__rho*dydrho__T/dydT__rho;
476 auto dydT__x = dydT__rho - dydrho__T*dxdT__rho/dxdrho__T;
477 auto dydrho__x = dydrho__T - dydT__rho*dxdrho__T/dxdT__rho;
480 double dTdt = dxdt/dxdT__y + dydt/dydT__x;
481 double drhodt = dxdt/dxdrho__y + dydt/dydrho__x;
487 std::cout << i <<
"," << (im.v-vals).abs().maxCoeff() << std::endl;
490 return std::make_tuple(T, rho, im.v(0), im.v(1));
std::shared_ptr< AbstractModel > model_residual
auto get_A00A10A01(double T, double rho, const Z &z) const
std::shared_ptr< AbstractModel > model_ideal_gas
auto get_R(const Z &z) const
auto get_R(const std::vector< double > &z) const
auto get_vals(const std::vector< char > &vars, const double R, const double T, const double rho, const Array &z) const
A convenience function for calculation of Jacobian terms of the form and where is one of the therm...
Eigen::Array33d get_deriv_mat2(double T, double rho, const std::vector< double > &z) const
Eigen::Array33d get_deriv_mat2(double T, double rho, const Z &z) const
MaxAbsErrorCondition(double threshold)
StoppingConditionReason stop(const StoppingData &data) override
std::string desc() override
std::string desc() override
MinRelStepsizeCondition(double threshold)
StoppingConditionReason stop(const StoppingData &data) override
Eigen::ArrayXd get_molefrac() const
Return the current mole fractions.
auto calc_maxabsr(double T, double rho) const
Calculate the maximum absolute value of the values in r.
std::vector< char > get_vars() const
Return the variables that are being used in the iteration.
auto calc_J(double T, double rho) const
auto get_T() const
Return the current temperature.
auto path_integration(double T, double rho, std::size_t N)
auto get_rho() const
Return the current molar density.
auto calc_vals(double T, double rho) const
std::string get_message() const
Return the current message relaying information about success or failure of the iteration.
auto calc_just_step(double T, double rho) const
auto get_nonconstant_indices() const
Get the indices of the nonconstant variables.
auto calc_step(double T, double rho) const
Eigen::Array2d get_vals() const
Return the target values to be obtained.
auto calc_matrices(double T, double rho) const
void reset(double T, double rho)
NRIterator(const AlphaModel &alphamodel, const std::vector< char > &vars, const Eigen::Array2d &vals, double T, double rho, const Eigen::Ref< const Eigen::ArrayXd > &z, const std::tuple< bool, bool > &relative_error, const std::vector< std::shared_ptr< StoppingCondition > > stopping_conditions)
int get_step_count() const
Return the current step counter.
auto calc_r(double T, double rho) const
auto take_steps_logrho(int N)
StoppingConditionReason stop(const StoppingData &data) override
std::string desc() override
StoppingConditionReason stop(const StoppingData &data) override
std::string desc() override
std::string desc() override
StepCountErrorCondition(int Nmax)
StoppingConditionReason stop(const StoppingData &data) override
virtual StoppingConditionReason stop(const StoppingData &)=0
virtual std::string desc()=0
auto build_iteration_Jv(const std::vector< char > &vars, const Eigen::Array< double, 3, 3 > &A, const double R, const double T, const double rho, const Array &z)
A convenience function for calculation of Jacobian terms of the form and where is one of the therm...
StoppingConditionReason reason
const Eigen::Array2d & r
The set of residual functions.
const std::vector< int > & nonconstant_indices
The indices where the independent variable can be varied (not T or rho)
const Eigen::Array2d & dx
The complete set of steps in independent variables.
const int N
The number of steps that have been taken so far.
const Eigen::Array2d & x
The complete set of independent variables.