Isis 3 Programmer Reference
NonLinearLSQ.cpp
Go to the documentation of this file.
1 
24 #include <string>
25 #include <vector>
26 #include <numeric>
27 #include <iostream>
28 #include <sstream>
29 
30 #include <gsl/gsl_errno.h>
31 #include <gsl/gsl_blas.h>
32 #include <gsl/gsl_multifit_nlin.h>
33 
34 #include "NonLinearLSQ.h"
35 #include "IException.h"
36 #include "IString.h"
37 
38 using namespace std;
39 
40 namespace Isis {
41 
42 
43 int NonLinearLSQ::curvefit() {
44 
45  size_t n(nSize());
46  size_t p(nParms());
47 
48  // Initialize the solver function information
49  _nlsqPointer d = { this };
50  gsl_multifit_function_fdf mf;
51  mf.f = &f;
52  mf.df = &df;
53  mf.fdf = &fdf;
54  mf.n = n;
55  mf.p = p;
56  mf.params = &d;
57 
58  const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder;
59  gsl_multifit_fdfsolver *s = gsl_multifit_fdfsolver_alloc(T, n, p);
60 
61  _fitParms = guess();
62  gsl_vector *x = NlsqTogsl(_fitParms);
63  gsl_matrix *covar = gsl_matrix_alloc(p, p);
64  gsl_multifit_fdfsolver_set(s, &mf, x);
65 
66  _nIters = 0;
67  checkIteration(_nIters, gslToNlsq(s->x), NLVector(p,999.0),
68  gsl_blas_dnrm2(s->f), GSL_CONTINUE);
69 
70 
71  gsl_matrix *J = gsl_matrix_alloc(n, p);
72  do {
73  _nIters++;
74 
75  _status = gsl_multifit_fdfsolver_iterate(s);
76  _fitParms = gslToNlsq(s->x);
77 
78  gsl_multifit_fdfsolver_jac(s, J);
79  gsl_multifit_covar(J, 0.0, covar);
80  _uncert = getUncertainty(covar);
81 
82  _status = checkIteration(_nIters, _fitParms, _uncert, gsl_blas_dnrm2(s->f),
83  _status);
84  if ( _status ) { break; }
85  if(!doContinue()) { break; }
86 
87  _status = gsl_multifit_test_delta(s->dx, s->x, absErr(), relErr());
88  } while ((_status == GSL_CONTINUE) && (_nIters < _maxIters));
89 
90  // Clean up
91  gsl_multifit_fdfsolver_free(s);
92  gsl_matrix_free(covar);
93  gsl_matrix_free(J);
94 
95  return (_status);
96 }
97 
98 
99 void NonLinearLSQ::Terminate(const std::string &message) {
100  _userMessage = message;
101  _userTerminated = true;
102  _status = GSL_SUCCESS;
103  return;
104 }
105 
106 void NonLinearLSQ::Abort(const std::string &reason) {
107  _userMessage = reason;
108  _userTerminated = true;
109  _status = GSL_FAILURE;
110  return;
111 }
112 
113 
114 int NonLinearLSQ::f(const gsl_vector *x, void *params, gsl_vector *fx) {
115  NonLinearLSQ *nlsq = (static_cast<_nlsqPointer *> (params))->nlsq;
116  int n = nlsq->nSize();
117  NLVector fxv = nlsq->f_x(nlsq->gslToNlsq(x));
118  for (int i = 0 ; i < n ; i++ ) {
119  gsl_vector_set(fx, i, fxv[i]);
120  }
121  return (GSL_SUCCESS);
122 }
123 
124 int NonLinearLSQ::df(const gsl_vector *x, void *params, gsl_matrix *J) {
125  NonLinearLSQ *nlsq = (static_cast<_nlsqPointer *> (params))->nlsq;
126  int n = nlsq->nSize();
127  int p = nlsq->nParms();
128 
129  NLMatrix m = nlsq->df_x(nlsq->gslToNlsq(x));
130 
131  for (int i = 0 ; i < n ; i++ ) {
132  for (int j = 0 ; j < p ; j++ ) {
133  gsl_matrix_set(J, i, j, m[i][j]);
134  }
135  }
136  return (GSL_SUCCESS);
137 }
138 
139 int NonLinearLSQ::fdf(const gsl_vector *x, void *params, gsl_vector *fx,
140  gsl_matrix *J) {
141  f(x,params,fx);
142  df(x,params,J);
143  return (GSL_SUCCESS);
144 }
145 
146 
147 NonLinearLSQ::NLVector NonLinearLSQ::getUncertainty(const gsl_matrix *covar)
148  const {
149  NLVector unc(covar->size1);
150  for (size_t i = 0 ; i < covar->size1 ; i++ ) {
151  unc[i] = sqrt(gsl_matrix_get(covar, i, i));
152  }
153  return (unc);
154 }
155 
156 NonLinearLSQ::NLVector NonLinearLSQ::gslToNlsq(const gsl_vector *v) const {
157  size_t n = v->size;
158  NLVector Nv(n);
159  for (size_t i = 0 ; i < n ; i++) {
160  Nv[i] = gsl_vector_get(v, i);
161  }
162  return (Nv);
163 }
164 
165 NonLinearLSQ::NLMatrix NonLinearLSQ::gslToNlsq(const gsl_matrix *m) const {
166  size_t nrows = m->size1;
167  size_t ncols = m->size2;
168  NLMatrix Nm(nrows, ncols);
169  for (size_t i = 0 ; i < nrows ; i++) {
170  for (size_t j = 0 ; j < ncols ; j++) {
171  Nm[i][j] = gsl_matrix_get(m,i,j);
172  }
173  }
174  return (Nm);
175 }
176 
177 gsl_vector *NonLinearLSQ::NlsqTogsl(const NonLinearLSQ::NLVector &v,
178  gsl_vector *gv) const {
179  if (gv == 0) {
180  gv = gsl_vector_alloc(v.dim());
181  }
182  else if (gv->size != (size_t) v.dim()) {
183  ostringstream mess;
184  mess << "Size of NL vector (" << v.dim() << ") not same as GSL vector ("
185  << gv->size << ")";
186  throw IException(IException::Programmer, mess.str(), _FILEINFO_);
187  }
188 
189  for (int i = 0 ; i < v.dim() ; i++) {
190  gsl_vector_set(gv, i, v[i]);
191  }
192  return (gv);
193 }
194 
195 gsl_matrix *NonLinearLSQ::NlsqTogsl(const NonLinearLSQ::NLMatrix &m,
196  gsl_matrix *gm) const {
197  if (gm == 0) {
198  gm = gsl_matrix_alloc(m.dim1(), m.dim2());
199  }
200  else if ((gm->size1 != (size_t) m.dim1()) &&
201  (gm->size2 != (size_t) m.dim2()) ) {
202  ostringstream mess;
203  mess << "Size of NL matrix (" << m.dim1() << "," << m.dim2()
204  << ") not same as GSL matrix (" << gm->size1 << "," << gm->size2
205  << ")";
206  throw IException(IException::Programmer, mess.str(), _FILEINFO_);
207  }
208 
209  for (int i = 0 ; i < m.dim1() ; i++) {
210  for (int j = 0 ; j < m.dim2() ; j++) {
211  gsl_matrix_set(gm, i, j, m[i][j]);
212  }
213  }
214  return (gm);
215 }
216 
217 } // namespace ISIS
Namespace for the standard library.
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31