00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00018 #include "yanera.h"
00019 #include "yanera_mdmin.h"
00020 #include "yanera_quadrature.h"
00021 #include "yanera_reflectivity.h"
00022 #include "yanera_util.h"
00023
00024 int yanera_mdmin_main(yanera_container *yanera)
00025 {
00026 int i, count;
00027 int status;
00028 gsl_vector *guess;
00029 gsl_multimin_function_fdf mdmin_func;
00030 gsl_multimin_fdfminimizer *solvr;
00031
00032
00033 guess = gsl_vector_alloc(yanera->parameters.n);
00034 for (i=0; i<yanera->parameters.n; i++)
00035 {
00036 gsl_vector_set(guess, i, yanera->parameters.p[i]);
00037 }
00038
00039 mdmin_func.f = &mdmin_f;
00040 mdmin_func.df = &mdmin_df;
00041 mdmin_func.fdf = &mdmin_fdf;
00042 mdmin_func.n = yanera->parameters.n;
00043 mdmin_func.params = (void *)yanera;
00044
00045 solvr = gsl_multimin_fdfminimizer_alloc( \
00046 yanera->misc.fit_method_mdmin, yanera->parameters.n);
00047
00048
00049 count = 0;
00050 if ((yanera->misc.fit_method == STEEP_DESC) ||
00051 (yanera->misc.fit_method == VECTOR_BFGS))
00052 gsl_multimin_fdfminimizer_set(solvr, &mdmin_func, guess, 1.1, 1E-2);
00053 else
00054 gsl_multimin_fdfminimizer_set(solvr, &mdmin_func, guess, 1.1, 1e-4);
00055 yanera_report(yanera, count, solvr);
00056
00057 do
00058 {
00059 count++;
00060
00061 status = gsl_multimin_fdfminimizer_iterate(solvr);
00062 if (status != GSL_SUCCESS)
00063 {
00064 fprintf(stderr,"STATUS: %s\n", gsl_strerror(status));
00065 break;
00066 }
00067
00068 yanera_report(yanera, count, solvr);
00069
00070 status = gsl_multimin_test_gradient(solvr->gradient, 1e-6);
00071
00072 if (status == GSL_SUCCESS)
00073 {
00074 fprintf(stderr,"STATUS: %s\n", gsl_strerror(status));
00075 }
00076
00077 } while ((status == GSL_CONTINUE) && (count < yanera->misc.fit_iterations));
00078
00079 yanera_report(yanera, -1, solvr);
00080
00081 gsl_multimin_fdfminimizer_free(solvr);
00082 gsl_vector_free(guess);
00083
00084 return GSL_SUCCESS;
00085 }
00086
00087 void mdmin_fdf(const gsl_vector *parameters, \
00088 void *yanera_pointer, \
00089 double *f, gsl_vector *df)
00090 {
00091 *f = mdmin_f(parameters, yanera_pointer);
00092 mdmin_df(parameters, yanera_pointer, df);
00093 return;
00094 }
00095
00096 double mdmin_f(const gsl_vector *parameters, \
00097 void *yanera_pointer)
00098 {
00099 int i;
00100 double tmp;
00101 yanera_container *yanera;
00102
00103
00104
00105 yanera = (yanera_container *)yanera_pointer;
00106
00107
00108
00109 for(i=0; i<yanera->parameters.n; i++)
00110 {
00111 yanera->parameters.p[i] = gsl_vector_get(parameters, i);
00112 }
00113
00114 tmp = mdmin_chisq(yanera);
00115
00116 return tmp;
00117 }
00118
00119 void mdmin_df(const gsl_vector *parameters, \
00120 void *yanera_pointer, \
00121 gsl_vector *df)
00122 {
00123 int i;
00124 double res, err;
00125 gsl_function F;
00126 yanera_container *yanera;
00127
00128
00129
00130 yanera = (yanera_container *)yanera_pointer;
00131
00132
00133
00134 for(i=0; i<yanera->parameters.n; i++)
00135 {
00136 yanera->parameters.tmp[i] = gsl_vector_get(parameters, i);
00137 }
00138
00139
00140
00141 F.function = &mdmin_derivatives;
00142 F.params = yanera_pointer;
00143
00144
00145
00146
00147
00148
00149 for (i=0; i<yanera->parameters.n; i++)
00150 {
00151 yanera->parameters.idx = i;
00152 if (yanera->parameters.f[i] == YES) res=0.0;
00153 else gsl_deriv_central(&F, yanera->parameters.tmp[i], 1e-6, &res, &err);
00154 gsl_vector_set(df, i, res);
00155 }
00156
00157 return;
00158 }
00159
00160 double mdmin_derivatives(double new_p, void *yanera_pointer)
00161 {
00162 int i;
00163 double tmp;
00164 yanera_container *yanera;
00165
00166
00167
00168 yanera = (yanera_container *)yanera_pointer;
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 for(i=0; i<yanera->parameters.n; i++)
00179 {
00180 yanera->parameters.p[i] = yanera->parameters.tmp[i];
00181 }
00182 yanera->parameters.p[yanera->parameters.idx] = new_p;
00183
00184 tmp = mdmin_chisq(yanera);
00185
00186 return tmp;
00187 }
00188
00189 double mdmin_chisq(yanera_container *yanera)
00190 {
00191 int i, j;
00192 double tmp;
00193 double residual;
00194 int numdata;
00195
00196
00197
00198
00199 residual = 0.0;
00200 numdata = 0;
00201 for (j=0; j<yanera->number_of_models; j++)
00202 {
00203
00204
00205
00206 if ((yanera->type == MODEL_COMPONENT) || \
00207 (yanera->type == MODEL_SLAB) || \
00208 (yanera->type == MODEL_FUNCTION))
00209 { doQuadrature(&yanera->models_complete[yanera->idx], yanera); }
00210
00211
00212
00213 for (i=0; i<yanera->data[j].n; i++)
00214 {
00215 tmp = calcReflectivity(yanera->data[j].q[i], \
00216 &yanera->data[j].resolution, \
00217 &yanera->models_complete[j], \
00218 yanera);
00219 tmp = (tmp - yanera->data[j].R[i]) / yanera->data[j].e[i];
00220 residual += tmp * tmp;
00221 numdata++;
00222 }
00223
00224
00225
00226 }
00227
00228 tmp = residual / (double)(numdata - yanera->parameters.n);
00229 return tmp;
00230 }
00231