00001
00002
00003
00004 #include "cddefines.h"
00005 #include "init.h"
00006 #include "lines.h"
00007 #include "prt.h"
00008 #include "called.h"
00009 #include "radius.h"
00010 #include "input.h"
00011 #include "cloudy.h"
00012 #include "cddrive.h"
00013 #include "optimize.h"
00014 #include "grid.h"
00015
00016 STATIC double chi2_func(double,double,double);
00017
00018 double optimize_func(realnum param[])
00019 {
00020
00021 #define MAXCAT 4
00022
00023 char
00024 chFind[5];
00025
00026 bool lgBAD,
00027 lgHIT,
00028 lgLimOK;
00029
00030 long int cat,
00031 i,
00032 j,
00033 nfound,
00034 nobs_cat[MAXCAT],
00035 np;
00036
00037 static long int ipobs[NOBSLM];
00038
00039 double chi1,
00040 chi2_cat[MAXCAT],
00041 chisq,
00042 func_v,
00043 help,
00044 predin,
00045 scld,
00046 snorm,
00047 theocl,
00048 temp_theory;
00049
00050 static char name_cat[MAXCAT][13] =
00051 {
00052 "rel flux ",
00053 "column dens ",
00054 "abs flux ",
00055 "mean Temp "
00056 };
00057
00058 static bool lgLinSet = false;
00059
00060 DEBUG_ENTRY( "optimize_func()" );
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 zero();
00075
00076 if( optimize.lgOptimFlow )
00077 {
00078 fprintf( ioQQQ, " trace, optimize_func variables" );
00079 for( i=0; i < optimize.nvary; i++ )
00080 {
00081 fprintf( ioQQQ, "%.2e", param[i] );
00082 }
00083 fprintf( ioQQQ, "\n" );
00084 }
00085
00086 for( i=0; i < optimize.nvary; i++ )
00087 {
00088 optimize.vparm[0][i] = param[i];
00089 }
00090
00091
00092
00093 vary_input(&lgLimOK);
00094
00095 if( !lgLimOK )
00096 {
00097
00098
00099 fprintf( ioQQQ, " Iteration %ld not within range.\n",
00100 optimize.nOptimiz );
00101
00102
00103 func_v = (double)FLT_MAX;
00104
00105
00106
00107 ++optimize.nOptimiz;
00108 return( func_v );
00109 }
00110
00111 for( i=0; i < optimize.nvary; i++ )
00112 {
00113 optimize.varmax[i] = (realnum)MAX2(optimize.varmax[i],optimize.vpused[i]);
00114 optimize.varmin[i] = (realnum)MIN2(optimize.varmin[i],optimize.vpused[i]);
00115 }
00116
00117 lgBAD = cloudy();
00118 if( lgBAD )
00119 {
00120 fprintf( ioQQQ, " PROBLEM Cloudy returned error condition - what happened?\n" );
00121 }
00122
00123 if( grid.lgGrid )
00124 {
00125
00126 chisq = 0.;
00127 }
00128 else
00129 {
00130
00131
00132 chisq = 0.0;
00133 for( i=0; i < MAXCAT; i++ )
00134 {
00135 nobs_cat[i] = 0;
00136 chi2_cat[i] = 0.0;
00137 }
00138
00139 if( LineSave.ipNormWavL < 0 )
00140 {
00141 fprintf( ioQQQ,
00142 " Normalization line array index is bad. What has gone wrong?\n" );
00143 cdEXIT(EXIT_FAILURE);
00144 }
00145
00146 if( (snorm = LineSv[LineSave.ipNormWavL].sumlin[LineSave.lgLineEmergent]) == 0. )
00147 {
00148 fprintf( ioQQQ, "\n\n PROBLEM Normalization line has zero intensity. What has gone wrong?\n" );
00149 fprintf( ioQQQ, " Is spectrum normalized to a species that does not exist?\n" );
00150 cdEXIT(EXIT_FAILURE);
00151 }
00152
00153
00154 cdWarnings(ioQQQ);
00155
00156
00157 nfound = 0;
00158
00159
00160 if( optimize.lgOptLin )
00161 {
00162
00163 if( !lgLinSet )
00164 {
00165 lgHIT = true;
00166 lgLinSet = true;
00167 for( i=0; i < optimize.nlobs; i++ )
00168 {
00169 double temp1, temp2;
00170 cap4(chFind , (char*)optimize.chLineLabel[i]);
00171
00172
00173
00174
00175
00176 j=cdLine( chFind , optimize.wavelength[i] , &temp1, &temp2 );
00177 if( j<=0 )
00178 {
00179 fprintf( ioQQQ, "\n" );
00180 lgHIT = false;
00181 }
00182 else
00183 {
00184 ipobs[i] = j;
00185 }
00186 }
00187
00188
00189 if( !lgHIT )
00190 {
00191 fprintf( ioQQQ, "\n\n Optimizer could not find one or more lines.\n" );
00192 fprintf( ioQQQ, " Sorry.\n");
00193 cdEXIT(EXIT_FAILURE);
00194 }
00195 }
00196
00197 for( i=0; i < 10; i++ )
00198 {
00199 optimize.SavGenericData[i] = 0.;
00200 }
00201
00202 for( i=0; i < optimize.nlobs; i++ )
00203 {
00204
00205 nfound += 1;
00206 scld = (double)LineSv[ipobs[i]].sumlin[LineSave.lgLineEmergent]/(double)snorm*LineSave.ScaleNormLine;
00207 chi1 = chi2_func(scld,(double)optimize.xLineInt_Obs[i],(double)optimize.xLineInt_error[i]);
00208 cat = 0;
00209 nobs_cat[cat]++;
00210 chi2_cat[cat] += chi1;
00211
00212 fprintf( ioQQQ, " %4.4s ",
00213 LineSv[ipobs[i]].chALab);
00214
00215 prt_wl( ioQQQ,LineSv[ipobs[i]].wavelength);
00216
00217 fprintf( ioQQQ, "%12.5f%12.5f%12.5f%12.2e Relative intensity",
00218 scld,
00219 optimize.xLineInt_Obs[i],
00220 optimize.xLineInt_error[i],
00221 chi1 );
00222
00223 fprintf( ioQQQ, "\n" );
00224
00225 if( i<10 )
00226 {
00227 optimize.SavGenericData[i] = chi1;
00228 }
00229 }
00230 }
00231
00232
00233
00234
00235 if( optimize.lgOptimize )
00236 {
00237 fprintf( ioQQQ, " ID Model Observed error chi**2 Type\n" );
00238 }
00239 else
00240 {
00241 ASSERT( grid.lgGrid );
00242 }
00243
00244
00245 if( optimize.lgOptTemp )
00246 {
00247 for( i=0; i < optimize.nTempObs; i++ )
00248 {
00249 if( cdTemp(optimize.chTempLab[i],optimize.ionTemp[i], &temp_theory, optimize.chTempWeight[i]) )
00250 {
00251
00252 fprintf(ioQQQ," optimizer did not find column density %s %li \n",
00253 optimize.chTempLab[i],optimize.ionTemp[i] );
00254 cdEXIT(EXIT_FAILURE);
00255 }
00256 nfound += 1;
00257 chi1 = chi2_func(temp_theory,(double)optimize.temp_obs[i],(double)optimize.temp_error[i]);
00258 cat = 3;
00259 nobs_cat[cat]++;
00260 chi2_cat[cat] += chi1;
00261
00262 fprintf( ioQQQ, " %4.4s %2ld ",
00263 optimize.chTempLab[i],
00264 optimize.ionTemp[i] );
00265 PrintE82( ioQQQ, temp_theory );
00266 fprintf( ioQQQ, " ");
00267 PrintE82( ioQQQ, optimize.temp_obs[i] );
00268 fprintf( ioQQQ, " %.5f %.2e",
00269 optimize.temp_error[i], chi1 );
00270 fprintf( ioQQQ, " Temperature\n");
00271 }
00272 }
00273
00274
00275 if( optimize.lgOptCol )
00276 {
00277 for( i=0; i < optimize.ncobs; i++ )
00278 {
00279 if( cdColm((char*)optimize.chColDen_label[i],optimize.ion_ColDen[i], &theocl) )
00280 {
00281
00282 fprintf(ioQQQ," optimizer did not find column density %s %li \n",
00283 optimize.chColDen_label[i],optimize.ion_ColDen[i] );
00284 cdEXIT(EXIT_FAILURE);
00285 }
00286 nfound += 1;
00287 chi1 = chi2_func(theocl,(double)optimize.ColDen_Obs[i],(double)optimize.chColDen_error[i]);
00288 cat = 1;
00289 nobs_cat[cat]++;
00290 chi2_cat[cat] += chi1;
00291
00292 fprintf( ioQQQ, " %4.4s%6ld%12.4e%12.4e%12.5f%12.2e Column density\n",
00293 optimize.chColDen_label[i], optimize.ion_ColDen[i], theocl,
00294 optimize.ColDen_Obs[i], optimize.chColDen_error[i], chi1 );
00295 }
00296 }
00297
00298
00299 if( optimize.lgOptLum )
00300 {
00301 nfound += 1;
00302 if( LineSv[LineSave.ipNormWavL].sumlin[LineSave.lgLineEmergent] > 0.f )
00303 {
00304 predin = log10(LineSv[LineSave.ipNormWavL].sumlin[LineSave.lgLineEmergent]) + radius.Conv2PrtInten;
00305 help = pow(10.,predin-(double)optimize.optint);
00306 chi1 = chi2_func(help,1.,(double)optimize.optier);
00307 }
00308 else
00309 {
00310 predin = -999.99999;
00311 chi1 = (double)FLT_MAX;
00312 }
00313 cat = 2;
00314 nobs_cat[cat]++;
00315 chi2_cat[cat] += chi1;
00316
00317 fprintf( ioQQQ, " %4.4s%6f%12.5f%12.5f%12.5f%12.2e Line intensity\n",
00318 LineSv[LineSave.ipNormWavL].chALab,
00319 LineSv[LineSave.ipNormWavL].wavelength,
00320 predin,
00321 optimize.optint,
00322 optimize.optier,
00323 chi1 );
00324 }
00325
00326
00327 if( nfound <= 0 && !grid.lgGrid )
00328 {
00329 fprintf( ioQQQ, " WARNING; no line matches found\n" );
00330 cdEXIT(EXIT_FAILURE);
00331 }
00332
00333
00334 fprintf( ioQQQ, "\n" );
00335 for( i=0; i < MAXCAT; i++ )
00336 {
00337 if( nobs_cat[i] > 0 )
00338 {
00339 chisq += chi2_cat[i]/nobs_cat[i];
00340 fprintf( ioQQQ, " Category %s #obs.%3ld Total Chi**2%11.3e Average Chi**2%11.3e\n",
00341 name_cat[i],nobs_cat[i],chi2_cat[i],chi2_cat[i]/nobs_cat[i] );
00342 }
00343 }
00344 if( nfound )
00345 {
00346 fprintf( ioQQQ, "\n Iteration%4ld Chisq=%13.5e\n", optimize.nOptimiz, chisq );
00347 }
00348 }
00349
00350
00351 ++optimize.nOptimiz;
00352
00353
00354 if( called.lgTalk )
00355 {
00356 fprintf( ioQQQ, "\n" );
00357 for( i=0; i < optimize.nvary; i++ )
00358 {
00359 optimize.vparm[0][i] = (realnum)MIN2(optimize.vparm[0][i],optimize.varang[i][1]);
00360 optimize.vparm[0][i] = (realnum)MAX2(optimize.vparm[0][i],optimize.varang[i][0]);
00361 param[i] = optimize.vparm[0][i];
00362 np = optimize.nvfpnt[i];
00363
00364
00365
00366 if( optimize.nvarxt[i] == 1 )
00367 {
00368
00369 sprintf( input.chCardSav[np] , optimize.chVarFmt[i], optimize.vparm[0][i] );
00370 }
00371
00372 else if( optimize.nvarxt[i] == 2 )
00373 {
00374
00375 sprintf( input.chCardSav[np] , optimize.chVarFmt[i], optimize.vparm[0][i], optimize.vparm[1][i]);
00376 }
00377
00378 else if( optimize.nvarxt[i] == 3 )
00379 {
00380
00381 sprintf( input.chCardSav[np] , optimize.chVarFmt[i],
00382 optimize.vparm[0][i], optimize.vparm[1][i] , optimize.vparm[2][i] );
00383 }
00384
00385 else if( optimize.nvarxt[i] == 4 )
00386 {
00387
00388 sprintf( input.chCardSav[np] , optimize.chVarFmt[i],
00389 optimize.vparm[0][i], optimize.vparm[1][i] , optimize.vparm[2][i], optimize.vparm[3][i] );
00390 }
00391
00392 else if( optimize.nvarxt[i] == 5 )
00393 {
00394
00395 sprintf( input.chCardSav[np] , optimize.chVarFmt[i],
00396 optimize.vparm[0][i], optimize.vparm[1][i] , optimize.vparm[2][i],
00397 optimize.vparm[3][i] , optimize.vparm[4][i]);
00398 }
00399
00400 else
00401 {
00402 fprintf(ioQQQ,"The number of variable options on this line makes no sense to me4\n");
00403 cdEXIT(EXIT_FAILURE);
00404 }
00405
00406 fprintf( ioQQQ, " Varied command: %s\n",
00407 input.chCardSav[np] );
00408 }
00409 }
00410
00411 func_v = MIN2(chisq,(double)FLT_MAX);
00412 return( func_v );
00413 }
00414
00415
00416 STATIC double chi2_func(double ymodl,
00417 double ymeas,
00418 double yerr)
00419 {
00420 double chi2_func_v,
00421 temp;
00422
00423 DEBUG_ENTRY( "chi2_func()" );
00424
00425
00426
00427
00428
00429 if( ymeas <= 0. )
00430 {
00431 fprintf( ioQQQ, "chi2_func: non-positive observed quantity, this should not happen\n" );
00432 cdEXIT(EXIT_FAILURE);
00433 }
00434
00435 if( yerr > 0. )
00436 {
00437 if( ymodl > 0. )
00438 {
00439 temp = POW2((ymodl-ymeas)/(MIN2(ymodl,ymeas)*yerr));
00440 chi2_func_v = MIN2( temp , (double)FLT_MAX );
00441 }
00442 else
00443 chi2_func_v = (double)FLT_MAX;
00444 }
00445 else if( yerr < 0. )
00446 {
00447
00448
00449
00450 if( ymodl > ymeas )
00451 {
00452 temp = POW2((ymodl-ymeas)/(ymeas*yerr));
00453 chi2_func_v = MIN2(temp,(double)FLT_MAX);
00454 }
00455 else
00456 chi2_func_v = 0.;
00457 }
00458 else
00459 {
00460 fprintf( ioQQQ, "chi2_func: relative error is zero, this should not happen\n" );
00461 cdEXIT(EXIT_FAILURE);
00462 }
00463 return chi2_func_v;
00464 }