15 std::size_t N = x.size();
16 std::vector<double> r, xp;
17 std::vector<std::vector<double>> J(N, std::vector<double>(N, 0));
18 std::vector<double> r0 =
call(x);
20 for (std::size_t i = 0; i < N; ++i) {
22 epsilon = 0.001 * x[i];
26 for (std::size_t j = 0; j < N; ++j) {
27 J[j][i] = (r[j] - r0[j]) / epsilon;
53 std::vector<double> f0, v;
54 std::vector<std::vector<double>> JJ;
55 std::vector<double> x0 = x;
56 Eigen::VectorXd r(x0.size());
57 Eigen::MatrixXd J(x0.size(), x0.size());
59 while (iter == 0 || std::abs(error) > tol) {
63 for (std::size_t i = 0; i < x0.size(); ++i) {
65 for (std::size_t j = 0; j < x0.size(); ++j) {
70 Eigen::VectorXd v = J.colPivHouseholderQr().solve(-r);
73 double max_relchange = -1;
74 for (std::size_t i = 0; i < x0.size(); i++) {
76 double relchange = std::abs(v(i) / x0[i]);
77 if (std::abs(x0[i]) > 1e-16 && relchange > max_relchange) {
78 max_relchange = relchange;
83 double max_abschange = v.cwiseAbs().maxCoeff();
87 if (max_relchange < 1e-12) {
92 f->
errstring =
"reached maximum number of iterations";
110 double x, dx, dfdx, fval = 999;
116 while (f->
iter < maxiter || std::abs(fval) > ftol) {
122 f->
errstring =
"Residual function in newton returned invalid number";
123 throw ValueError(
"Residual function in newton returned invalid number");
127 std::cout <<
format(
"i: %d, x: %0.15g, dx: %g, f: %g, dfdx: %g", f->
iter, x, dx, fval, dfdx) << std::endl;
132 if (std::abs(dx / x) < 1e-11) {
136 if (f->
iter > maxiter) {
137 f->
errstring =
"Newton reached maximum number of iterations";
161 double x, dx, fval = 999, dfdx, d2fdx2;
171 while (f->
iter < 2 || std::abs(fval) > ftol) {
173 std::string msg =
format(
"Input [%0.15g] is out of range", x);
183 f->
errstring =
"Residual function in Halley returned invalid number";
184 throw ValueError(
"Residual function in Halley returned invalid number");
187 f->
errstring =
"Derivative function in Halley returned invalid number";
188 throw ValueError(
"Derivative function in Halley returned invalid number");
191 dx = -omega * (2 * fval * dfdx) / (2 *
POW2(dfdx) - fval * d2fdx2);
194 std::cout <<
format(
"i: %d, x: %0.15g, dx: %g, f: %g, dfdx: %g, d2fdx2: %g", f->
iter, x, dx, fval, dfdx, d2fdx2) << std::endl;
201 if (std::abs(dx / x) < xtol_rel) {
205 if (f->
iter > maxiter) {
206 f->
errstring =
"Halley reached maximum number of iterations";
231 double x, dx, fval = 999, dfdx, d2fdx2, d3fdx3;
241 while (f->
iter < 2 || std::abs(fval) > ftol) {
252 throw ValueError(
"Residual function in Householder4 returned invalid number");
255 throw ValueError(
"Derivative function in Householder4 returned invalid number");
258 throw ValueError(
"Second derivative function in Householder4 returned invalid number");
261 throw ValueError(
"Third derivative function in Householder4 returned invalid number");
264 dx = -omega * fval * (
POW2(dfdx) - fval * d2fdx2 / 2.0) / (
POW3(dfdx) - fval * dfdx * d2fdx2 + d3fdx3 *
POW2(fval) / 6.0);
268 if (std::abs(dx / x) < xtol_rel) {
272 if (f->
iter > maxiter) {
273 f->
errstring =
"reached maximum number of iterations";
292#if defined(COOLPROP_DEEP_DEBUG)
293 static std::vector<double> xlog, flog;
299 double x1 = 0, x2 = 0, x3 = 0, y1 = 0, y2 = 0, x = x0, fval = 999;
306 if (std::abs(dx) == 0) {
310 while (f->
iter <= 2 || std::abs(fval) > tol) {
329#if defined(COOLPROP_DEEP_DEBUG)
331 flog.push_back(fval);
335 throw ValueError(
"Residual function in secant returned invalid number");
341 double deltax = x2 - x1;
342 if (std::abs(deltax) < 1e-14) {
346 double deltay = y2 - y1;
347 if (f->
iter > 2 && std::abs(deltay) < 1e-14) {
350 x3 = x2 - omega * y2 / (y2 - y1) * (x2 - x1);
355 if (f->
iter > maxiter) {
356 f->
errstring = std::string(
"reached maximum number of iterations");
377 double x1 = 0, x2 = 0, x3 = 0, y1 = 0, y2 = 0, x, fval = 999;
380 if (std::abs(dx) == 0) {
384 while (iter <= 3 || std::abs(fval) > tol) {
388 }
else if (iter == 2) {
399 x3 = x2 - y2 / (y2 - y1) * (x2 - x1);
402 x3 = (xmin + x2) / 2;
405 x3 = (xmax + x2) / 2;
411 if (iter > maxiter) {
412 f->
errstring =
"reached maximum number of iterations";
434 #if defined(COOLPROP_DEEP_DEBUG)
435 static std::vector<double> xlog, flog;
436 xlog.clear(); flog.clear();
440 double x1=0,x2=0,x3=0,y0=0,y1=0,y2=0,x=x0,fval=999;
447 if (std::abs(dx)==0){ f->
errstring=
"dx cannot be zero";
return _HUGE;}
448 while (f->
iter<=2 || std::abs(fval)>tol)
450 if (f->
iter==1){x1=x0; x=x1;}
451 if (f->
iter==2){x2=x0+dx; x=x2;}
452 if (f->
iter>2) {x=x2;}
460 #if defined(COOLPROP_DEEP_DEBUG)
462 flog.push_back(fval);
466 if (f->
iter==1){
return x;}
467 else {
return x2-omega*y1/(y1-y0)*(x2-x1);}
469 if (f->
iter==1){y1=fval;}
472 double deltax = x2-x1;
473 if (std::abs(deltax)<1e-14){
477 double deltay = y2-y1;
478 if (f->
iter > 2 && std::abs(deltay)<1e-14){
481 x3=x2-omega*y2/(y2-y1)*(x2-x1);
482 y0=y1;y1=y2; x1=x2; x2=x3;
487 f->
errstring=std::string(
"reached maximum number of iterations");
513 double fa, fb, c, fc, m, tol, d, e, p, q, s, r;
518 if (std::abs(fb) < t) {
522 throw ValueError(
format(
"Brent's method f(b) is NAN for b = %g, other input was a = %g", b, a).c_str());
524 if (std::abs(fa) < t) {
528 throw ValueError(
format(
"Brent's method f(a) is NAN for a = %g, other input was b = %g", a, b).c_str());
531 throw ValueError(
format(
"Inputs in Brent [%f,%f] do not bracket the root. Function values are [%f,%f]", a, b, fa, fb));
537 if (std::abs(fc) < std::abs(fb)) {
549 tol = 2 * macheps * std::abs(b) + t;
550 while (std::abs(m) > tol && fb != 0) {
552 if (std::abs(e) < tol || std::abs(fa) <= std::abs(fb)) {
566 p = s * (2 * m * q * (q - r) - (b - a) * (r - 1));
567 q = (q - 1) * (r - 1) * (s - 1);
577 if (2 * p < 3 * m * q - std::abs(tol * q) || p < std::abs(0.5 * s * q)) {
586 if (std::abs(d) > tol) {
595 throw ValueError(
format(
"Brent's method f(t) is NAN for t = %g", b).c_str());
597 if (std::abs(fb) < macheps) {
606 if (std::abs(fc) < std::abs(fb)) {
616 tol = 2 * macheps * std::abs(b) + t;
627 if (iter > maxiter) {
628 throw SolutionError(
format(
"Brent's method reached maximum number of steps of %d ", maxiter));
630 if (std::abs(fb) < 2 * macheps * std::abs(b)) {