static double my_f (const gsl_vector *v, void *params) { double val; my_fdf(v, params, &val, NULL); return val; }
void measurement_df(const gsl_vector *v, void *params, gsl_vector *df) { double f; my_fdf(v, params, &f, df); }
/* The gradient of f, df = (df/dx, df/dy). */ static void my_df (const gsl_vector *v, void *params, gsl_vector *df) { my_fdf(v, params, NULL, df); }
void minim(density_t * ndft){ const gsl_multimin_fdfminimizer_type *T; gsl_multimin_fdfminimizer *s; gsl_multimin_function_fdf my_func; gsl_vector * grad_initial; size_t iter; ipf_t ipf_previous; int status; double minimum, g_initial, norm_initial; char * output_string; int i; params_gsl_multimin_function_t params; output_string = (char *) malloc(25*sizeof(char)); params.nDFT = density_get_val(ndft); my_func.n = ipf.npar; my_func.f = my_f; my_func.df = my_df; my_func.fdf = my_fdf; my_func.params = (void *) (¶ms); /* We use the BFGS algorithm from thee GNU Scientific Library (GSL) in its optimized version bfgs2 */ T = gsl_multimin_fdfminimizer_vector_bfgs2; messages_basic("\n\nStarting the optimization.\n\n\n"); grad_initial = gsl_vector_alloc(ipf.npar); my_fdf (ipf.gamma, ¶ms, &g_initial, grad_initial); norm_initial = gsl_blas_dnrm2(grad_initial); if(g_initial < epsilon_gvalue){ if(myid == 0) printf("The value of G for the starting gamma is %.12lg,\n", g_initial); if(myid == 0) printf("which is already below the requested threshold of %.12lg\n", epsilon_gvalue); parallel_end(EXIT_SUCCESS); } if(norm_initial < epsilon_grad){ if(myid == 0) printf("The value of the normm of the gradient of G for the starting gamma is %.12lg,\n", norm_initial); if(myid == 0) printf("which is already below the requested threshold of %.12lg\n", epsilon_grad); parallel_end(EXIT_SUCCESS); } if(myid == 0) printf(" Starting from gamma = "); if(myid == 0) {for(i = 0; i < ipf.npar; i++) printf ("%.5f ", gsl_vector_get (ipf.gamma, i));} if(myid == 0) printf("\n G(gamma) = %.12lg\n", g_initial); if(myid == 0) printf(" ||Grad G(gamma)|| = %.12lg\n\n", norm_initial); /* Initialization of the minimizer s for the function my_func starting at the x point The step for the first try is 0.1 and the convergence criteria is 0.1 */ messages_basic("\n\nInitialization of the minimizer.\n\n\n"); s = gsl_multimin_fdfminimizer_alloc (T, ipf.npar); gsl_multimin_fdfminimizer_set (s, &my_func, ipf.gamma, 0.1, 0.1); minimum = g_initial; iter = 0; do{ iter++; ipf_copy(&ipf_previous, &ipf); if(myid == 0) printf(" Iter = %d\n", (int)iter); if(myid == 0) printf(" starting gamma = "); if(myid == 0) {for(i = 0; i < ipf.npar; i++) printf ("%.5f ", gsl_vector_get (gsl_multimin_fdfminimizer_x(s), i));} if(myid == 0) printf("\n starting G(gamma) = %15.10f\n", minimum); /* We make an iteration of the minimizer s */ status = gsl_multimin_fdfminimizer_iterate (s); minimum = gsl_multimin_fdfminimizer_minimum(s); if (status){ if(myid == 0) printf(" Breaking. Reason: %s\n", gsl_strerror(status)); break; } if(myid == 0) printf(" ||Grad G(gamma)|| = %15.10f\n", gsl_blas_dnrm2(gsl_multimin_fdfminimizer_gradient(s))); if(myid == 0) printf(" G(gamma) = %15.10f\n", minimum); /* Checks convergence */ if(minimum < epsilon_gvalue){ status = GSL_SUCCESS; }else{ status = gsl_multimin_test_gradient (gsl_multimin_fdfminimizer_gradient(s), epsilon_grad); } gsl_vector_memcpy(ipf.gamma, gsl_multimin_fdfminimizer_x(s)); ipf_write(ipf, ipf_ref, "intermediate-pot"); /* Print the diff between initial and reference IPFs */ if(myid == 0) printf(" Diff[ IPF(previous), IPF(new) ] = %.12lg\n", ipf_diff(&ipf_previous, &ipf)); ipf_end(&ipf_previous); } while (status == GSL_CONTINUE && iter < minim_maxiter); if(myid == 0) printf("\n\nFinished optimization. status = %d (%s)\n", status, gsl_strerror(status)); if(myid == 0) printf(" Final gamma = "); if(myid == 0) {for(i = 0; i < ipf.npar; i++) printf ("%.5f ", gsl_vector_get (gsl_multimin_fdfminimizer_x(s), i));} if(myid == 0) printf("\n With value: G(gamma) = %.12lg\n\n", gsl_multimin_fdfminimizer_minimum(s)); gsl_vector_memcpy(ipf.gamma, gsl_multimin_fdfminimizer_x(s)); sprintf(output_string, "pot"); ipf_write(ipf, ipf_ref, output_string); gsl_multimin_fdfminimizer_free (s); fflush(stdout); }