teqp 0.22.0
Loading...
Searching...
No Matches
rootfinding.hpp
Go to the documentation of this file.
1#pragma once
2
3namespace teqp{
4
5template<typename Callable, typename Inputs>
6auto NewtonRaphson(Callable f, const Inputs& args, double tol) {
7 // Jacobian matrix
8 Eigen::ArrayXd x = args, r0;
9 Eigen::MatrixXd J(args.size(), args.size());
10 for (int iter = 0; iter < 30; ++iter) {
11 r0 = f(x);
12 for (auto i = 0; i < args.size(); ++i) {
13 auto dri = std::max(1e-6 * x[i], 1e-8);
14 auto argsplus = x;
15 argsplus[i] += dri;
16 J.col(i) = (f(argsplus) - r0) / dri; // Forward diff to avoid negative concentration possibility
17 }
18 Eigen::ArrayXd v = J.colPivHouseholderQr().solve(-r0.matrix());
19 x += v;
20 auto err = r0.matrix().norm();
21 if (!std::isfinite(err)){
22 throw std::invalid_argument("err is now NaN");
23 }
24 if (err < tol) {
25 break;
26 }
27 }
28 return x;
29}
30
31}; /* namespace teqp */
auto NewtonRaphson(Callable f, const Inputs &args, double tol)