1 #include <omp.h> 2 /* 3 * File: fit.c 4 * This is a general non-linear fitting program. It's used to a an 5 * optimal set of coefficients for the r_over _i ratio. 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <math.h> 11 #include <sys/time.h> 12 #include "myrandom.h" 13 14 15 //#define _DOPRINT_ // #define NTRAJ 2500 //#define POINT 51 16 17 #define NTRAJ 750 18 #define E_MIN 0.05 19 #define POINT 51 20 #define NPAR 4 21 #define ERRCRI 0.01 22 #define PI 3.14159265358979 23 24 unsigned int INITIAL_SEED = 123; 25 26 /*---------------*/ 27 /* function 'rmse'. 28 * This function calculates the RMS error for the inputting 29 * bat and ba 30 * 'bat' is the back scattering coefficient of our own MC simulation 31 * 'ba' is the full quantum MC simulation and is used as experiment 32 * to which we are fitting to 33 */ 34 double rmse(double bat[], double ba[]); 35 36 /* function: rmse */ 37 double rmse(double bat[], double ba[]) 38 { 39 double rms; 40 int i; 41 42 rms=0.0; 43 for(i=0;i<POINT;i++) 44 { 45 rms += (bat[i]-ba[i])*(bat[i]-ba[i])/bat[i]/(1.0-bat[i]); 46 } 47 48 return (rms); 49 } 50 51 52 /*---------------*/ 53 /* private function 'back'. 54 * This function simulates the backscattering coefficient for the 55 * given element and energy 56 * array point stores the energy and element information in the 57 * sequence E,Z,A,rho (energy, atomic#, atomic weight, density) 58 * array coef is the array of the parameters (the parameters we are 59 * adjusting to make a good fit) 60 * backsc is the address of the output back scattering coefficient 61 */ 62 63 64 /* Function: backsc */ 65 double back(double point[], double coef[]) 66 { 67 int i,j,k,jj; 68 int icic,iback; 69 double eng; 70 double engo,sigma,lamda,alpha,r_over_i; 71 double ran1,ran2,ran3,ran4,step,zcor,cz,sz,de,c_phi,s_phi,psi,cc; 72 int filtr,filtf; 73 double base=(double)2147483647; 74 75 /*-----------------------*/ 76 /* Here is the section for setting up the some initial values for 77 * calculating sigma, alpha..., so that these values won't need to be 78 * recalculated for each trajectory. This section need modification if 79 * wemodify the formulas of alpha, r_over_i.. 80 */ 81 double p1=coef[0],p2=coef[1],p3=coef[2],p4=coef[3]; 82 double engt=point[0],zz=point[1],aa=point[2],rho=point[3]; 83 double z133=pow(zz,1.33),z165=pow(zz,1.65),zex=(1.0-zz/1000.0); 84 double lamda_a = aa/6.022e23/rho; 85 double j_j=0.001*(9.76*zz+58.5/pow(zz,0.19)); 86 double j_a=1.166/j_j; 87 double p_sa = -78500.0*rho*zz/aa; 88 /*-----------------------*/ 89 90 /*printf("p1,p2,p3,p4,p5,p6 %e %e %e %e %e %e\n",p1,p2,p3,p4,p5,p6); 91 printf("z133,z15 %e %e\n",z133,z15); 92 printf("lamda_a,j_j,j_a,p_sa, %e %e %e %e\n",lamda_a,j_j,j_a,p_sa); 93 */ 94 95 long int result; 96 97 srand_mr(INITIAL_SEED); 98 99 /*---------------------------------------------------------------- 100 * 101 * Now, we begin to calculate the back-scattering coefficient for 102 * this set of coefficient 103 */ 104 105 /* now, the loop for all NTRAJ trajectories */ 106 iback=0; // accumulator... 107 for(jj=0;jj<NTRAJ;jj++) 108 { 109 eng=engt; 110 111 engo = (eng+511.0)/(eng+1024.0); 112 sigma = p4*4.0e-18*z165*engo*engo/ 113 (eng+p3*1.0e-2*z133*pow(eng,0.5)); 114 lamda = lamda_a/sigma; 115 alpha = 7.0e-3/eng; 116 /*printf("engo,sigma,lamda,alpha %e %e %e %e \n", 117 engo,sigma,lamda,alpha); 118 */ 119 120 result = rand_mr(); 121 ran1=result/base; 122 step = -lamda*log(ran1); 123 /*printf("ran1,step %e %e\n",ran1,step); 124 */ 125 126 zcor=step; 127 cz=1; 128 129 de=step*p_sa*log(j_a*eng+1.0)/eng; 130 eng=eng+de; 131 /*printf("de,eng %e %e\n",de,eng); 132 */ 133 134 /*-------------------------------- 135 * now the loop for tracing the trajectory until it backscattered 136 * or it has energy too small to backscatter 137 */ 138 filtf=zcor>0 && eng>E_MIN && eng>(-de*zcor/step); 139 icic=filtf; 140 /* printf("\n"); 141 printf("icic,zcor,eng,de,step %d %e %e %e %e\n", 142 icic,zcor,eng,de,step); 143 */ 144 while(icic) 145 { 146 147 r_over_i=p1*100.0*pow(eng,zex)/zz+zz*zz*zz/eng/p2/1.0e5; 148 149 engo=(eng+511)/(eng+1024); 150 sigma = p4*4.0e-18*z165*engo*engo/ 151 (eng+p3*1.0e-2*z133*pow(eng,0.5)); 152 lamda= lamda_a/sigma; 153 alpha=7.0e-3/eng; 154 155 result = rand_mr(); 156 ran1=result/base; 157 result = rand_mr(); 158 ran2=result/base; 159 result = rand_mr(); 160 ran3=result/base; 161 result = rand_mr(); 162 ran4=result/base; 163 filtr=ran4<r_over_i/(r_over_i+1.0); 164 165 step = -lamda*log(ran1); 166 c_phi=filtr*(-2*alpha*ran2/(alpha-ran2+1)+1)+(1-filtr)*(1-2*ran2); 167 s_phi=sqrt(1.0-c_phi*c_phi); 168 psi=2*PI*ran3; 169 sz=sqrt(1.0-cz*cz); 170 cc = -s_phi*cos(psi)*sz+c_phi*cz; 171 172 zcor=zcor+step*cc; 173 de=step*p_sa*log(j_a*eng+1.0)/eng; 174 eng=eng+de; 175 cz=cc; 176 177 filtf=zcor>0 && eng>E_MIN && eng>(-de*zcor/step); 178 icic=filtf; 179 180 } /* end of the tracing process for this trajectory */ 181 182 if(zcor<0) iback++; 183 184 } /* end of the NTRAJ trajectories */ 185 186 #ifdef _DOPRINT_ 187 printf("point: engt %f, zz %f, A %f, rho %f\n",engt,zz,aa,rho); 188 printf("backscattering coeff for this point is %f \n",*backsc); 189 #endif 190 return (double)iback/(double)NTRAJ; 191 192 } /* end of back subroutine */ 193 /**************************************************************/ 194 195 196 /**********************************************************************/ 197 198 /**********************************************************************/ 199 /**********************************************************************/ 200 /********************** main function ***********************/ 201 /********************** ***********************/ 202 203 main(int argc, char ** argv) 204 { 205 int i,j,k,m; 206 int ii,jj,icic,icic2,icc; 207 double coe[NPAR]; 208 const char *fitfile, *montefile, *paramfile; 209 FILE *fpot, *fcoe, *fbac; 210 double point[POINT][4]; 211 double backsct[POINT],baexp[POINT],ajunk,bjunk; 212 double pointt[4],coet[NPAR],backcoe; 213 double rms,oldrms; 214 215 /* ---------------------------------------------------------- 216 * Read in the elements that need to be considered and the energy that 217 * need to be calculated for the back-scattering coefficient 218 */ 219 220 if (argc < 4) { 221 fprintf(stderr, "Not all files specified.\n Correct command line: %s fit.inp monte.dat param.dat\n", argv[0]); 222 exit(1); 223 } 224 225 fitfile = argv[1]; 226 montefile = argv[2]; 227 paramfile = argv[3]; 228 229 230 if ((fpot=fopen(fitfile,"r")) == NULL) 231 { 232 printf ("Error in opening %s\n", fitfile); 233 exit(1); 234 } 235 236 if ((fcoe=fopen(paramfile,"r")) == NULL) 237 { 238 printf ("Error in opening %s\n", paramfile); 239 exit(1); 240 } 241 242 if ((fbac=fopen(montefile,"r")) == NULL) 243 { 244 printf ("Error in opening %s\n", montefile); 245 exit(1); 246 } 247 /*-----------------------------------------------*/ 248 249 /*-----------------------------------------------*/ 250 /* Now, read in the data */ 251 252 for(i=0;i<POINT;i++) 253 { 254 for(j=0;j<4;j++) fscanf(fpot,"%lf",&point[i][j]); 255 for(j=0;j<4;j++) printf("%e ",point[i][j]); 256 printf("\n"); 257 } 258 printf("\n"); 259 260 for(i=0;i<NPAR;i++) 261 { 262 fscanf(fcoe,"%lf",&coe[i]); 263 printf("%e \n",coe[i]); 264 } 265 printf("\n"); 266 267 for(i=0;i<POINT;i++) 268 { 269 fscanf(fbac,"%lf%lf%lf",&ajunk,&bjunk,&baexp[i]); 270 printf("%e %e %e\n",ajunk,bjunk,baexp[i]); 271 } 272 printf("\n\n"); 273 fflush(stdout); 274 275 fclose(fpot); 276 fclose(fcoe); 277 fclose(fbac); 278 279 /****************************************************/ 280 /*----------------------- 281 * now calculate the POINT points of backscattering coefficients 282 */ 283 284 printf("first plot\n"); 285 printf("parameter set: \n"); 286 for(i=0;i<NPAR;i++) printf(" %e ",coe[i]); 287 printf("\n\n"); 288 fflush(stdout); 289 290 for(i=0;i<NPAR;i++) coet[i]=coe[i]; 291 292 #pragma omp parallel for private (i, pointt, backcoe) schedule(dynamic) 293 for(ii=0;ii<POINT;ii++) 294 { 295 for(i=0;i<4;i++) pointt[i]=point[ii][i]; 296 backcoe = back(pointt,coet); 297 backsct[ii]=backcoe; 298 fflush(stdout); 299 } 300 301 rms=rmse(backsct,baexp); 302 oldrms=rms; 303 icic=oldrms>ERRCRI; 304 printf("icic %d, rms %f \n\n",icic,oldrms); 305 fflush(stdout); 306 307 /*---------------------------------*/ 308 /* Now we begin the loop for automated fitting */ 309 310 while(icic) 311 { 312 313 /*----------------------------------------------------*/ 314 icc=0; 315 316 for(jj=0;jj<NPAR;jj++) 317 { 318 printf("Changing # %d \n\n",jj); 319 fflush(stdout); 320 321 for(i=0;i<NPAR;i++) coet[i]=coe[i]; 322 coet[jj]=coe[jj]*1.2; 323 324 #pragma omp parallel for private (i, pointt, backcoe) schedule(dynamic) 325 for(ii=0;ii<POINT;ii++) 326 { 327 for(i=0;i<4;i++) pointt[i]=point[ii][i]; 328 backcoe = back(pointt,coet); 329 backsct[ii]=backcoe; 330 fflush(stdout); 331 } 332 333 rms=rmse(backsct,baexp); 334 icic2=rms<oldrms; 335 336 if(icic2) 337 while(icic2) 338 { 339 icc=1; 340 oldrms=rms; 341 for(i=0;i<NPAR;i++) coe[i]=coet[i]; 342 printf("new parameter set: \n"); 343 for(i=0;i<NPAR;i++) printf(" %e ",coe[i]); 344 printf("\n"); 345 printf("corresponding rms: %f \n\n",oldrms); 346 fflush(stdout); 347 348 printf("increasing # %d \n",jj); 349 fflush(stdout); 350 351 for(i=0;i<NPAR;i++) coet[i]=coe[i]; 352 coet[jj]=coe[jj]*1.2; 353 354 #pragma omp parallel for private (i, pointt, backcoe) schedule(dynamic) 355 for(ii=0;ii<POINT;ii++) 356 { 357 for(i=0;i<4;i++) pointt[i]=point[ii][i]; 358 backcoe = back(pointt,coet); 359 backsct[ii]=backcoe; 360 fflush(stdout); 361 } 362 363 rms=rmse(backsct,baexp); 364 icic2=rms<oldrms; 365 } /* end of while and if */ 366 367 else 368 { 369 for(i=0;i<NPAR;i++) coet[i]=coe[i]; 370 coet[jj]=coe[jj]*0.8; 371 372 #pragma omp parallel for private (i, pointt, backcoe) schedule(dynamic) 373 for(ii=0;ii<POINT;ii++) 374 { 375 for(i=0;i<4;i++) pointt[i]=point[ii][i]; 376 backcoe = back(pointt,coet); 377 backsct[ii]=backcoe; 378 fflush(stdout); 379 } 380 381 rms=rmse(backsct,baexp); 382 icic2=rms<oldrms; 383 384 while(icic2) 385 { 386 icc=1; 387 oldrms=rms; 388 for(i=0;i<NPAR;i++) coe[i]=coet[i]; 389 printf("new parameter set: \n"); 390 for(i=0;i<NPAR;i++) printf(" %e ",coe[i]); 391 printf("\n"); 392 printf("corresponding rms: %f \n\n",oldrms); 393 fflush(stdout); 394 395 printf("decreasing # %d \n",jj); 396 fflush(stdout); 397 398 for(i=0;i<NPAR;i++) coet[i]=coe[i]; 399 coet[jj]=coe[jj]*0.8; 400 401 #pragma omp parallel for private (i, pointt, backcoe) schedule(dynamic) 402 for(ii=0;ii<POINT;ii++) 403 { 404 for(i=0;i<4;i++) pointt[i]=point[ii][i]; 405 backcoe = back(pointt,coet); 406 backsct[ii]=backcoe; 407 fflush(stdout); 408 } 409 410 rms=rmse(backsct,baexp); 411 icic2=rms<oldrms; 412 } /* end of while */ 413 } /* end of else */ 414 } /* end of for(jj=0... */ 415 416 icic=icc*(oldrms>ERRCRI); 417 418 } /* end of while(icic) */ 419 420 printf("\n\n***********************************************\n\n"); 421 printf("End of fitting process\n\n"); 422 printf("final parameter set: \n"); 423 for(i=0;i<NPAR;i++) printf(" %e ",coe[i]); 424 printf("\n\n Corresponding rmse: %f \n\n",oldrms); 425 printf("----------------------------------------\n\n"); 426 fflush(stdout); 427 428 }