yanera_mdmin.c

Go to the documentation of this file.
00001 /*============================================================================
00002 Copyright 2006 Thad Harroun, Kevin Yager
00003 
00004 This file is part of "yanera 2.0".
00005 
00006 "yanera 2.0" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
00007 
00008 "yanera 2.0" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00009 
00010 You should have received a copy of the GNU General Public License along with "yanera 2.0"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 
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   /* Inital guess is the paramters as they were passed into here */
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   ** r =>> residual
00104   */
00105   yanera = (yanera_container *)yanera_pointer;
00106   /*
00107   **  Load the params back into the parameter array.
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   **  Load the params into the temporary parameter array.
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   **  d(chisq)/d(p_i)
00145   **  => i is the parameter index
00146   ** If the parameter is to be held fixed, then
00147   ** set the derivative to zero.
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   ** p =>> varying parameter for derivative
00167   */
00168   yanera = (yanera_container  *)yanera_pointer; 
00169   /*
00170    *  We need move the parameters from 'tmp', back into 'p'
00171    *  with the derivative parameter 'new_p' 
00172    *  replacing the parameter at index 'y->parameters.idx'.
00173    *
00174    *  model and data index  = yanera->idx;
00175    *  parameter index       = yanera->parameters.idx;
00176    *  data point index      = yanera->data[yanera->idx].idx;
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   ** Loop over the data sets with index k.
00198   */
00199   residual = 0.0;
00200   numdata  = 0;
00201   for (j=0; j<yanera->number_of_models; j++)
00202   {
00203     /*
00204     ** Redo quadrature for this moel
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     ** Loop over the data points
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 

Generated on Thu May 29 10:56:33 2008 by  doxygen 1.5.5