int magcal_proc(gsl_vector *m, const satdata_mag *data, magcal_workspace *w) { int s; gsl_multifit_function_fdf f; gsl_multifit_fdfsolver *fdf_s; magcal_params params; gsl_vector_view v; const double xtol = 1e-10; const double gtol = 1e-10; const double ftol = 0.0; int info; /* copy data arrays */ s = magcal_init(data, w); if (s) return s; /* scale parameters to dimensionless units */ magcal_scale(1, m, w); params.w = w; f.f = &magcal_f; f.df = &magcal_df; f.n = w->n; f.p = w->p; f.params = ¶ms; v = gsl_vector_subvector(m, MAGCAL_IDX_DT, w->p); gsl_multifit_fdfsolver_set (w->fdf_s, &f, &v.vector); gsl_multifit_fdfridge_set (w->fdf_ridge, &f, &v.vector, w->lambda); #if 0 s = gsl_multifit_fdfsolver_driver(w->fdf_s, 500, xtol, gtol, ftol, &info); fdf_s = w->fdf_s; #else s = gsl_multifit_fdfridge_driver(w->fdf_ridge, 500, xtol, gtol, ftol, &info); fdf_s = w->fdf_ridge->s; #endif if (s != GSL_SUCCESS) { fprintf(stderr, "magcal_proc: error computing parameters: %s\n", gsl_strerror(s)); } else { magcal_print_state (w, fdf_s); fprintf(stderr, "magcal_proc: total data processed: %zu\n", w->n); fprintf(stderr, "magcal_proc: number of iterations: %zu\n", fdf_s->niter); fprintf(stderr, "magcal_proc: function evaluations: %zu\n", fdf_s->fdf->nevalf); fprintf(stderr, "magcal_proc: jacobian evaluations: %zu\n", fdf_s->fdf->nevaldf); fprintf(stderr, "magcal_proc: reason for convergence: %d\n", info); /* save calibration parameters */ gsl_vector_memcpy(&v.vector, fdf_s->x); /* restore time shift parameter */ gsl_vector_set(m, MAGCAL_IDX_DT, 0.0); /* scale offsets back to nT */ magcal_scale(-1, m, w); #if 0 /* compute covariance matrix */ gsl_multifit_covar(fdf_s->J, 0.0, w->covar); #endif } return s; } /* magcal_proc() */
static void test_fdfridge(const gsl_multifit_fdfsolver_type * T, const double xtol, const double gtol, const double ftol, const double epsrel, const double x0_scale, test_fdf_problem *problem, const double *wts) { gsl_multifit_function_fdf *fdf = problem->fdf; const size_t n = fdf->n; const size_t p = fdf->p; const size_t max_iter = 1500; gsl_vector *x0 = gsl_vector_alloc(p); gsl_vector_view x0v = gsl_vector_view_array(problem->x0, p); gsl_multifit_fdfridge *w = gsl_multifit_fdfridge_alloc (T, n, p); const char *pname = problem->name; char sname[2048]; int status, info; double lambda = 0.0; sprintf(sname, "ridge/%s", gsl_multifit_fdfridge_name(w)); /* scale starting point x0 */ gsl_vector_memcpy(x0, &x0v.vector); test_scale_x0(x0, x0_scale); /* test undamped case with lambda = 0 */ if (wts) { gsl_vector_const_view wv = gsl_vector_const_view_array(wts, n); gsl_multifit_fdfridge_wset(w, fdf, x0, lambda, &wv.vector); } else gsl_multifit_fdfridge_set(w, fdf, x0, lambda); status = gsl_multifit_fdfridge_driver(w, max_iter, xtol, gtol, ftol, &info); gsl_test(status, "%s/%s did not converge, status=%s", sname, pname, gsl_strerror(status)); /* check solution */ test_fdf_checksol(sname, pname, epsrel, w->s, problem); /* test for self consisent solution with L = \lambda I */ { const double eps = 1.0e-10; gsl_matrix *L = gsl_matrix_calloc(p, p); gsl_vector_view diag = gsl_matrix_diagonal(L); gsl_multifit_fdfridge *w2 = gsl_multifit_fdfridge_alloc (T, n, p); gsl_vector *y0 = gsl_vector_alloc(p); size_t i; /* pick some value for lambda and set L = \lambda I */ lambda = 5.0; gsl_vector_set_all(&diag.vector, lambda); /* scale initial vector */ gsl_vector_memcpy(x0, &x0v.vector); test_scale_x0(x0, x0_scale); gsl_vector_memcpy(y0, x0); if (wts) { gsl_vector_const_view wv = gsl_vector_const_view_array(wts, n); gsl_multifit_fdfridge_wset(w, fdf, x0, lambda, &wv.vector); gsl_multifit_fdfridge_wset3(w2, fdf, y0, L, &wv.vector); } else { gsl_multifit_fdfridge_set(w, fdf, x0, lambda); gsl_multifit_fdfridge_set3(w2, fdf, y0, L); } /* solve with scalar lambda routine */ status = gsl_multifit_fdfridge_driver(w, max_iter, xtol, gtol, ftol, &info); gsl_test(status, "%s/lambda/%s did not converge, status=%s", sname, pname, gsl_strerror(status)); /* solve with general matrix routine */ status = gsl_multifit_fdfridge_driver(w2, max_iter, xtol, gtol, ftol, &info); gsl_test(status, "%s/L/%s did not converge, status=%s", sname, pname, gsl_strerror(status)); /* test x = y */ for (i = 0; i < p; ++i) { double xi = gsl_vector_get(w->s->x, i); double yi = gsl_vector_get(w2->s->x, i); if (fabs(xi) < eps) { gsl_test_abs(yi, xi, eps, "%s/%s ridge lambda=%g i="F_ZU, sname, pname, lambda, i); } else { gsl_test_rel(yi, xi, eps, "%s/%s ridge lambda=%g i="F_ZU, sname, pname, lambda, i); } } gsl_matrix_free(L); gsl_vector_free(y0); gsl_multifit_fdfridge_free(w2); } gsl_multifit_fdfridge_free(w); gsl_vector_free(x0); }