yanera_lstsq.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_lstsq.h"
00020 #include "yanera_quadrature.h"
00021 #include "yanera_reflectivity.h"
00022 #include "yanera_util.h"
00023 /*===========================================================================*/
00024 int yanera_lstsq_main(yanera_container *yanera)
00025 {
00026   unsigned int                        i;
00027   int                                 count, stop1, stop2;
00028   gsl_vector                         *guess;
00029   gsl_vector                         *gradt;
00030   gsl_matrix                         *covar;
00031   gsl_multifit_function_fdf           lstsq_func;
00032   gsl_multifit_fdfsolver             *solvr;
00033   
00034   /* Inital guess is the paramters as they were passed into here */
00035   guess = gsl_vector_alloc(yanera->parameters.n);
00036   for (i=0; i<yanera->parameters.n; i++) 
00037   {
00038     gsl_vector_set(guess, i, yanera->parameters.p[i]);
00039   }
00040 
00041   /* count the number of data points */
00042   count = 0;
00043   for (i=0; i<yanera->number_of_models; i++)
00044   {
00045     count += yanera->data[i].n;
00046   }
00047 
00048   /* need this vector for stop test #2 */
00049   gradt = gsl_vector_alloc(yanera->parameters.n);
00050   
00051   /* covariant matrix  */
00052   covar = gsl_matrix_alloc(yanera->parameters.n, yanera->parameters.n);
00053 
00054   lstsq_func.f      = &lstsq_f;
00055   lstsq_func.df     = &lstsq_df;
00056   lstsq_func.fdf    = &lstsq_fdf;
00057   lstsq_func.n      = count;                /* number of data points */
00058   lstsq_func.p      = yanera->parameters.n; /* number of paramters   */
00059   lstsq_func.params = (void *)yanera; /* pass the full yanera_container */
00060   
00061   solvr = gsl_multifit_fdfsolver_alloc(\
00062           yanera->misc.fit_method_lstsq, lstsq_func.n, lstsq_func.p);
00063 
00064   /*==================================================*/
00065   count = 0;
00066   gsl_multifit_fdfsolver_set(solvr, &lstsq_func, guess);
00067   /*gsl_multifit_covar(solvr->J, 0.0, covar);*/
00068   yanera_report(yanera, count, solvr);
00069 
00070   do
00071   { 
00072     count++;
00073     
00074     stop1 = gsl_multifit_fdfsolver_iterate(solvr);    
00075     /*gsl_multifit_covar(solvr->J, 0.0, covar);*/
00076     yanera_report(yanera, count, solvr);
00077     
00078     if (stop1) 
00079     {
00080       fprintf(stderr,"STATUS: %s\n", gsl_strerror(stop1));
00081       break;
00082     }
00083     
00084     /* Stop test #1 */
00085     stop1 = gsl_multifit_test_delta(solvr->dx, solvr->x, 1e-6, 1e-6);
00086 
00087     /* Stop test #2 */    
00088     gsl_multifit_gradient(solvr->J, solvr->f, gradt);
00089     stop2 = gsl_multifit_test_gradient(gradt, 1e-6);
00090     
00091     if ((stop1==GSL_SUCCESS) && (stop2==GSL_SUCCESS))
00092     {
00093       fprintf(stderr,"STATUS: %s\n", gsl_strerror(stop1));
00094     }
00095 
00096   } while (((stop1 == GSL_CONTINUE) || (stop2 == GSL_CONTINUE)) \
00097             && (count < yanera->misc.fit_iterations));
00098 
00099   /*==================================================*/
00100   /*gsl_multifit_covar(solvr->J, 0.0, covar);*/
00101   yanera_report(yanera, -1, solvr);
00102   
00103   /*==================================================*/
00104 
00105   gsl_multifit_fdfsolver_free(solvr);
00106   gsl_matrix_free(covar);
00107   gsl_vector_free(guess);
00108   gsl_vector_free(gradt);
00109 
00110   return GSL_SUCCESS;
00111 }
00112 /*===================================================================
00113  *    lstsq_fdf 
00114  */
00115 int lstsq_fdf(const gsl_vector *parameters, \
00116               void *yanera_pointer, \
00117               gsl_vector *r, gsl_matrix *J)
00118 {
00119   lstsq_f (parameters, yanera_pointer, r);
00120   lstsq_df(parameters, yanera_pointer, J);
00121   return GSL_SUCCESS;
00122 }
00123 /*===================================================================
00124  *    lstsq_f 
00125  */
00126 int lstsq_f(const gsl_vector *parameters, \
00127             void *yanera_pointer, \
00128             gsl_vector *r)
00129 {
00130   int                i, j;
00131   int                r_index;
00132   double             tmp;
00133   yanera_container  *yanera;
00134   /*
00135   ** r =>> residual
00136   */
00137   yanera = (yanera_container *)yanera_pointer;
00138   /*
00139   **  Load the params back into the parameter array.
00140   */
00141   for(i=0; i<yanera->parameters.n; i++)
00142   {
00143     yanera->parameters.p[i] = gsl_vector_get(parameters, i);
00144   }
00145   /*
00146   ** Loop over the data sets and models
00147   */
00148   r_index = 0;
00149   for (j=0; j<yanera->number_of_models; j++)
00150   {
00151     /*
00152     ** Redo quadrature for this moel
00153     */
00154     if ((yanera->type == MODEL_COMPONENT) ||
00155         (yanera->type == MODEL_SLAB) ||
00156         (yanera->type == MODEL_FUNCTION))
00157     { doQuadrature(&yanera->models_complete[j], yanera); }
00158     /*
00159     ** Loop over the data points
00160     */ 
00161     for (i=0; i<yanera->data[j].n; i++)
00162     {
00163       tmp = calcReflectivity(yanera->data[j].q[i], \
00164                              &yanera->data[j].resolution, \
00165                              &yanera->models_complete[j], \
00166                              yanera);
00167       tmp = (tmp - yanera->data[j].R[i]) / yanera->data[j].e[i];
00168       gsl_vector_set(r, r_index, tmp);
00169       r_index++; 
00170     }
00171     /*
00172     ** 
00173     */
00174   }
00175   
00176   return GSL_SUCCESS;
00177 }
00178 /*===================================================================
00179  *    lstsq_df 
00180  */
00181 int lstsq_df(const gsl_vector *parameters, \
00182              void *yanera_pointer, \
00183              gsl_matrix *J)
00184 {
00185   int                i, j, k;
00186   int                r_index;
00187   double             res, err;
00188   gsl_function       F;
00189   yanera_container  *yanera;
00190   /*
00191   **
00192   */
00193   yanera = (yanera_container *)yanera_pointer;
00194   /*
00195   **  Load the params into the temporary parameter array.
00196   */
00197   for(i=0; i<yanera->parameters.n; i++)
00198   {
00199     yanera->parameters.tmp[i] = gsl_vector_get(parameters, i);
00200   }
00201   /*
00202    *
00203    */
00204   F.function = &lstsq_derivatives;
00205   F.params   = yanera_pointer;
00206   /*
00207   ** Loop over the data sets
00208   */
00209   r_index = 0;
00210   for (k=0; k<yanera->number_of_models; k++)
00211   {
00212     /*
00213     **  The jacobian mtirx J_ij = d(r_i)/d(a_j)
00214     **  => i is the data index of residual r
00215     **  => j is the parameter index
00216     */
00217     yanera->idx = k;
00218     /*
00219     ** Loop over the data points
00220     */
00221     for (i=0; i<yanera->data[k].n; i++)
00222     {
00223       yanera->data[k].idx = i;
00224       /*
00225       ** Loop over the parameters 
00226       */
00227       for (j=0; j<yanera->parameters.n; j++) 
00228       {
00229         yanera->parameters.idx = j;
00230         /*
00231         ** If fixed, J_ij = 0
00232         */
00233         if (yanera->parameters.f[j] == YES) res=0.0;
00234         else gsl_deriv_central(&F, yanera->parameters.tmp[j], 1e-5, &res, &err);
00235         gsl_matrix_set(J, r_index, j, res);
00236       }
00237       r_index++; 
00238     }
00239     /*
00240     **
00241     */
00242   }
00243     
00244   return GSL_SUCCESS;
00245 }
00246 /*===================================================================
00247  *    lstsq_derivatives 
00248  */
00249 double lstsq_derivatives(double new_p, void *yanera_pointer)
00250 {
00251   int                i;
00252   double             tmp;
00253   yanera_container  *yanera;
00254   /*
00255   ** p =>> varying parameter for derivative
00256   */
00257   yanera = (yanera_container  *)yanera_pointer; 
00258   /*
00259    *  We need move the parameters from 'tmp', back into 'p'
00260    *  with the derivative parameter 'new_p' 
00261    *  replacing the parameter at index 'y->parameters.idx'.
00262    *
00263    *  model and data index  = yanera->idx;
00264    *  parameter index       = yanera->parameters.idx;
00265    *  data point index      = yanera->data[yanera->idx].idx;
00266    */
00267   for(i=0; i<yanera->parameters.n; i++) 
00268   {
00269     yanera->parameters.p[i] = yanera->parameters.tmp[i];
00270   }
00271   yanera->parameters.p[yanera->parameters.idx] = new_p;
00272   if ((yanera->type == MODEL_COMPONENT) ||
00273       (yanera->type == MODEL_SLAB) ||
00274       (yanera->type == MODEL_FUNCTION))
00275   { doQuadrature(&yanera->models_complete[yanera->idx], yanera); }
00276   
00277   tmp = 0.0;
00278   i = yanera->data[yanera->idx].idx;
00279   tmp = calcReflectivity(yanera->data[yanera->idx].q[i], \
00280                          &yanera->data[yanera->idx].resolution, \
00281                          &yanera->models_complete[yanera->idx], \
00282                           yanera);
00283   tmp = (tmp - yanera->data[yanera->idx].R[i]) /  \
00284                yanera->data[yanera->idx].e[i];
00285   return tmp;
00286 }
00287 

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