nmrrelaxfit.cpp
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13 ***************************************************************************/
14 #include "nmrrelax.h"
15 #include "nmrrelaxfit.h"
16 #include "rand.h"
17 
18 
19 #include <gsl/gsl_multifit_nlin.h>
20 
21 typedef int (exp_f) (const gsl_vector * X, void * PARAMS, gsl_vector * F);
22 typedef int (exp_df) (const gsl_vector * X, void * PARAMS, gsl_matrix * J);
23 typedef int (exp_fdf) (const gsl_vector * X, void * PARAMS, gsl_vector * F, gsl_matrix * J);
24 
25 static int
26 do_nlls(int n, int p, double *param, double *err, double *det, void *user, exp_f *ef, exp_df *edf, exp_fdf *efdf
27  , int itercnt);
28 
29 #include <gsl/gsl_blas.h>
30 #include <gsl/gsl_ieee_utils.h>
31 
32 //---------------------------------------------------------------------------
33 
34 class XRelaxFuncPoly : public XRelaxFunc {
35 public:
36 //! define a term in a relaxation function
37 //! a*exp(-p*t/T1)
38  struct Term {
39  int p;
40  double a;
41  };
42 
43  XRelaxFuncPoly(const char *name, bool runtime, const Term *terms)
44  : XRelaxFunc(name, runtime), m_terms(terms) {
45  }
46  virtual ~XRelaxFuncPoly() {}
47 
48  //! called during fitting
49  //! \param f f(t, it1) will be passed
50  //! \param dfdt df/d(it1) will be passed
51  //! \param t a time P1 or 2tau
52  //! \param it1 1/T1 or 1/T2
53  virtual void relax(double *f, double *dfdt, double t, double it1) {
54  double rf = 0, rdf = 0;
55  double x = -t * it1;
56  x = std::min(5.0, x);
57  for(const Term *term = m_terms; term->p != 0; term++) {
58  double a = term->a * exp(x*term->p);
59  rf += a;
60  rdf += a * term->p;
61  }
62  rdf *= -t;
63  *f = 1.0 - rf;
64  *dfdt = -rdf;
65  }
66 private:
67  const struct Term *m_terms;
68 };
69 //! Power exponential.
70 class XRelaxFuncPowExp : public XRelaxFunc {
71 public:
72  XRelaxFuncPowExp(const char *name, bool runtime, double pow)
73  : XRelaxFunc(name, runtime), m_pow(pow) {}
74  virtual ~XRelaxFuncPowExp() {}
75 
76  //! called during fitting
77  //! \param f f(t, it1) will be passed
78  //! \param dfdt df/d(it1) will be passed
79  //! \param t a time P1 or 2tau
80  //! \param it1 1/T1 or 1/T2
81  virtual void relax(double *f, double *dfdt, double t, double it1) {
82  it1 = std::max(0.0, it1);
83  double rt = pow(t * it1, m_pow);
84  double a = exp(-rt);
85  *f = 1.0 - a;
86  *dfdt = t*rt/(t*it1)*m_pow * a;
87  }
88 private:
89  const double m_pow;
90 };
91 
92 //NQR I=1
93 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr2[] = {
94  {3, 1.0}, {0, 0}
95 };
96 //NQR I=3/2
97 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr3[] = {
98  {3, 1.0}, {0, 0}
99 };
100 //NQR I=5/2, 5/2
101 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr5_5[] = {
102  {3, 3.0/7}, {10, 4.0/7}, {0, 0}
103 };
104 //NQR I=5/2, 3/2
105 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr5_3[] = {
106  {3, 3.0/28}, {10, 25.0/28}, {0, 0}
107 };
108 //NQR I=3, 3
109 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr6_6[] = {
110  {21,0.05303}, {10,0.64935}, {3,0.29762}, {0, 0}
111 };
112 //NQR I=3, 2
113 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr6_4[] = {
114  {21,0.47727}, {10,0.41558}, {3,0.10714}, {0, 0}
115 };
116 //NQR I=3, 1
117 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr6_2[] = {
118  {21,0.88384}, {10,0.10823}, {3,0.0079365}, {0, 0}
119 };
120 //NQR I=7/2, 7/2
121 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr7_7[] = {
122  {3, 3.0/14}, {10, 50.0/77}, {21, 3.0/22}, {0, 0}
123 };
124 //NQR I=7/2, 5/2
125 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr7_5[] = {
126  {3, 2.0/21}, {10, 25.0/154}, {21, 49.0/66}, {0, 0}
127 };
128 //NQR I=7/2, 3/2
129 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr7_3[] = {
130  {3, 1.0/42}, {10, 18.0/77}, {21, 49.0/66}, {0, 0}
131 };
132 //NQR I=9/2, 9/2
133 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr9_9[] = {
134  {3, 4.0/33}, {10, 80.0/143}, {21, 49.0/165}, {36, 16.0/715}, {0, 0}
135 };
136 //NQR I=9/2, 7/2
137 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr9_7[] = {
138  {3, 9.0/132}, {10, 5.0/572}, {21, 441.0/660}, {36, 729.0/2860}, {0, 0}
139 };
140 //NQR I=9/2, 5/2
141 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr9_5[] = {
142  {3, 1.0/33}, {10, 20.0/143}, {21, 4.0/165}, {36, 576.0/715}, {0, 0}
143 };
144 //NQR I=9/2, 3/2
145 static const struct XRelaxFuncPoly::Term s_relaxdata_nqr9_3[] = {
146  {3, 1.0/132}, {10, 45.0/572}, {21, 49.0/165}, {36, 441.0/715}, {0, 0}
147 };
148 //NMR I=1/2
149 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr1[] = {
150  {1, 1}, {0, 0}
151 };
152 //NMR I=1
153 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr2[] = {
154  {3,0.75}, {1,0.25}, {0, 0}
155 };
156 //NMR I=3/2 center
157 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr3ca[] = {
158  {1, 0.1}, {6, 0.9}, {0, 0}
159 };
160 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr3cb[] = {
161  {1, 0.4}, {6, 0.6}, {0, 0}
162 };
163 //NMR I=3/2 satellite
164 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr3s[] = {
165  {1, 0.1}, {3, 0.5}, {6, 0.4}, {0, 0}
166 };
167 //NMR I=5/2 center
168 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr5ca[] = {
169  {1, 0.02857}, {6, 0.17778}, {15, 0.793667}, {0, 0}
170 };
171 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr5cb[] = {
172  {1, 0.25714}, {6, 0.266667}, {15, 0.4762}, {0, 0}
173 };
174 //NMR I=5/2 satellite
175 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr5s[] = {
176  {1, 0.028571}, {3, 0.05357}, {6, 0.0249987}, {10, 0.4464187}, {15, 0.4463875}, {0, 0}
177 };
178 //NMR I=5/2 satellite 3/2-5/2
179 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr5s2[] = {
180  {1, 0.028571}, {3, 0.2143}, {6, 0.3996}, {10, 0.2857}, {15, 0.0714}, {0, 0}
181 };
182 //NMR I=3 1--1
183 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr6c[] = {
184  {21,0.66288}, {15,0.14881}, {10,0.081169}, {6,0.083333}, {3,0.0059524}, {1,0.017857}, {0,0}
185 };
186 //NMR I=3 2-1
187 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr6s1[] = {
188  {21,0.23864}, {15,0.48214}, {10,0.20779}, {3,0.053571}, {1,0.017857}, {0,0}
189 };
190 //NMR I=3 3-2
191 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr6s2[] = {
192  {21,0.026515}, {15,0.14881}, {10,0.32468}, {6,0.33333}, {3,0.14881}, {1,0.017857}, {0,0}
193 };
194 //NMR I=7/2 center
195 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr7c[] = {
196  {1, 0.0119}, {6, 0.06818}, {15, 0.20605}, {28, 0.7137375}, {0, 0}
197 };
198 //NMR I=7/2 satellite 3/2-1/2
199 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr7s1[] = {
200  {1, 0.01191}, {3, 0.05952}, {6, 0.030305}, {10, 0.17532}, {15, 0.000915}, {21, 0.26513}, {28, 0.45678}, {0, 0}
201 };
202 //NMR I=7/2 satellite 5/2-3/2
203 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr7s2[] = {
204  {28,0.11422}, {21,0.37121}, {15,0.3663}, {10,0.081169}, {6,0.0075758}, {3,0.047619}, {1,0.011905} , {0, 0}
205 };
206 //NMR I=7/2 satellite 7/2-5/2
207 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr7s3[] = {
208  {28,0.009324}, {21,0.068182}, {15,0.20604}, {10,0.32468}, {6,0.27273}, {3,0.10714}, {1,0.011905}, {0, 0}
209 };
210 //NMR I=9/2 center
211 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr9c[] = {
212  {45,0.65306}, {28,0.215}, {15,0.092308}, {6,0.033566}, {1,0.0060606}, {0, 0}
213 };
214 //NMR I=9/2 satellite 3/2-1/2
215 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr9s1[] = {
216  {45,0.45352}, {36,0.30839}, {28,0.0033594}, {21,0.14848}, {15,0.016026}, {10,0.039336}, {6,0.021037}, {3,0.0037879}, {1,0.0060606}, {0, 0}
217 };
218 //NMR I=9/2 satellite 5/2-3/2
219 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr9s2[] = {
220  {45,0.14809}, {36,0.4028}, {28,0.28082}, {21,0.012121}, {15,0.064103}, {10,0.06993}, {6,0.0009324}, {3,0.015152}, {1,0.0060606}, {0, 0}
221 };
222 //NMR I=9/2 satellite 7/2-5/2
223 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr9s3[] = {
224  {45,0.020825}, {36,0.12745}, {28,0.30318}, {21,0.33409}, {15,0.14423}, {10,0.0043706}, {6,0.025699}, {3,0.034091}, {1,0.0060606}, {0, 0}
225 };
226 //NMR I=9/2 satellite 9/2-7/2
227 static const struct XRelaxFuncPoly::Term s_relaxdata_nmr9s4[] = {
228  {45,0.0010284}, {36,0.011189}, {28,0.05375}, {21,0.14848}, {15,0.25641}, {10,0.27972}, {6,0.18275}, {3,0.060606}, {1,0.0060606}, {0, 0}
229 };
230 
231 XRelaxFuncList::XRelaxFuncList(const char *name, bool runtime)
232  : XAliasListNode<XRelaxFunc>(name, runtime) {
233  create<XRelaxFuncPoly>("NMR I=1/2", true, s_relaxdata_nmr1);
234  create<XRelaxFuncPoly>("NMR I=1", true, s_relaxdata_nmr2);
235  create<XRelaxFuncPoly>("NMR I=3/2 center a", true, s_relaxdata_nmr3ca);
236  create<XRelaxFuncPoly>("NMR I=3/2 center b", true, s_relaxdata_nmr3cb);
237  create<XRelaxFuncPoly>("NMR I=3/2 satellite", true, s_relaxdata_nmr3s);
238  create<XRelaxFuncPoly>("NMR I=5/2 center a", true, s_relaxdata_nmr5ca);
239  create<XRelaxFuncPoly>("NMR I=5/2 center b", true, s_relaxdata_nmr5cb);
240  create<XRelaxFuncPoly>("NMR I=5/2 satellite 3/2-1/2", true, s_relaxdata_nmr5s);
241  create<XRelaxFuncPoly>("NMR I=5/2 satellite 5/2-3/2", true, s_relaxdata_nmr5s2);
242  create<XRelaxFuncPoly>("NMR I=3 1-0", true, s_relaxdata_nmr6c);
243  create<XRelaxFuncPoly>("NMR I=3 2-1", true, s_relaxdata_nmr6s1);
244  create<XRelaxFuncPoly>("NMR I=3 3-2", true, s_relaxdata_nmr6s2);
245  create<XRelaxFuncPoly>("NMR I=7/2 center", true, s_relaxdata_nmr7c);
246  create<XRelaxFuncPoly>("NMR I=7/2 satellite 3/2-1/2", true, s_relaxdata_nmr7s1);
247  create<XRelaxFuncPoly>("NMR I=7/2 satellite 5/2-3/2", true, s_relaxdata_nmr7s2);
248  create<XRelaxFuncPoly>("NMR I=7/2 satellite 7/2-5/2", true, s_relaxdata_nmr7s3);
249  create<XRelaxFuncPoly>("NMR I=9/2 center", true, s_relaxdata_nmr9c);
250  create<XRelaxFuncPoly>("NMR I=9/2 satellite 3/2-1/2", true, s_relaxdata_nmr9s1);
251  create<XRelaxFuncPoly>("NMR I=9/2 satellite 5/2-3/2", true, s_relaxdata_nmr9s2);
252  create<XRelaxFuncPoly>("NMR I=9/2 satellite 7/2-5/2", true, s_relaxdata_nmr9s3);
253  create<XRelaxFuncPoly>("NMR I=9/2 satellite 9/2-7/2", true, s_relaxdata_nmr9s4);
254  create<XRelaxFuncPoly>("NQR I=1", true, s_relaxdata_nqr2);
255  create<XRelaxFuncPoly>("NQR I=3/2", true, s_relaxdata_nqr3);
256  create<XRelaxFuncPoly>("NQR I=5/2 5/2-3/2", true, s_relaxdata_nqr5_5);
257  create<XRelaxFuncPoly>("NQR I=5/2 3/2-1/2", true, s_relaxdata_nqr5_3);
258  create<XRelaxFuncPoly>("NQR I=3 3-2", true, s_relaxdata_nqr6_6);
259  create<XRelaxFuncPoly>("NQR I=3 2-1", true, s_relaxdata_nqr6_4);
260  create<XRelaxFuncPoly>("NQR I=3 1-0", true, s_relaxdata_nqr6_2);
261  create<XRelaxFuncPoly>("NQR I=7/2 7/2-5/2", true, s_relaxdata_nqr7_7);
262  create<XRelaxFuncPoly>("NQR I=7/2 5/2-3/2", true, s_relaxdata_nqr7_5);
263  create<XRelaxFuncPoly>("NQR I=7/2 3/2-2/1", true, s_relaxdata_nqr7_3);
264  create<XRelaxFuncPoly>("NQR I=9/2 9/2-7/2", true, s_relaxdata_nqr9_9);
265  create<XRelaxFuncPoly>("NQR I=9/2 7/2-5/2", true, s_relaxdata_nqr9_7);
266  create<XRelaxFuncPoly>("NQR I=9/2 5/2-3/2", true, s_relaxdata_nqr9_5);
267  create<XRelaxFuncPoly>("NQR I=9/2 3/2-2/1", true, s_relaxdata_nqr9_3);
268  create<XRelaxFuncPowExp>("Pow.Exp.0.5: exp(-t^0.5)", true, 0.5);
269  create<XRelaxFuncPowExp>("Pow.Exp.0.6: exp(-t^0.6)", true, 0.6);
270  create<XRelaxFuncPowExp>("Pow.Exp.0.7: exp(-t^0.7)", true, 0.7);
271  create<XRelaxFuncPowExp>("Pow.Exp.0.8: exp(-t^0.8)", true, 0.7);
272  create<XRelaxFuncPowExp>("Gaussian: exp(-t^2)", true, 2.0);
273  create<XRelaxFuncPowExp>("Exp.: exp(-t)", true, 1.0);
274 }
275 
276 int
277 XRelaxFunc::relax_f (const gsl_vector * x, void *params,
278  gsl_vector * f) {
279  XNMRT1::NLLS *data = ((XNMRT1::NLLS *)params);
280  double iT1 = gsl_vector_get (x, 0);
281  double c = gsl_vector_get (x, 1);
282 
283  double a;
284  if(data->is_minftyfit)
285  a = gsl_vector_get (x, 2);
286  else
287  a = data->fixed_minfty - c;
288 
289  int i = 0;
290  for(auto it = data->pts->begin(); it != data->pts->end(); it++) {
291  if(it->isigma == 0) continue;
292  double t = it->p1;
293  double yi = 0, dydt = 0;
294  data->func->relax(&yi, &dydt, t, iT1);
295  double y = it->var;
296  gsl_vector_set (f, i, (c * yi + a - y) * it->isigma);
297  i++;
298  }
299  return GSL_SUCCESS;
300 }
301 int
302 XRelaxFunc::relax_df (const gsl_vector * x, void *params,
303  gsl_matrix * J) {
304 
305  XNMRT1::NLLS *data = ((XNMRT1::NLLS *)params);
306  double iT1 = gsl_vector_get (x, 0);
307  double c = gsl_vector_get (x, 1);
308 
309  int i = 0;
310  for(auto it = data->pts->begin();
311  it != data->pts->end(); it++) {
312  if(it->isigma == 0) continue;
313  double t = it->p1;
314  double yi = 0, dydt = 0;
315  data->func->relax(&yi, &dydt, t, iT1);
316  gsl_matrix_set (J, i, 0, (c * dydt) * it->isigma);
317  gsl_matrix_set (J, i, 1, yi * it->isigma);
318  if(data->is_minftyfit)
319  gsl_matrix_set (J, i, 2, it->isigma);
320  i++;
321  }
322  return GSL_SUCCESS;
323 }
324 int
325 XRelaxFunc::relax_fdf (const gsl_vector * x, void *params,
326  gsl_vector * f, gsl_matrix * J) {
327  XNMRT1::NLLS *data = ((XNMRT1::NLLS *)params);
328  double iT1 = gsl_vector_get (x, 0);
329 
330  double c = gsl_vector_get (x, 1);
331  double a;
332  if(data->is_minftyfit)
333  a = gsl_vector_get (x, 2);
334  else
335  a = data->fixed_minfty - c;
336 
337  int i = 0;
338  for(auto it = data->pts->begin();
339  it != data->pts->end(); it++) {
340  if(it->isigma == 0) continue;
341  double t = it->p1;
342  double yi = 0, dydt = 0;
343  data->func->relax(&yi, &dydt, t, iT1);
344  double y = it->var;
345  gsl_vector_set (f, i, (c * yi + a - y) * it->isigma);
346  gsl_matrix_set (J, i, 0, (c * dydt) * it->isigma);
347  gsl_matrix_set (J, i, 1, yi * it->isigma);
348  if(data->is_minftyfit)
349  gsl_matrix_set (J, i, 2, it->isigma);
350  i++;
351  }
352  return GSL_SUCCESS;
353 }
354 XString
355 XNMRT1::iterate(Transaction &tr, shared_ptr<XRelaxFunc> &func, int itercnt) {
356  const Snapshot &shot_this(tr);
357  //# of samples.
358  int n = 0;
359  double max_var = -1e90, min_var = 1e90;
360  for(auto it = shot_this[ *this].m_sumpts.begin(); it != shot_this[ *this].m_sumpts.end(); it++) {
361  if(it->isigma > 0) n++;
362  max_var = std::max(max_var, it->var);
363  min_var = std::min(min_var, it->var);
364  }
365  struct NLLS nlls = {
366  &tr[ *this].m_sumpts,
367  func,
368  shot_this[ *mInftyFit()],
369  0.0, //m_params[1] + m_params[2],
370  };
371  //# of indep. params.
372  int p = nlls.is_minftyfit ? 3 : 2;
373  if(n <= p) return formatString("%d",n) + i18n(" points, more points needed.");
374  int status;
375  double norm = 0;
376  XTime firsttime = XTime::now();
377  for(;;) {
378  status = do_nlls(n, p, tr[ *this].m_params, tr[ *this].m_errors, &norm,
379  &nlls, &XRelaxFunc::relax_f, &XRelaxFunc::relax_df, &XRelaxFunc::relax_fdf, itercnt);
380  if( !status && (fabs(tr[ *this].m_params[1]) < (max_var - min_var) * 10))
381  break;
382  if(XTime::now() - firsttime < 0.02) continue;
383  if(XTime::now() - firsttime > 0.07) break;
384  double p1max = shot_this[ *p1Max()];
385  double p1min = shot_this[ *p1Min()];
386  tr[ *this].m_params[0] = 1.0 / exp(log(p1max/p1min) * randMT19937() + log(p1min));
387  tr[ *this].m_params[1] = (max_var - min_var) * (randMT19937() * 2.0 + 0.9) * ((randMT19937() < 0.5) ? 1 : -1);
388  tr[ *this].m_params[2] = 0.0;
389  status = do_nlls(n, p, tr[ *this].m_params, tr[ *this].m_errors, &norm,
390  &nlls, &XRelaxFunc::relax_f, &XRelaxFunc::relax_df, &XRelaxFunc::relax_fdf, itercnt);
391  }
392  tr[ *this].m_errors[0] *= norm / sqrt((double)n);
393  tr[ *this].m_errors[1] *= norm / sqrt((double)n);
394  tr[ *this].m_errors[2] *= norm / sqrt((double)n);
395 
396  if( !nlls.is_minftyfit)
397  tr[ *this].m_params[2] = nlls.fixed_minfty - tr[ *this].m_params[1];
398 
399  double t1 = 0.001 / shot_this[ *this].m_params[0];
400  double t1err = 0.001 / pow(shot_this[ *this].m_params[0], 2.0) * shot_this[ *this].m_errors[0];
401  XString buf = "";
402  switch(shot_this[ *mode()]) {
403  case MEAS_ST_E:
404  case MEAS_T1:
405  buf += formatString("1/T1[1/s] = %.5g +- %.3g(%.2f%%)\n",
406  1000.0 * shot_this[ *this].m_params[0],
407  1000.0 * shot_this[ *this].m_errors[0],
408  fabs(100.0 * shot_this[ *this].m_errors[0]/shot_this[ *this].m_params[0]));
409  buf += formatString("T1[s] = %.5g +- %.3g(%.2f%%)\n",
410  t1, t1err, fabs(100.0 * t1err/t1));
411  break;
412  case MEAS_T2:
413  buf += formatString("1/T2[1/ms] = %.5g +- %.3g(%.2f%%)\n",
414  1000.0 * shot_this[ *this].m_params[0],
415  1000.0 * shot_this[ *this].m_errors[0],
416  fabs(100.0 * shot_this[ *this].m_errors[0]/shot_this[ *this].m_params[0]));
417  buf += formatString("T2[ms] = %.5g +- %.3g(%.2f%%)\n",
418  t1, t1err, fabs(100.0 * t1err/t1));
419  break;
420  }
421  buf += formatString("c[V] = %.5g +- %.3g(%.3f%%)\n",
422  shot_this[ *this].m_params[1], shot_this[ *this].m_errors[1],
423  fabs(100.0 * shot_this[ *this].m_errors[1]/shot_this[ *this].m_params[1]));
424  buf += formatString("a[V] = %.5g +- %.3g(%.3f%%)\n",
425  shot_this[ *this].m_params[2], shot_this[ *this].m_errors[2],
426  fabs(100.0 * shot_this[ *this].m_errors[2]/shot_this[ *this].m_params[2]));
427  buf += formatString("status = %s\n", gsl_strerror (status));
428  buf += formatString("rms of residuals = %.3g\n", norm / sqrt((double)n));
429  buf += formatString("elapsed time = %.2f ms\n", 1000.0 * (XTime::now() - firsttime));
430  return buf;
431 }
432 
433 int
434 do_nlls(int n, int p, double *param, double *err, double *det, void *user, exp_f *ef, exp_df *edf, exp_fdf *efdf
435  , int itercnt) {
436  const gsl_multifit_fdfsolver_type *T;
437  T = gsl_multifit_fdfsolver_lmsder;
438  gsl_multifit_fdfsolver *s;
439  int iter = 0;
440  int status;
441  int i;
442  double c;
443  gsl_multifit_function_fdf f;
444 
445  gsl_ieee_env_setup ();
446 
447  f.f = ef;
448  f.df = edf;
449  f.fdf = efdf;
450  f.n = n;
451  f.p = p;
452  f.params = user;
453  s = gsl_multifit_fdfsolver_alloc (T, n, p);
454  gsl_vector_view x = gsl_vector_view_array (param, p);
455  gsl_multifit_fdfsolver_set (s, &f, &x.vector);
456 
457 
458  do {
459  iter++;
460  status = gsl_multifit_fdfsolver_iterate (s);
461 
462  if (status)
463  break;
464 
465  status = gsl_multifit_test_delta (s->dx, s->x,
466  1e-4, 1e-4);
467  }
468  while (status == GSL_CONTINUE && iter < itercnt);
469 
470  if(det) *det = gsl_blas_dnrm2 (s->f);
471  for(i = 0; i < p; i++)
472  param[i] = gsl_vector_get (s->x, i);
473 
474  gsl_matrix *covar = gsl_matrix_alloc (p, p);
475  gsl_multifit_covar (s->J, 0.0, covar);
476  for(i = 0; i < p; i++) {
477  c = gsl_matrix_get(covar,i,i);
478 
479  err[i] = (c > 0) ? sqrt(c) : -1.0;
480  }
481  gsl_matrix_free(covar);
482  gsl_multifit_fdfsolver_free (s);
483 
484  return status;
485 }
486 

Generated for KAME4 by  doxygen 1.8.3