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 if (Jac.determinant() == 0.0)
117 std::cerr <<
"**WARNING** Singular Jacobian in Broyden::Solve" << std::endl;
121 MatrixXd Jinv = Jac.inverse();
123 fold = VectorXd::Map(&tmpvec[0], tmpvec.size());
126 xnew = xold - Jinv * fold;
128 VectorXd::Map(&xcur[0], xcur.size()) = xnew;
131 fnew = VectorXd::Map(&tmpvec[0], tmpvec.size());
135 for (
size_t i = 0; i < xcur.size(); ++i) {
136 maxdiff = std::max(maxdiff, fabs(fnew[i]));
139 xdelta = xnew - xold;
140 fdelta = fnew - fold;
142 VectorXd::Map(&xdeltavec[0], xdeltavec.size()) = xdelta;
144 if (SolutionCriterium->
IsSolved(xcur, tmpvec, xdeltavec))
152 for (
int i = 0; i < N; ++i)
153 for (
int j = 0; j < N; ++j)
154 norm += xdelta[i] * Jinv(i, j) * fdelta[j];
156 p1 = (xdelta - Jinv * fdelta);
157 for (
int i = 0; i < N; ++i) p1[i] *= 1. / norm;
158 Jinv = Jinv + (p1 * xdelta.transpose()) * Jinv;
162 Jac = Eigen::Map< Matrix<double, Dynamic, Dynamic, RowMajor> >(&JacobianInUse->
Jacobian(xcur)[0], N, N);
163 Jinv = Jac.inverse();
170 if (UseDefaultSolutionCriterium) {
171 delete SolutionCriterium;
172 SolutionCriterium = NULL;
174 if (UseDefaultJacobian) {
175 delete JacobianInUse;
176 JacobianInUse = NULL;
183 double maxdiff = 0., maxdiffxdelta = 0.;
184 for (
size_t i = 0; i < x.size(); ++i) {
185 maxdiff = std::max(maxdiff, fabs(f[i]));
186 maxdiffxdelta = std::max(maxdiffxdelta, fabs(xdelta[i]));