13 #include <Eigen/Dense> 16 using namespace Eigen;
22 const double BroydenJacobian::EPS = 1.0E-6;
23 const double Broyden::TOL = 1.0E-10;
24 const int Broyden::MAX_ITERS = 200;
27 std::vector<double> BroydenJacobian::Jacobian(
const std::vector<double>& x)
29 if (m_Equations == NULL) {
30 printf(
"**ERROR** BroydenJacobian::Jacobian: Equations to solve not specified!\n");
34 if (m_Equations->Dimension() !=
static_cast<int>(x.size())) {
35 printf(
"**ERROR** BroydenJacobian::Jacobian: Equations dimension does not match that of input!\n");
39 int N = m_Equations->Dimension();
41 std::vector<double> h = x;
43 std::vector< std::vector<double> > xh(N);
45 for (
size_t i = 0; i < x.size(); ++i) {
46 h[i] = m_dx*abs(h[i]);
47 if (h[i] == 0.0) h[i] = m_dx;
48 if (h[i] < 1.e-10) h[i] = 1.e-10;
52 for (
size_t i = 0; i < x.size(); ++i) {
54 for (
size_t j = 0; j < x.size(); ++j) {
58 xh[i][j] = x[j] + h[j];
62 std::vector<double> Jac(N*N);
64 std::vector<double> fx = m_Equations->Equations(x);
66 for (
int j = 0; j < N; ++j) {
67 std::vector<double> dfdxj = m_Equations->Equations(xh[j]);
68 for (
size_t i = 0; i < dfdxj.size(); ++i) {
69 dfdxj[i] = (dfdxj[i] - fx[i]) / h[j];
70 Jac[i*N + j] = dfdxj[i];
79 if (m_Equations == NULL) {
80 printf(
"**ERROR** Broyden::Solve: Equations to solve not specified!\n");
84 m_MaxIterations = max_iterations;
87 bool UseDefaultSolutionCriterium =
false;
88 if (SolutionCriterium == NULL) {
90 UseDefaultSolutionCriterium =
true;
94 bool UseDefaultJacobian =
false;
95 if (JacobianInUse == NULL) {
97 UseDefaultJacobian =
true;
100 double &maxdiff = m_MaxDifference;
101 int N = m_Equations->Dimension();
102 std::vector<double> xcur = x0, tmpvec, xdeltavec = x0;
103 VectorXd xold(N), xnew(N), xdelta(N);
104 VectorXd fold(N), fnew(N), fdelta(N);
106 xold = VectorXd::Map(&xcur[0], xcur.size());
108 MatrixXd Jac = Eigen::Map< Matrix<double, Dynamic, Dynamic, RowMajor> >(&JacobianInUse->
Jacobian(xcur)[0], N, N);
110 if (Jac.determinant() == 0.0)
112 printf(
"**WARNING** Singular Jacobian in Broyden::Solve\n");
116 MatrixXd Jinv = Jac.inverse();
117 tmpvec = m_Equations->Equations(xcur);
118 fold = VectorXd::Map(&tmpvec[0], tmpvec.size());
120 for (m_Iterations = 1; m_Iterations < max_iterations; ++m_Iterations) {
121 xnew = xold - Jinv * fold;
123 VectorXd::Map(&xcur[0], xcur.size()) = xnew;
125 tmpvec = m_Equations->Equations(xcur);
126 fnew = VectorXd::Map(&tmpvec[0], tmpvec.size());
130 for (
size_t i = 0; i < xcur.size(); ++i) {
131 maxdiff = std::max(maxdiff, fabs(fnew[i]));
134 xdelta = xnew - xold;
135 fdelta = fnew - fold;
137 VectorXd::Map(&xdeltavec[0], xdeltavec.size()) = xdelta;
139 if (SolutionCriterium->
IsSolved(xcur, tmpvec, xdeltavec))
147 for (
int i = 0; i < N; ++i)
148 for (
int j = 0; j < N; ++j)
149 norm += xdelta[i] * Jinv(i, j) * fdelta[j];
151 p1 = (xdelta - Jinv * fdelta);
152 for (
int i = 0; i < N; ++i) p1[i] *= 1. / norm;
153 Jinv = Jinv + (p1 * xdelta.transpose()) * Jinv;
157 Jac = Eigen::Map< Matrix<double, Dynamic, Dynamic, RowMajor> >(&JacobianInUse->
Jacobian(xcur)[0], N, N);
158 Jinv = Jac.inverse();
165 if (UseDefaultSolutionCriterium) {
166 delete SolutionCriterium;
167 SolutionCriterium = NULL;
169 if (UseDefaultJacobian) {
170 delete JacobianInUse;
171 JacobianInUse = NULL;
176 bool Broyden::BroydenSolutionCriterium::IsSolved(
const std::vector<double>& x,
const std::vector<double>& f,
const std::vector<double>& xdelta)
const 178 double maxdiff = 0., maxdiffxdelta = 0.;
179 for (
size_t i = 0; i < x.size(); ++i) {
180 maxdiff = std::max(maxdiff, fabs(f[i]));
181 maxdiffxdelta = std::max(maxdiffxdelta, fabs(xdelta[i]));
183 return (maxdiff < m_MaximumError) || maxdiffxdelta == 0.;
virtual std::vector< double > Jacobian(const std::vector< double > &x)
Evaluates the Jacobian for given values of the variables.
Sub-class where it is determined whether the required accuracy is achieved in the Broyden's method...
Class which implements calculation of the Jacobian needed for the Broyden's method.
Implementation of the generic Broyden's method routines.
The main namespace where all classes and functions of the Thermal-FIST library reside.
virtual bool IsSolved(const std::vector< double > &x, const std::vector< double > &f, const std::vector< double > &xdelta=std::vector< double >()) const