37 if (m_Equations == NULL) {
38 throw std::runtime_error(
"BroydenJacobian::Jacobian: Equations to solve not specified!");
41 if (m_Equations->Dimension() !=
static_cast<int>(x.size())) {
42 throw std::runtime_error(
"**ERROR** BroydenJacobian::Jacobian: Equations dimension does not match that of input!");
45 int N = m_Equations->Dimension();
47 std::vector<double> h = x;
49 std::vector< std::vector<double> > xh(N);
51 for (
size_t i = 0; i < x.size(); ++i) {
52 h[i] = m_dx*std::abs(h[i]);
53 if (h[i] == 0.0) h[i] = m_dx;
54 if (h[i] < 1.e-10) h[i] = 1.e-10;
58 for (
size_t i = 0; i < x.size(); ++i) {
60 for (
size_t j = 0; j < x.size(); ++j) {
64 xh[i][j] = x[j] + h[j];
68 std::vector<double> Jac(N*N);
70 std::vector<double> fx = m_Equations->Equations(x);
72 for (
int j = 0; j < N; ++j) {
73 std::vector<double> dfdxj = m_Equations->Equations(xh[j]);
74 for (
size_t i = 0; i < dfdxj.size(); ++i) {
75 dfdxj[i] = (dfdxj[i] - fx[i]) / h[j];
76 Jac[i*N + j] = dfdxj[i];
86 throw std::runtime_error(
"Broyden::Solve: Equations to solve not specified!");
92 bool UseDefaultSolutionCriterium =
false;
93 if (SolutionCriterium == NULL) {
95 UseDefaultSolutionCriterium =
true;
99 bool UseDefaultJacobian =
false;
100 if (JacobianInUse == NULL) {
102 UseDefaultJacobian =
true;
107 std::vector<double> xcur = x0, tmpvec, xdeltavec = x0;
108 VectorXd xold(N), xnew(N), xdelta(N);
109 VectorXd fold(N), fnew(N), fdelta(N);
111 xold = VectorXd::Map(&xcur[0], xcur.size());
113 MatrixXd Jac = Eigen::Map< Matrix<double, Dynamic, Dynamic, RowMajor> >(&JacobianInUse->
Jacobian(xcur)[0], N, N);
115 double det = Jac.determinant();
116 if (det == 0.0 || std::abs(det) < 1.e-300)
118 std::cerr <<
"**WARNING** Singular Jacobian in Broyden::Solve (det=" << det <<
")" << std::endl;
122 MatrixXd Jinv = Jac.inverse();
125 bool hasNaNInverse =
false;
126 for (
int i = 0; i < N && !hasNaNInverse; ++i)
127 for (
int j = 0; j < N && !hasNaNInverse; ++j)
128 if (std::isnan(Jinv(i,j)) || std::isinf(Jinv(i,j)))
129 hasNaNInverse =
true;
131 std::cerr <<
"**WARNING** NaN/Inf in Jacobian inverse in Broyden::Solve (det=" << det <<
")" << std::endl;
135 fold = VectorXd::Map(&tmpvec[0], tmpvec.size());
138 xnew = xold - Jinv * fold;
141 bool hasNaNSolution =
false;
142 for (
int i = 0; i < N; ++i)
143 if (std::isnan(xnew[i]) || std::isinf(xnew[i]))
144 hasNaNSolution =
true;
145 if (hasNaNSolution) {
146 std::cerr <<
"**WARNING** NaN/Inf in Broyden iteration " <<
m_Iterations <<
", solver failed" << std::endl;
148 VectorXd::Map(&xcur[0], xcur.size()) = xold;
153 VectorXd::Map(&xcur[0], xcur.size()) = xnew;
156 fnew = VectorXd::Map(&tmpvec[0], tmpvec.size());
160 for (
size_t i = 0; i < xcur.size(); ++i) {
161 maxdiff = std::max(maxdiff, fabs(fnew[i]));
164 xdelta = xnew - xold;
165 fdelta = fnew - fold;
167 VectorXd::Map(&xdeltavec[0], xdeltavec.size()) = xdelta;
169 if (SolutionCriterium->
IsSolved(xcur, tmpvec, xdeltavec))
177 for (
int i = 0; i < N; ++i)
178 for (
int j = 0; j < N; ++j)
179 norm += xdelta[i] * Jinv(i, j) * fdelta[j];
182 if (std::abs(norm) < 1.e-25) {
184 Jac = Eigen::Map< Matrix<double, Dynamic, Dynamic, RowMajor> >(&JacobianInUse->
Jacobian(xcur)[0], N, N);
185 if (Jac.determinant() != 0.0)
186 Jinv = Jac.inverse();
190 p1 = (xdelta - Jinv * fdelta);
191 for (
int i = 0; i < N; ++i) p1[i] *= 1. / norm;
192 Jinv = Jinv + (p1 * xdelta.transpose()) * Jinv;
197 Jac = Eigen::Map< Matrix<double, Dynamic, Dynamic, RowMajor> >(&JacobianInUse->
Jacobian(xcur)[0], N, N);
198 Jinv = Jac.inverse();
205 if (UseDefaultSolutionCriterium) {
206 delete SolutionCriterium;
207 SolutionCriterium = NULL;
209 if (UseDefaultJacobian) {
210 delete JacobianInUse;
211 JacobianInUse = NULL;
218 double maxdiff = 0., maxdiffxdelta = 0.;
219 for (
size_t i = 0; i < x.size(); ++i) {
220 maxdiff = std::max(maxdiff, fabs(f[i]));
221 maxdiffxdelta = std::max(maxdiffxdelta, fabs(xdelta[i]));