int InterpolaVPR_GSL::interpola_VPR(const float* vpr, int hvprmax, int livmin) { LOG_CATEGORY("radar.vpr"); static const unsigned N = 10; const gsl_multifit_fdfsolver_type *T; gsl_multifit_fdfsolver *s; int status; unsigned int i; const size_t n = N; const size_t p = 5; char file_vprint[512]; gsl_matrix *covar = gsl_matrix_alloc (p, p); double a[5]; struct data d(N); gsl_multifit_function_fdf f; double x_init[5] = { 4, 0.2, 3. , 1.4, -0.4 }; gsl_vector_view x = gsl_vector_view_array (x_init, p); ////////////////////////////////////////////////////////////////////////////// int ier_int=0; double xint,yint; /* punti interessanti per inizializzare parametri*/ int in1=(int)((hvprmax-TCK_VPR/2)/TCK_VPR); //indice del massimo int in2=(int)((hvprmax+HALF_BB)/TCK_VPR); //indice del massimo + 500 m int in3=in2+1; int in4=in2+5; //indice del massimo + 1000 m if (in4 > NMAXLAYER-1) { ier_int=1; return ier_int; } B=vpr[in1]-vpr[in2]; E=hvprmax/1000.; G=0.25; C=vpr[in2-1]; F=vpr[in4]<vpr[in3]?(vpr[in4]-vpr[in3])/((in4-in3)*TCK_VPR/1000.):0.; // fprintf(stderr, "const unsigned NMAXLAYER=%d;\n", NMAXLAYER); // fprintf(stderr, "float vpr[] = {"); // for (unsigned i = 0; i < NMAXLAYER; ++i) // fprintf(stderr, "%s%f", i==0?"":",", (double)vpr[i]); // fprintf(stderr, "};\n"); x_init[0]= a[0]=B; x_init[1]= a[1]=E; x_init[2]= a[2]=G; x_init[3]= a[3]=C; x_init[4]= a[4]=F; ///////////////////////////////////////////////////////////////////////////////////////////////////////// f.f = &expb_f; f.df = &expb_df; f.fdf = &expb_fdf; f.n = n; f.p = p; f.params = &d; /* This is the data to be fitted */ for (i = 0; i < n; i++) { d.t[i]= ((hvprmax-1000.)>livmin)? (i*TCK_VPR+(hvprmax-800)-TCK_VPR)/1000. : (livmin+i*TCK_VPR)/1000.; d.y[i]= ((hvprmax-1000.)>livmin)? vpr[i+(int)(((hvprmax-800)-TCK_VPR)/TCK_VPR)] : vpr[i+(int)(livmin/TCK_VPR)]; d.sigma[i] = 0.5; }; T = gsl_multifit_fdfsolver_lmsder; s = gsl_multifit_fdfsolver_alloc (T, n, p); gsl_multifit_fdfsolver_set (s, &f, &x.vector); //print_state (0, s); bool found = false; for (unsigned iter = 0; !found && iter < 500; ++iter) { //fprintf(stderr, "Iter %d\n", iter); //d.print(); int status = gsl_multifit_fdfsolver_iterate (s); if (status != 0) { LOG_ERROR("gsl_multifit_fdfsolver_iterate: %s", gsl_strerror(status)); return 1; } //print_state (iter, s); status = gsl_multifit_test_delta (s->dx, s->x, 1e-4, 1e-4); switch (status) { case GSL_SUCCESS: found = true; break; case GSL_CONTINUE: break; default: LOG_ERROR("gsl_multifit_test_delta: %s", gsl_strerror(status)); return 1; } } #if GSL_MAJOR_VERSION == 2 // Use of GSL 2.0 taken from https://sft.its.cern.ch/jira/browse/ROOT-7776 gsl_matrix* J = gsl_matrix_alloc(s->fdf->n, s->fdf->p); gsl_multifit_fdfsolver_jac(s, J); gsl_multifit_covar(J, 0.0, covar); #else gsl_multifit_covar(s->J, 0.0, covar); #endif #define FIT(i) gsl_vector_get(s->x, i) #define ERR(i) sqrt(gsl_matrix_get(covar,i,i)) { double chi = gsl_blas_dnrm2(s->f); double dof = n - p; double c = GSL_MAX_DBL(1, chi / sqrt(dof)); // printf("chisq/dof = %g\n", pow(chi, 2.0) / dof); // printf ("B = %.5f +/- %.5f\n", FIT(0), c*ERR(0)); // printf ("E = %.5f +/- %.5f\n", FIT(1), c*ERR(1)); // printf ("G = %.5f +/- %.5f\n", FIT(2), c*ERR(2)); // printf ("C = %.5f +/- %.5f\n", FIT(3), c*ERR(3)); // printf ("F = %.5f +/- %.5f\n", FIT(4), c*ERR(4)); } B = a[0] = FIT(0); E = a[1] = FIT(1); G = a[2] = FIT(2); C = a[3] = FIT(3); F = a[4] = FIT(4); gsl_multifit_fdfsolver_free (s); gsl_matrix_free (covar); ///////////////////////////////////////////////////////// if (testfit(a) == 1) return 1; for (i=1; i<=N; i++) { xint=(i*TCK_VPR-TCK_VPR/2)/1000.; yint= lineargauss(xint, a); vpr_int[i-1] = yint; } return 0; }
int main(int argc, char **argv[]) { testfit(); exit(0); }
/* comstart interpola_VPR idx interpola il profilo verticale tramite una funzione lingauss interpola il profilo verticale tramite una funzione gaussiana + lineare del tipo y= B*exp(-((x-E)/G)^2)+C+Fx usa la funzione mrqmin delle numerical recipes in C: tutti i vettori passati a mrqmin devono essere allocati e deallcocati usando le funzioni di NR (vector, matrix, free_vector, free_matrix.. etc) che definiscono vettori con indice a partire da 1. NB gli ndata dati considerati partono da 1000 m sotto il massimo (in caso il massimo sia più basso di 1000 m partono da 0 m) A ogni iterazione si esegue un test sui parametri. Se ritorna 1 si torna ai valori dell'iterazione precedente. A fine interpolazione si verifica che il chisquare non superi una soglia prefissata, in tal caso ritorna 1 e interpol. fallisce. INIZIALIZZAZIONE PARAMETRI: a[1]=B=vpr(liv del massimo)-vpr(liv. del massimo+500m); a[2]=E= quota liv. massimo vpr (in KM); a[3]=G=semiampiezza BB (quota liv .massimo- quota massimo decremento vpr nei 600 m sopra il massimo ) in KM; a[4]=C=vpr(liv massimo + 700 m); a[5]=F=coeff. angolare segmento con estremi nel vpr ai livelli max+900m e max+1700m, se negativo =0.; float a[ma], int ma: vettore parametri e n0 parametri float *x, *y: quote in KM e valori del vpr usati per l'interpolazione float *sig,alamda : vettore dev st. e variabile che decrementa al convergere delle iterazioni float *dyda: vettore derivate rispetto ai parametri float B,E,C,G,F: parametri da ottimizzare, first guess float chisq; scarto quadratico int i,in1,in2,in3,in4,*ia,ifit,ii,ndati_ok,k; int ndata=15; numero di dati considerati float **covar,**alpha; matrice ovarianze, matrice alpha comend */ int InterpolaVPR_NR::interpola_VPR(const float* vpr, int hvprmax, int livmin) { LOG_CATEGORY("radar.vpr"); static const unsigned npar=5; float *x, *y,*sig,alamda,y1=0,*dyda,xint,qdist,*abest; float chisq=100.; float chisqold=0.0; float chisqin=0.0; int i,in1,in2,in3,in4,*ia,ifit,ii,ndati_nok,k,ier_int; //int ma=5; int ndata=10; float **covar; float **alpha; FILE *file; float *a=vector(1,npar); for (i=1;i<=npar;i++){ a[i]=NODATAVPR; } LOG_INFO("sono in interpola_vpr"); ier_int=0; in1=(hvprmax-TCK_VPR/2)/TCK_VPR; //indice del massimo in2=(hvprmax+HALF_BB)/TCK_VPR; //indice del massimo + 500 m in3=in2+1; in4=in2+5; //indice del massimo + 1000 m LOG_INFO("in1 in2 %i %i %f %f",in1,in2,vpr[in1],vpr[in2]); if (in4 > NMAXLAYER-1) { ier_int=1; return ier_int; } /* inizializzazione vettore parametri */ abest=vector(1,npar); x=vector(1,ndata); y=vector(1,ndata); sig=vector(1,ndata); ia=ivector(1,npar); covar=matrix(1,npar,1,npar); alpha=matrix(1,npar,1,npar); for (k=in1+2; k<=in3; k++) { ier_int=0; dyda=vector(1,npar); a[1]=B=vpr[in1]-vpr[in2]; a[2]=E=hvprmax/1000.; a[3]=G=(k-in1-0.5)*TCK_VPR/1000.; // a[3]= G=0.25; a[4]=C=vpr[in2]; a[5]=F=vpr[in4]<vpr[in3]?(vpr[in4]-vpr[in3])/((in4-in3)*TCK_VPR/1000.):0.; //fprintf(stderr, "k:%d, a1:%f a2:%f a3:%f a4:%f a5:%f\n", k, a[1], a[2], a[3], a[4], a[5]); alamda=-0.01; for (i=1;i<=npar;i++) ia[i]=1; qdist=0; ii=1; ndati_nok=0; for (i=1; i<=ndata; i++) { sig[ii]=0.5; x[ii]= ((hvprmax-1000.)>livmin)? (i*TCK_VPR+(hvprmax-800)-TCK_VPR)/1000. : (livmin+(i-1)*TCK_VPR)/1000.; y[ii]= ((hvprmax-1000.)>livmin)? vpr[i+((hvprmax-800)-TCK_VPR)/TCK_VPR] : vpr[i-1+livmin/TCK_VPR]; // x[ii]= ((hvprmax-800.)>livmin)? (i*TCK_VPR+(hvprmax-600)-TCK_VPR)/1000. : (livmin+(i-1)*TCK_VPR)/1000.; //y[ii]= ((hvprmax-800.)>livmin)? vpr[i+((hvprmax-600)-TCK_VPR)/TCK_VPR] : vpr[i-1+livmin/TCK_VPR]; lineargauss(x[ii], a, &y1, dyda, ndata); qdist=(y1-y[ii])*(y1-y[ii]); //fprintf(stderr, "i:%d, ii:%d, xii:%f, yii:%f, y1:%f, qdist:%f, chisqin:%f\n", i, ii, x[ii], y[ii], y1, qdist, chisqin); if (sqrt(qdist) < DIST_MAX) { ii+=1; chisqin=qdist+chisqin; } else ndati_nok=ndati_nok+1; if ( ndati_nok > 2 ) { LOG_WARN(" first guess troppo lontano dai punti , interpolazione fallisce"); ier_int=1; break; } } if (!ier_int) { LOG_INFO("\n alamda %f chisqin % f a[1] % f a[2] % f a[3] % f a[4] % f a[5] % f", alamda,chisqin,a[1], a[2], a[3],a[4],a[5]); //fprintf(stderr, "i t y sigma\n"); //for (unsigned i = 1; i <= ndata; ++i) //fprintf(stderr, "%2d %.2f %.2f %.2f\n", i, x[i], y[i], sig[i]); ifit=0; while (fabs(chisq-chisqold) > DCHISQTHR && ifit < 1) { chisqold=chisq; B=a[1]; E=a[2]; G=a[3]; C=a[4]; F=a[5]; mrqmin(x, y, sig, ndata, a, ia, npar, covar, alpha, &chisq, &lineargauss, &alamda); LOG_INFO("alamda %f chisq % f a[1] % f a[2] % f a[3] % f a[4] % f a[5] % f", alamda,chisq,a[1], a[2], a[3],a[4],a[5]); ifit=testfit(a,chisq,chisqin); /*test sul risultato del fit */ if (ifit) {/*test sul risultato del fit */ a[1]=B; /*test sul risultato del fit */ a[2]=E; /*test sul risultato del fit */ a[3]=G; /*test sul risultato del fit */ a[4]=C; /*test sul risultato del fit */ a[5]=F; /*test sul risultato del fit */ chisq=chisqin; } } if (chisq < chisqfin) { chisqfin=chisq; for (i=1;i<=npar;i++) abest[i]=a[i]; } } } for (i=1; i<=ndata-ndati_nok; i++) { lineargauss(x[i], abest, &y1, dyda, ndata); rmsefin=rmsefin+ (y[i]-y1)*(y[i]-y1) ; } rmsefin=sqrt(rmsefin/(float)((ndata-ndati_nok)*(ndata-ndati_nok))); LOG_INFO("RMSEFIN %f", rmsefin ); if (chisqfin>CHISQ_MAX) { ier_int=1; } else { // Calcola il profilo interpolato for (i=1;i<=npar;i++) a[i]=abest[i]; for (i=1; i<=NMAXLAYER; i++) { xint=(i*TCK_VPR-TCK_VPR/2)/1000.; lineargauss(xint, a, &y1, dyda, ndata); vpr_int[i-1] = y1; } } B=a[1]; E=a[2]; G=a[3]; C=a[4]; F=a[5]; free_vector(dyda,1,npar); free_vector(abest,1,npar); free_ivector(ia,1,npar); free_vector(x,1,ndata); free_vector(y,1,ndata); free_vector(sig,1,ndata); free_matrix(alpha,1,ndata,1,ndata); free_matrix(covar,1,ndata,1,ndata); free_vector(a,1,npar); return ier_int; }
int main(int argc, char* argv[]) { // a function to do L-M minimization and return H coronal parameters // from spacecraft data //set up the input variables: name of file to fit against, and optional fitting parameters string obsname; bool userIPH=FALSE; double IPHb=0.0; bool usercal=FALSE; double cal=1.0; bool usertemp=FALSE; double Texo=1.0; bool userdens=FALSE; double nexo=1.0; bool printsim=FALSE; bool simulate_IPH=FALSE; bool forcesim=FALSE; for (int i = 1; i < argc; i++) /* Skip argv[0] (program name). */ { if (strcmp(argv[i], "-b") == 0) /* Process optional arguments. */ { userIPH=TRUE; /* * Increment 'i' again (twice total) so that you don't * check these arguments the next time through the loop. */ i++; IPHb = atof(argv[i]); /* Convert string to int. */ } else if (strcmp(argv[i], "-c") == 0) { usercal=TRUE; i++; cal = atof(argv[i]); std::cout << "Fixing calibration factor at " << cal << " .\n"; std::cout << std::endl; } else if (strcmp(argv[i], "-T") == 0) { usertemp=TRUE; i++; Texo = atof(argv[i]); std::cout << "Fixing temperature at " << Texo << " K.\n"; std::cout << std::endl; } else if (strcmp(argv[i], "-n") == 0) { userdens=TRUE; i++; nexo = atof(argv[i]); std::cout << "Fixing density at " << nexo << " / cm3.\n"; std::cout << std::endl; } else if (strcmp(argv[i], "-simIPH") == 0) { simulate_IPH=TRUE; } else if (strcmp(argv[i], "-forcesim") == 0) { forcesim=TRUE; } else if (strcmp(argv[i], "-p") == 0) { printsim=TRUE; } else { //get the observation to perform analysis on from the function call: obsname=argv[i]; std::cout << "Observation under analysis is: " << obsname << std::endl; } } if (userIPH) { if (simulate_IPH) { std::cout << "Fixing background IPH multiplier at " << IPHb << " .\n"; std::cout << std::endl; } else { std::cout << "Fixing background IPH at " << IPHb << " kR.\n"; std::cout << std::endl; } } else { if (simulate_IPH) { IPHb=1.0; } else { IPHb=0.0; } } if (!usercal) { cal=1.0; } corona_simulator sim; std::cout << "Proceeding with interpolated computation.\n"; sim.obs_import(obsname,simulate_IPH);//load the observation //here's an initial parameter guess: VecDoub parms(4);///mmm delicious parms parms[0]=30000.0;parms[1]=350.0;parms[2]=0.45;parms[3]=1.0; //this sets it up: Fitmrq testfit(sim.obs_vec,sim.I_obs,sim.DI_obs,parms,sim); //if the user specified values, fix this to the user value: if (userdens) { testfit.hold(0,nexo); } if (usertemp) { testfit.hold(1,Texo); } if (userIPH) { testfit.hold(2,IPHb); } if (usercal) { testfit.hold(3,cal); } //now do the fit, which updates all the contained objects: testfit.fit(); //get the escape flux for these parameters double lambdac = G*mMars*mH/(kB*testfit.a[1]*rexo); double vth = std::sqrt(2*kB*parms[1]/mH); double escflux = testfit.a[0]*vth/(2*std::sqrt(pi)) *(1+lambdac)*std::exp(-lambdac); //print out the results: std::cout << "\nHere's the result of the fitting routine:\n" << "Chi-squared is: " << testfit.chisq << " on " << sim.nobs-parms.size() << " DOF."<< std::endl; std::cout << "\nBest fit model parameters are: \n"; for (int i = 0; i < testfit.a.size(); i++) std::cout << testfit.a[i] << ",\t"; std::cout << "\b\b\n"; std::cout << "\nComputed escape flux is: \n"; std::cout << escflux << std::endl; std::cout << "\nFormal fit parameter covariance matrix is as follows: \n"; for (int i = 0; i < testfit.a.size(); i++) { std::cout << " [ "; for (int j = 0; j < testfit.a.size(); j++) { std::cout.width(10); std::cout << testfit.covar[i][j] << ",\t"; } std::cout << "\b\b ]" << std::endl; } if (printsim) { //print out the simulated values at the best fit double I_calc[sim.nobs]; for (int i = 0; i < sim.nobs; i++) { I_calc[i] = testfit.a[3]*sim.interp_iobs(sim.obs_vec[i], testfit.a[0], testfit.a[1], testfit.a[2]); } //print out the results: std::cout << "\nHere's the best fit:\n" << "\nI_calc = [ "; for (int i = 0; i < sim.nobs-1; i++) std::cout << I_calc[i] << ", "; std::cout << I_calc[sim.nobs-1] << " ]\n"; if (simulate_IPH) { std::cout << "\nHere's the computed and scaled IPH vector:\n" << "\nIPH = [ "; for (int i = 0; i < sim.nobs-1; i++) std::cout << testfit.a[3]*testfit.a[2]*sim.IPHb_model[i] << ", "; std::cout << testfit.a[3]*testfit.a[2]*sim.IPHb_model[sim.nobs-1] << " ]\n"; } } std::cout << std::endl << "\n\nYou have reached the end of the program!\nGoodbye.\n\n"; return 0; }