void TKfit_getPulsarDesignMatrix(double *x,double *y,int n,int nf,void (*fitFuncs)(double, double [], int,pulsar *,int,int), pulsar *psr, int* ip, double **uinv,int ipsr,double ***OUT_designMatrix,double ***OUT_white_designMatrix,double** OUT_b, double** OUT_wb){ //double precision arrays for matrix algebra. double **designMatrix, **white_designMatrix; double basisFunc[nf]; double *b,*white_b; int i,j; int nrows=get_blas_rows(uinv); int ncols=get_blas_cols(uinv); if (ncols!=n){ logmsg("n=%d ncols=%d",n,ncols); logerr("uinv error. Either you did not use malloc_uinv() to create uinv or np!=ncols"); exit(1); } if (nrows!=n && nrows != 1){ logmsg("n=%d nrows=%d",n,nrows); logerr("uinv error. Either you did not use malloc_uinv() to create uinv or np!=nrows"); exit(1); } // double arrays white_designMatrix=malloc_blas(n,nf); designMatrix=malloc_blas(n,nf); b=(double*)malloc(sizeof(double)*n); white_b=(double*)malloc(sizeof(double)*n); /* This routine has been developed from Section 15 in Numerical Recipes */ /* Determine the design matrix - eq 15.4.4 * and the vector 'b' - eq 15.4.5 */ for (i=0;i<n;i++) { // fitFuncs is not threadsafe! fitFuncs(x[i],basisFunc,nf,psr,ip[i],ipsr); for (j=0;j<nf;j++) designMatrix[i][j] = basisFunc[j]; b[i] = y[i]; } // Take into account the data covariance matrix if(nrows==1){ // we have only diagonal elements for (i=0;i<n;i++){ white_b[i]=b[i]*uinv[0][i]; for (j=0;j<nf;j++){ white_designMatrix[i][j] = designMatrix[i][j]*uinv[0][i]; } } } else { TKmultMatrix_sq(uinv,designMatrix,n,nf,white_designMatrix); TKmultMatrixVec_sq(uinv,b,n,white_b); } *OUT_designMatrix=designMatrix; *OUT_white_designMatrix=white_designMatrix; *OUT_b=b; *OUT_wb=white_b; }
// routine for pulsar fitting. void TKleastSquares_single_pulsar(double *x,double *y,int n,double *outP,double *e,int nf,double **cvm, double *chisq, void (*fitFuncs)(double, double [], int,pulsar *,int, int),pulsar *psr,double tol, int *ip,char rescale_errors, double **uinv) { double **designMatrix, **white_designMatrix, **constraintsMatrix; double *b,*white_b; constraintsMatrix=NULL; TKfit_getPulsarDesignMatrix(x,y,n,nf,fitFuncs,psr,ip,uinv,0,&designMatrix,&white_designMatrix,&b,&white_b); if(psr->nconstraints > 0){ logmsg("Get constraint weights"); computeConstraintWeights(psr); logmsg("fill constraints matrix"); constraintsMatrix = malloc_blas(psr->nconstraints,nf); for (int ic=0; ic < psr->nconstraints; ic++){ CONSTRAINTfuncs(psr,0,nf,psr->constraints[ic],constraintsMatrix[ic]); } } *chisq = TKrobustConstrainedLeastSquares(b,white_b,designMatrix,white_designMatrix,constraintsMatrix, n,nf,psr->nconstraints,tol,rescale_errors, outP,e,cvm,psr->robust); free_blas(designMatrix); // free-TKleastSquares_svd_psr_dcm-designMatrix** free_blas(white_designMatrix); // free-TKleastSquares_svd_psr_dcm-white_designMatrix** if(psr->nconstraints > 0) free_blas(constraintsMatrix); free(b); free(white_b); }
// same as above but without a uinv matrix. void TKleastSquares_svd_psr(double *x,double *y,double *sig,int n,double *p,double *e,int nf,double **cvm, double *chisq, void (*fitFuncs)(double, double [], int,pulsar *,int,int),int weight,pulsar *psr,double tol, int *ip) { logmsg("Warning: Deprecated method TKleastSquares_svd_psr() -> TKleastSquares_single_pulsar()"); int i; double ** uinv=malloc_blas(1,n); if (weight==1){ for (i=0; i<n;i++){ uinv[0][i]=1.0/sig[i]; } } else{ for (i=0; i<n;i++){ uinv[0][i]=1.0; } } TKleastSquares_single_pulsar(x,y,n,p,e,nf,cvm,chisq,fitFuncs,psr,tol,ip,(weight==0 || (weight==1 && psr->rescaleErrChisq==1)),uinv); free_blas(uinv); }
void initialiseOne (pulsar *psr, int noWarnings, int fullSetup) { int fail = 0; int i,j,k; char temp[100]; psr->nobs = 0; // psr->obsn = NULL; // if (psr->obsn == NULL) psr->obsn = (observation *)malloc(sizeof(observation)*MAX_OBSN); if (psr->obsn == NULL) fail = 1; // Initialise the barycentre vectors: // // To the best of my knowledge, this only ever happens in // preProcessSimple.C, which does not get called when running Tempo2 // through PSRchive. For reasons unknown to me, these uninitialised // values most commonly end up being zero (as they should be) and // are subsequently set later on, but once in a statistical while, // they will go rogue, crashing everything. For my purposes, // initialisation right here seems to do the trick, though a // substantial reanalysis of the preprocess and initialise functions // (and which bits belong where) is in order to make sure these // "glitches" don't happen with any other parameters. // // JPWV, MPIfR, 22 July 2010. /* for(int obsct = 0; obsct < MAX_OBSN; obsct++ ){ for (int vecct = 0; vecct < 6; vecct++ ){ psr->obsn[obsct].earthMoonBary_ssb[vecct] = 0.0; psr->obsn[obsct].earthMoonBary_earth[vecct] = 0.0; psr->obsn[obsct].observatory_earth[vecct] = 0.0; psr->obsn[obsct].earth_ssb[vecct] = 0.0; } }*/ if (fail) { printf("Not enough memory to allocate room for %d observations\n",MAX_OBSN); printf("Please decrease the value of MAX_OBSN_VAL in tempo2.h or use -nobs on the command line\n"); printf("You can also decrease the number of pulsars being stored in memory using -npsr\n"); printf("Note: 1 observation requires %f kBytes, you request %f MBytes\n",(double)sizeof(observation)/1024.0,(double)sizeof(observation)/1024.0/1024.0*MAX_OBSN); exit(1); } /* This memory gets deallocated by destroyOne */ psr->covar = malloc_blas(MAX_FIT,MAX_FIT); strcpy(psr->eopc04_file,"/earth/eopc04_IAU2000.62-now"); strcpy(psr->filterStr,""); strcpy(psr->passStr,""); strcpy(psr->fitFunc,"default"); strcpy(psr->whiteNoiseModelFile,"NULL"); psr->simflag=0; psr->nits=1; psr->clockFromOverride[0] = '\0'; psr->nCompanion = 0; psr->bootStrap = 0; psr->units = SI_UNITS; psr->setUnits = 0; psr->ne_sw = NE_SW_DEFAULT; psr->nWhite = 0; /* No whitening by default */ psr->nQuad = 0; /* No quadrupolar function */ psr->ifuncN = 0; /* No interpolation functions by default */ psr->clkOffsN = 0;/* No clock offsets by default */ psr->nTelDX = 0; psr->nTelDY = 0; psr->nTelDZ = 0; psr->quad_ifuncN_p = 0; psr->quad_ifuncN_c = 0; psr->quad_ifunc_geom_p = 0; psr->quad_ifunc_geom_c = 0; psr->cgw_mc = 0; psr->timeEphemeris = IF99_TIMEEPH; psr->useCalceph = 0; psr->dilateFreq = 1; psr->planetShapiro = 1; psr->correctTroposphere = 1; psr->t2cMethod = T2C_IAU2000B; psr->fixedFormat=0; psr->nStorePrecision=0; strcpy(psr->fjumpID,""); strcpy(psr->deleteFileName,"NONE"); strcpy(psr->tzrsite,"NULL"); psr->ToAextraCovar=NULL; psr->dmoffsDMnum=0; psr->dmoffsCMnum = 0; psr->calcShapiro=1; psr->dmOffset = 0; psr->ipm = 1; psr->swm = 0; psr->nPhaseJump=0; psr->eclCoord=0; psr->noWarnings=noWarnings; psr->fitMode = 0; /* Don't fit with errors by default (MODE 0) */ psr->robust = 0; /* Don't fit with robust by default (MODE 0) */ psr->rescaleErrChisq = 1; /* Rescale parameter errors by reduced chisq */ strcpy(psr->name,"NOT SET"); strcpy(psr->binaryModel,"NONE"); psr->nJumps=0; psr->nToffset = 0; psr->ndmx = 0; psr->nconstraints = 0; psr->constraint_efactor = 1e15; psr->auto_constraints = 0; psr->jboFormat=0; // Moved from readTimfile.C (next line): psr->dmOffset = 0; for (i=0;i<MAX_JUMPS;i++) { psr->jumpVal[i] = 0.0; psr->jumpSAT[i] = 0; psr->jumpValErr[i] = 0.0; } psr->nT2efac = 0; // Number of T2EFACs psr->nT2equad = 0; // Number of T2EQUADs psr->T2globalEfac = 1; // A global multiplying factor psr->nSx = 0; //number of SX parameters psr->nTNEF = 0; // Number of TNEFACs psr->nTNEQ = 0; // Number of TNEQUADs psr->nTNECORR = 0; // Number of TNECORRs psr->TNGlobalEF=0; psr->TNGlobalEQ=0; psr->nTNSQ = 0; // Number of TNEQUADs psr->TNRedAmp = 0; psr->TNRedGam = 0; psr->TNRedC = 0; psr->TNRedFLow=0; psr->TNRedCorner=0.01; psr->TNDMAmp = 0; psr->TNDMGam = 0; psr->TNDMC = 0; psr->TNBandDMAmp = 0; psr->TNBandDMGam = 0; psr->TNBandDMC = 0; psr->nTNBandNoise = 0; //Number of band noise parameters psr->nTNGroupNoise = 0; // Number of TN Group Noise parameters psr->TNsubtractDM=0; psr->TNsubtractRed=0; psr->AverageResiduals=0; psr->useTNOrth = 0; psr->nDMEvents=0; psr->nTNShapeletEvents=0; psr->sorted=0; psr->detUinv=0; allocateMemory(psr,0); /* psr->param[param_track].paramSet[0]=1; psr->param[param_track].val[0]=0.0; psr->param[param_track].prefit[0]=0.0;*/ /* Spin-frequency parameters */ for (j=0;j<psr->param[param_f].aSize;j++) { psr->param[param_f].val[j] = 0.0; sprintf(temp,"F%d (s^-%d)",j,j+1); strcpy(psr->param[param_f].label[j],temp); sprintf(temp,"F%d",j); strcpy(psr->param[param_f].shortlabel[j],temp); } strcpy(psr->param[param_raj].label[0],"RAJ (rad)"); strcpy(psr->param[param_raj].shortlabel[0],"RAJ"); strcpy(psr->param[param_decj].label[0],"DECJ (rad)"); strcpy(psr->param[param_decj].shortlabel[0],"DECJ"); strcpy(psr->param[param_fddi].label[0],"FDDI"); /* Frequency dependent delay */ strcpy(psr->param[param_fddi].shortlabel[0],"FDDI"); /* Frequency dependent delay */ strcpy(psr->param[param_fddc].label[0],"FDDC"); /* Frequency dependent delay */ strcpy(psr->param[param_fddc].shortlabel[0],"FDDC"); /* Frequency dependent delay */ for (j=0; j<psr->param[param_fd].aSize; j++) { sprintf(psr->param[param_fd].shortlabel[j],"FD%d",j+1); sprintf(psr->param[param_fd].label[j],"FD%d",j+1); } /* Dispersion measure and its derivative */ for (k=0;k<psr->param[param_dm].aSize;k++) { if (k>0){ sprintf(temp,"DM%d (cm^-3 pc yr^-%d)",k,k); strcpy(psr->param[param_dm].label[k],temp); sprintf(temp,"DM%d",k); strcpy(psr->param[param_dm].shortlabel[k],temp); } else { strcpy(psr->param[param_dm].label[0],"DM (cm^-3 pc)"); strcpy(psr->param[param_dm].shortlabel[0],"DM"); } } strcpy(psr->param[param_px].label[0],"PX (mas)"); strcpy(psr->param[param_px].shortlabel[0],"PX"); strcpy(psr->param[param_dm_sin1yr].label[0],"DM_S1YR (cm^-3 pc)"); strcpy(psr->param[param_dm_sin1yr].shortlabel[0],"DM_S1YR"); strcpy(psr->param[param_dm_cos1yr].label[0],"DM_C1YR (cm^-3 pc)"); strcpy(psr->param[param_dm_cos1yr].shortlabel[0],"DM_C1YR"); strcpy(psr->param[param_daop].label[0],"AOP dist. (kpc)"); strcpy(psr->param[param_daop].shortlabel[0],"D_AOP"); strcpy(psr->param[param_daop].label[0],"IPERHARM"); strcpy(psr->param[param_daop].shortlabel[0],"IPERHARM"); strcpy(psr->param[param_pmrv].label[0],"PMRV (mas/yr)"); strcpy(psr->param[param_pmrv].shortlabel[0],"PMRV"); for (k=0;k<psr->param[param_dmassplanet].aSize;k++) { sprintf(psr->param[param_dmassplanet].label[k], "DMASSPLANET%d (Msun)", k+1); sprintf(psr->param[param_dmassplanet].shortlabel[k], "DMASSPLANET%d", k+1); } strcpy(psr->param[param_tres].label[0],"TRES"); strcpy(psr->param[param_tres].shortlabel[0],"TRES"); strcpy(psr->param[param_ephver].label[0],"EPHVER"); strcpy(psr->param[param_ephver].shortlabel[0],"EPHVER"); strcpy(psr->param[param_pmra].label[0],"PMRA (mas/yr)"); strcpy(psr->param[param_pmra].shortlabel[0],"PMRA"); strcpy(psr->param[param_pmdec].label[0],"PMDEC (mas/yr)"); strcpy(psr->param[param_pmdec].shortlabel[0],"PMDEC"); strcpy(psr->param[param_posepoch].label[0],"POSEPOCH (MJD)"); strcpy(psr->param[param_posepoch].shortlabel[0],"POSEPOCH"); strcpy(psr->param[param_waveepoch].label[0],"WAVEEPOCH (MJD)"); strcpy(psr->param[param_waveepoch].shortlabel[0],"WAVEEPOCH"); strcpy(psr->param[param_waveepoch_dm].label[0],"WAVEEPOCHD (MJD)"); strcpy(psr->param[param_waveepoch_dm].shortlabel[0],"WAVEEPOCHD"); strcpy(psr->param[param_gwm_amp].label[0],"GWM_AMP"); strcpy(psr->param[param_gwm_amp].shortlabel[0],"GWM_AMP"); strcpy(psr->param[param_gwm_amp].label[1],"GWM_AMP_2"); strcpy(psr->param[param_gwm_amp].shortlabel[1],"GWM_AMP_2"); strcpy(psr->param[param_gwcs_amp].label[0],"GWCS_AMP1"); strcpy(psr->param[param_gwcs_amp].shortlabel[0],"GWCS_AMP1"); strcpy(psr->param[param_gwcs_amp].label[1],"GWCS_AMP2"); strcpy(psr->param[param_gwcs_amp].shortlabel[1],"GWCS_AMP2"); strcpy(psr->param[param_gwb_amp].label[0],"GWB_AMP"); strcpy(psr->param[param_gwb_amp].shortlabel[0],"GWB_AMP"); strcpy(psr->param[param_gwb_amp].label[1],"GWB_AMP_2"); strcpy(psr->param[param_gwb_amp].shortlabel[1],"GWB_AMP_2"); strcpy(psr->param[param_gwecc].label[0],"GWECC_AMP"); strcpy(psr->param[param_gwecc].shortlabel[0],"GWECC_AMP"); strcpy(psr->param[param_tel_dx].label[0],"TEL_DX"); strcpy(psr->param[param_tel_dy].label[0],"TEL_DY"); strcpy(psr->param[param_tel_dz].label[0],"TEL_DZ"); strcpy(psr->param[param_tel_vx].label[0],"TEL_VX (km/s)"); strcpy(psr->param[param_tel_vy].label[0],"TEL_VY (km/s)"); strcpy(psr->param[param_tel_vz].label[0],"TEL_VZ (km/s)"); strcpy(psr->param[param_tel_x0].label[0],"TEL_X0 (km)"); strcpy(psr->param[param_tel_y0].label[0],"TEL_Y0 (km)"); strcpy(psr->param[param_tel_z0].label[0],"TEL_Z0 (km)"); strcpy(psr->param[param_tel_dx].shortlabel[0],"TEL_DX"); strcpy(psr->param[param_tel_dy].shortlabel[0],"TEL_DY"); strcpy(psr->param[param_tel_dz].shortlabel[0],"TEL_DZ"); strcpy(psr->param[param_tel_vx].shortlabel[0],"TEL_VX"); strcpy(psr->param[param_tel_vy].shortlabel[0],"TEL_VY"); strcpy(psr->param[param_tel_vz].shortlabel[0],"TEL_VZ"); strcpy(psr->param[param_tel_x0].shortlabel[0],"TEL_X0"); strcpy(psr->param[param_tel_y0].shortlabel[0],"TEL_Y0"); strcpy(psr->param[param_tel_z0].shortlabel[0],"TEL_Z0"); strcpy(psr->param[param_ifunc].label[0],"IFUNC"); strcpy(psr->param[param_ifunc].shortlabel[0],"IFUNC"); strcpy(psr->param[param_df1].label[0],"DF1"); strcpy(psr->param[param_df1].shortlabel[0],"DF1"); strcpy(psr->param[param_clk_offs].label[0],"CLK_OFFS"); strcpy(psr->param[param_clk_offs].shortlabel[0],"CLK_OFFS"); strcpy(psr->param[param_quad_ifunc_p].label[0],"QIFUNC_p"); strcpy(psr->param[param_quad_ifunc_p].shortlabel[0],"QIFUNC_p"); strcpy(psr->param[param_quad_ifunc_c].label[0],"QIFUNC_c"); strcpy(psr->param[param_quad_ifunc_c].shortlabel[0],"QIFUNC_c"); strcpy(psr->param[param_pepoch].label[0],"PEPOCH (MJD)"); strcpy(psr->param[param_pepoch].shortlabel[0],"PEPOCH"); strcpy(psr->param[param_dmepoch].label[0],"DMEPOCH (MJD)"); strcpy(psr->param[param_dmepoch].shortlabel[0],"DMEPOCH"); strcpy(psr->param[param_start].label[0],"START (MJD)"); strcpy(psr->param[param_start].shortlabel[0],"START"); strcpy(psr->param[param_finish].label[0],"FINISH (MJD)"); strcpy(psr->param[param_finish].shortlabel[0],"FINISH"); strcpy(psr->param[param_track].label[0],"TRACK (MJD)"); strcpy(psr->param[param_track].shortlabel[0],"TRACK"); strcpy(psr->param[param_dshk].label[0],"DSHK (kpc)"); strcpy(psr->param[param_dshk].shortlabel[0],"DSHK"); strcpy(psr->param[param_iperharm].label[0],"IPERHARM"); strcpy(psr->param[param_iperharm].shortlabel[0],"IPERHARM"); /* Telescope coordinates */ strcpy(psr->param[param_telx].shortlabel[0],"TELX"); strcpy(psr->param[param_telx].label[0],"TELX (lt-s)"); for (k=1;k<psr->param[param_telx].aSize;k++) { sprintf(psr->param[param_telx].label[k], "TELX%d (lt-s)", k); sprintf(psr->param[param_telx].shortlabel[k], "TELX%d", k); } strcpy(psr->param[param_tely].shortlabel[0],"TELY"); strcpy(psr->param[param_tely].label[0],"TELY (lt-s)"); for (k=1;k<psr->param[param_tely].aSize;k++) { sprintf(psr->param[param_tely].label[k], "TELY%d (lt-s)", k); sprintf(psr->param[param_tely].shortlabel[k], "TELY%d", k); } strcpy(psr->param[param_telz].shortlabel[0],"TELZ"); strcpy(psr->param[param_telz].label[0],"TELZ (lt-s)"); for (k=1;k<psr->param[param_telz].aSize;k++) { sprintf(psr->param[param_telz].label[k], "TELZ%d (lt-s)", k); sprintf(psr->param[param_telz].shortlabel[k], "TELZ%d", k); } strcpy(psr->param[param_telEpoch].shortlabel[0],"TELEPOCH"); strcpy(psr->param[param_telEpoch].label[0],"TEL EPOCH (MJD)"); /* Glitch parameters */ for (k=0;k<psr->param[param_glep].aSize;k++) { sprintf(temp,"GLEP_%d",k+1); strcpy(psr->param[param_glep].label[k],temp); strcpy(psr->param[param_glep].shortlabel[k],temp); sprintf(temp,"GLPH_%d",k+1); strcpy(psr->param[param_glph].label[k],temp); strcpy(psr->param[param_glph].shortlabel[k],temp); sprintf(temp,"GLF0_%d",k+1); strcpy(psr->param[param_glf0].label[k],temp); strcpy(psr->param[param_glf0].shortlabel[k],temp); sprintf(temp,"GLF1_%d",k+1); strcpy(psr->param[param_glf1].label[k],temp); strcpy(psr->param[param_glf1].shortlabel[k],temp); sprintf(temp,"GLF2_%d",k+1); strcpy(psr->param[param_glf2].label[k],temp); strcpy(psr->param[param_glf2].shortlabel[k],temp); sprintf(temp,"GLF0D_%d",k+1); strcpy(psr->param[param_glf0d].label[k],temp); strcpy(psr->param[param_glf0d].shortlabel[k],temp); sprintf(temp,"GLTD_%d",k+1); strcpy(psr->param[param_gltd].label[k],temp); strcpy(psr->param[param_gltd].shortlabel[k],temp); sprintf(temp,"SWITCH_%d",k+1); strcpy(psr->param[param_stateSwitchT].label[k],temp); strcpy(psr->param[param_stateSwitchT].shortlabel[k],temp); } /* Binary parameters */ strcpy(psr->param[param_t0].label[0],"T0 (MJD)"); strcpy(psr->param[param_t0].shortlabel[0],"T0"); for (k=0;k<psr->param[param_fb].aSize;k++) { sprintf(temp,"FB%d",k); strcpy(psr->param[param_fb].label[k],temp); sprintf(temp,"FB%d",k); strcpy(psr->param[param_fb].shortlabel[k],temp); } /* Dispersion measure and its derivative */ for (k=1;k<psr->param[param_pb].aSize;k++) { sprintf(temp,"PB_%d (d)",k+1); strcpy(psr->param[param_pb].label[k],temp); sprintf(temp,"PB_%d",k+1); strcpy(psr->param[param_pb].shortlabel[k],temp); sprintf(temp,"ECC_%d",k+1); strcpy(psr->param[param_ecc].label[k],temp); sprintf(temp,"ECC_%d",k+1); strcpy(psr->param[param_ecc].shortlabel[k],temp); sprintf(temp,"OM_%d (deg)",k+1); strcpy(psr->param[param_om].label[k],temp); sprintf(temp,"OM_%d",k+1); strcpy(psr->param[param_om].shortlabel[k],temp); sprintf(temp,"A1_%d (lt-s)",k+1); strcpy(psr->param[param_a1].label[k],temp); sprintf(temp,"A1_%d",k+1); strcpy(psr->param[param_a1].shortlabel[k],temp); sprintf(temp,"T0_%d (mjd)",k+1); strcpy(psr->param[param_t0].label[k],temp); sprintf(temp,"T0_%d",k+1); strcpy(psr->param[param_t0].shortlabel[k],temp); } strcpy(psr->param[param_pb].label[0],"PB (d)"); strcpy(psr->param[param_pb].shortlabel[0],"PB"); strcpy(psr->param[param_a1].label[0],"A1 (lt-s)"); strcpy(psr->param[param_a1].shortlabel[0],"A1"); strcpy(psr->param[param_om].label[0],"OM (deg)"); strcpy(psr->param[param_om].shortlabel[0],"OM"); strcpy(psr->param[param_ecc].label[0],"ECC"); strcpy(psr->param[param_e2dot].shortlabel[0],"E2DOT"); strcpy(psr->param[param_e2dot].label[0],"E2DOT"); strcpy(psr->param[param_edot].shortlabel[0],"EDOT"); strcpy(psr->param[param_edot].label[0],"EDOT"); strcpy(psr->param[param_ecc].shortlabel[0],"ECC"); strcpy(psr->param[param_kom].label[0],"KOM"); strcpy(psr->param[param_kom].shortlabel[0],"KOM"); strcpy(psr->param[param_kin].label[0],"KIN"); strcpy(psr->param[param_kin].shortlabel[0],"KIN"); strcpy(psr->param[param_shapmax].label[0],"SHAPMAX"); strcpy(psr->param[param_shapmax].shortlabel[0],"SHAPMAX"); strcpy(psr->param[param_m2].label[0],"M2"); strcpy(psr->param[param_m2].shortlabel[0],"M2"); strcpy(psr->param[param_mtot].label[0],"MTOT"); strcpy(psr->param[param_mtot].shortlabel[0],"MTOT"); strcpy(psr->param[param_dr].label[0],"DR"); strcpy(psr->param[param_dr].shortlabel[0],"DR"); strcpy(psr->param[param_dth].label[0],"DTH"); strcpy(psr->param[param_dth].shortlabel[0],"DTH"); strcpy(psr->param[param_a0].label[0],"A0"); strcpy(psr->param[param_a0].shortlabel[0],"A0"); strcpy(psr->param[param_b0].label[0],"B0"); strcpy(psr->param[param_b0].shortlabel[0],"B0"); strcpy(psr->param[param_bp].label[0],"BP"); strcpy(psr->param[param_bp].shortlabel[0],"BP"); strcpy(psr->param[param_bpp].label[0],"BPP"); strcpy(psr->param[param_bpp].shortlabel[0],"BPP"); strcpy(psr->param[param_dtheta].label[0],"DTHETA"); strcpy(psr->param[param_dtheta].shortlabel[0],"DTHETA"); strcpy(psr->param[param_sini].label[0],"SINI"); strcpy(psr->param[param_sini].shortlabel[0],"SINI"); // Freire & Wex (2010; FW10) parameters: strcpy( psr->param[param_h3].label[0], "H3" ); strcpy( psr->param[param_h3].shortlabel[0], "H3" ); strcpy( psr->param[param_stig].label[0], "STIG" ); strcpy( psr->param[param_stig].shortlabel[0], "STIG" ); strcpy( psr->param[param_h4].label[0], "H4" ); strcpy( psr->param[param_h4].shortlabel[0], "H4" ); strcpy( psr->param[param_nharm].label[0], "Number of Shapiro delay harmonics" ); strcpy( psr->param[param_nharm].shortlabel[0], "NHARM" ); // End Freire & Wex parameters strcpy(psr->param[param_gamma].label[0],"GAMMA"); strcpy(psr->param[param_gamma].shortlabel[0],"GAMMA"); strcpy(psr->param[param_pbdot].label[0],"PBDOT"); strcpy(psr->param[param_pbdot].shortlabel[0],"PBDOT"); strcpy(psr->param[param_xpbdot].label[0],"XPBDOT"); strcpy(psr->param[param_xpbdot].shortlabel[0],"XPBDOT"); strcpy(psr->param[param_a1dot].label[0],"XDOT"); strcpy(psr->param[param_a1dot].shortlabel[0],"XDOT"); strcpy(psr->param[param_a2dot].label[0],"X2DOT"); strcpy(psr->param[param_a2dot].shortlabel[0],"X2DOT"); strcpy(psr->param[param_xomdot].label[0],"XOMDOT"); strcpy(psr->param[param_xomdot].shortlabel[0],"XOMDOT"); strcpy(psr->param[param_afac].label[0],"AFAC"); strcpy(psr->param[param_afac].shortlabel[0],"AFAC"); strcpy(psr->param[param_omdot].label[0],"OMDOT (deg/yr)"); strcpy(psr->param[param_omdot].shortlabel[0],"OMDOT"); strcpy(psr->param[param_om2dot].label[0],"OM2DOT(1e-20 rad/yr^2)"); strcpy(psr->param[param_om2dot].shortlabel[0],"OM2DOT"); strcpy(psr->param[param_orbpx].label[0],"ORBPX (kpc^-1)"); strcpy(psr->param[param_orbpx].shortlabel[0],"ORBPX"); strcpy(psr->param[param_tasc].label[0],"TASC (MJD)"); strcpy(psr->param[param_tasc].shortlabel[0],"TASC"); strcpy(psr->param[param_eps1].label[0],"EPS1"); strcpy(psr->param[param_eps1].shortlabel[0],"EPS1"); strcpy(psr->param[param_eps1dot].label[0],"EPS1DOT"); strcpy(psr->param[param_eps1dot].shortlabel[0],"EPS1DOT"); strcpy(psr->param[param_eps2].label[0],"EPS2"); strcpy(psr->param[param_eps2].shortlabel[0],"EPS2"); strcpy(psr->param[param_eps2dot].label[0],"EPS2DOT"); strcpy(psr->param[param_eps2dot].shortlabel[0],"EPS2DOT"); strcpy(psr->param[param_tzrmjd].label[0],"TZRMJD"); strcpy(psr->param[param_tzrmjd].shortlabel[0],"TZRMJD"); strcpy(psr->param[param_tzrfrq].label[0],"TZRFRQ (MHz)"); strcpy(psr->param[param_tzrfrq].shortlabel[0],"TZRFRQ"); strcpy(psr->param[param_tspan].label[0],"TSPAN (min)"); strcpy(psr->param[param_tspan].shortlabel[0],"TSPAN"); strcpy(psr->param[param_brake].label[0],"BRAKING INDEX"); strcpy(psr->param[param_brake].shortlabel[0],"BRAKE"); strcpy( psr->param[param_ne_sw].label[0], "NE_SW (cm^-3)" ); strcpy( psr->param[param_ne_sw].shortlabel[0], "NE_SW" ); for (k=0;k<psr->param[param_bpjep].aSize;k++) { sprintf(temp,"BPJEP_%d",k+1); strcpy(psr->param[param_bpjep].label[k],temp); strcpy(psr->param[param_bpjep].shortlabel[k],temp); sprintf(temp,"BPJPH_%d",k+1); strcpy(psr->param[param_bpjph].label[k],temp); strcpy(psr->param[param_bpjph].shortlabel[k],temp); sprintf(temp,"BPJA1_%d",k+1); strcpy(psr->param[param_bpja1].label[k],temp); strcpy(psr->param[param_bpja1].shortlabel[k],temp); sprintf(temp,"BPJEC_%d",k+1); strcpy(psr->param[param_bpjec].label[k],temp); strcpy(psr->param[param_bpjec].shortlabel[k],temp); sprintf(temp,"BPJOM_%d",k+1); strcpy(psr->param[param_bpjom].label[k],temp); strcpy(psr->param[param_bpjom].shortlabel[k],temp); sprintf(temp,"BPJPB_%d",k+1); strcpy(psr->param[param_bpjpb].label[k],temp); strcpy(psr->param[param_bpjpb].shortlabel[k],temp); } strcpy(psr->param[param_wave_om].label[0],"WAVE_OM"); strcpy(psr->param[param_wave_om].shortlabel[0],"WAVE_OM"); strcpy(psr->param[param_wave_dm].label[0],"WAVE_DM"); strcpy(psr->param[param_wave_dm].shortlabel[0],"WAVE_DM"); strcpy(psr->param[param_quad_om].label[0],"QUAD_OM"); strcpy(psr->param[param_quad_om].shortlabel[0],"QUAD_OM"); strcpy(psr->param[param_dmmodel].label[0],"DMMODEL"); strcpy(psr->param[param_dmmodel].shortlabel[0],"DMMODEL"); strcpy(psr->param[param_gwsingle].label[0],"GW_OMEGA"); strcpy(psr->param[param_gwsingle].shortlabel[0],"GW_OMEGA"); /* Piecewise-constant DM variation (DMX) */ for (k=0;k<psr->param[param_dmx].aSize;k++) { sprintf(temp,"DMX_%04d (cm^-3 pc)",k+1); strcpy(psr->param[param_dmx].label[k],temp); sprintf(temp,"DMX_%04d",k+1); strcpy(psr->param[param_dmx].shortlabel[k],temp); sprintf(temp,"DMXR1_%04d (MJD)",k+1); strcpy(psr->param[param_dmxr1].label[k],temp); sprintf(temp,"DMXR1_%04d",k+1); strcpy(psr->param[param_dmxr1].shortlabel[k],temp); sprintf(temp,"DMXR2_%04d (MJD)",k+1); strcpy(psr->param[param_dmxr2].label[k],temp); sprintf(temp,"DMXR2_%04d",k+1); strcpy(psr->param[param_dmxr2].shortlabel[k],temp); } for (k=0;k<psr->param[param_sx].aSize;k++) { sprintf(temp,"SX_%04d (cm^-3 pc)",k+1); strcpy(psr->param[param_sx].label[k],temp); sprintf(temp,"SX_%04d",k+1); strcpy(psr->param[param_sx].shortlabel[k],temp); sprintf(temp,"SXR1_%04d (MJD)",k+1); strcpy(psr->param[param_sxr1].label[k],temp); sprintf(temp,"SXR1_%04d",k+1); strcpy(psr->param[param_sxr1].shortlabel[k],temp); sprintf(temp,"SXR2_%04d (MJD)",k+1); strcpy(psr->param[param_sxr2].label[k],temp); sprintf(temp,"SXR2_%04d",k+1); strcpy(psr->param[param_sxr2].shortlabel[k],temp); sprintf(temp,"SXER_%04d (MJD)",k+1); strcpy(psr->param[param_sxer].label[k],temp); sprintf(temp,"SXER_%04d",k+1); strcpy(psr->param[param_sxer].shortlabel[k],temp); } for (k=0; k < MAX_PARAMS; ++k){ psr->constraint_special[k]=0; } }
void TKleastSquares_global_pulsar(double **x,double **y,int *n, double *outP,double *e,int* nf, int nglobal,double **cvm, double *chisq, void (*fitFuncs)(double, double [], int,pulsar *,int,int),pulsar *psr,double tol, int **ip,char rescale_errors, double ***uinv, int npsr) { double **designMatrix, **white_designMatrix; double **constraintsMatrix; double **psr_DM, **psr_wDM; double *b,*white_b, *psr_b,*psr_wb; int ipsr; int totalFit=0; int totalObs=0; int totalConstraints=0; int i,j; int off_r=0; int off_f=0; int off_c=0; for (ipsr=0; ipsr < npsr; ipsr++){ totalFit+=nf[ipsr]; totalObs+=n[ipsr]; totalConstraints+=psr[ipsr].nconstraints; } totalFit+=nglobal; white_designMatrix=malloc_blas(totalObs,totalFit); designMatrix=malloc_blas(totalObs,totalFit); constraintsMatrix=malloc_blas(totalConstraints,totalFit); b=(double*)calloc(totalObs,sizeof(double)); white_b=(double*)calloc(totalObs,sizeof(double)); for (ipsr=0; ipsr < npsr; ipsr++){ logdbg("Getting design matrix / whitened residuals for psr %d off_r=%d off_f=%d nglobal=%d",ipsr,off_r,off_f,nglobal); TKfit_getPulsarDesignMatrix(x[ipsr],y[ipsr],n[ipsr],nf[ipsr]+nglobal,fitFuncs,psr,ip[ipsr],uinv[ipsr],ipsr,&psr_DM,&psr_wDM,&psr_b,&psr_wb); // the global fit parameters for(i=0; i < n[ipsr]; i++){ for(j=0; j < nglobal; j++){ designMatrix[i+off_r][j] = psr_DM[i][j]; white_designMatrix[i+off_r][j] = psr_wDM[i][j]; } } // the regular fit parameters for(i=0; i < n[ipsr]; i++){ for(j=0; j < nf[ipsr]; j++){ designMatrix[i+off_r][j+off_f+nglobal] = psr_DM[i][j+nglobal]; white_designMatrix[i+off_r][j+off_f+nglobal] = psr_wDM[i][j+nglobal]; } } // the residuals for(i=0; i < n[ipsr]; i++){ b[i+off_r] = psr_b[i]; white_b[i+off_r] = psr_wb[i]; } if(psr[ipsr].nconstraints > 0){ logmsg("Get constraint weights"); computeConstraintWeights(psr+ipsr); logmsg("fill constraints matrix"); for (int ic=0; ic < psr[ipsr].nconstraints; ic++){ CONSTRAINTfuncs(psr,ipsr,nf[ipsr],psr->constraints[ic],constraintsMatrix[ic+off_c]+off_f); } } // increment the offset. off_r += n[ipsr]; off_f += nf[ipsr]; off_c += psr[ipsr].nconstraints; // free temp matricies. free_blas(psr_DM); free_blas(psr_wDM); free(psr_b); free(psr_wb); } // go ahead and do the fit! *chisq = TKrobustConstrainedLeastSquares(b,white_b,designMatrix,white_designMatrix, constraintsMatrix, totalObs,totalFit,totalConstraints,tol,rescale_errors, outP,e,cvm,psr[0].robust); free_blas(designMatrix); // free-TKleastSquares_svd_psr_dcm-designMatrix** free_blas(white_designMatrix); // free-TKleastSquares_svd_psr_dcm-white_designMatrix** free_blas(constraintsMatrix); // free-TKleastSquares_svd_psr_dcm-white_designMatrix** free(b); free(white_b); }
void t2Fit(pulsar *psr,unsigned int npsr, const char *covarFuncFile){ // if we have a model for the data covariance function, then use it. // Otherwise we we will just whiten using the error bars. bool haveCovar = (covarFuncFile!=NULL && strcmp(covarFuncFile,"NULL")); /** * Find out if there are any global parameters and what they are... */ FitInfo global_fitinfo; t2Fit_fillGlobalFitInfo(psr,npsr,global_fitinfo); logdbg("Nglobal parameters = %d",global_fitinfo.nParams); // If we had any global parameters (or constraints) then we need to do a global fit // otherwise we can do a fit for each pulsar individually, which is quicker // and saves memory. bool doGlobalFit = (global_fitinfo.nParams > 0) || (global_fitinfo.nConstraints > 0); unsigned long long totalGlobalData=0; // the number of data points across all pulsars unsigned int gParams=global_fitinfo.nParams; // the number of global fit parameters unsigned int gConstraints=global_fitinfo.nConstraints; // the number of global constraints unsigned long long totalGlobalParams=gParams; unsigned long long totalGlobalConstraints=gConstraints; double** gUinvs[MAX_PSR]; // whitening matrix for each pulsar double* gX[MAX_PSR]; // "x" values for each pulsar double* gY[MAX_PSR]; // "y" values for each pulsar double* gW[MAX_PSR]; // whitened "y" values for each pulsar double** gDM[MAX_PSR]; // design matrix for each pulsar double** gWDM[MAX_PSR]; // whitened design matrix for each pulsar double** gCM[MAX_PSR]; // constraints matrix for each pulsar unsigned int gNdata[MAX_PSR]; // number of data points for each pulsar (size of x and y) logmsg("NEW fit routine. GlobalFit=%s",doGlobalFit ? "true" : "false"); /** * However we are going to do the fit, we want to loop over all the pulsars * to get the input data and design matricies etc. */ for (size_t ipsr=0; ipsr < npsr; ipsr++) { double *psr_x = (double*)malloc(sizeof(double)*psr[ipsr].nobs); double *psr_y = (double*)malloc(sizeof(double)*psr[ipsr].nobs); double *psr_white_y = (double*)malloc(sizeof(double)*psr[ipsr].nobs); double *psr_e = (double*)malloc(sizeof(double)*psr[ipsr].nobs); int *psr_toaidx = (int*)malloc(sizeof(int)*psr[ipsr].nobs); // mapping from fit data to observation number double** uinv; // the whitening matrix. /** * Working out which data contributes to the fit is done in this routine. * Basically gets values for all observations within START and FINISH which are * not deleted. * * returns the number of data points. */ const unsigned int psr_ndata = t2Fit_getFitData(psr+ipsr,psr_x,psr_y,psr_e,psr_toaidx); assert(psr_ndata > 0u); psr[ipsr].nFit = psr_ndata; // pulsar.nFit is the number of data points used in the fit. /** * Now we work out which parameters are being fit for, how many parameters, * and determine the gradient functions for the design matrix and the update functions * which update the pulsar struct. */ t2Fit_fillFitInfo(psr+ipsr,psr[ipsr].fitinfo,global_fitinfo); /** * The whitening matrix behaves diferently if we have a covariance matrix. * If we have a covariance matrix, uinv is an ndata x ndata triangular matrix. * Otherwise, it only has diagonal elements, so we efficiently store it as * a 1-d ndata array. */ if (haveCovar) { // ToAs must be sorted for covariance function code sortToAs(psr+ipsr); // malloc_uinv does a blas-compatible allocation of a 2-d array. uinv = malloc_uinv(psr_ndata); psr[ipsr].fitMode=1; // Note: forcing this to 1 as the Cholesky fit is a weighted fit logmsg("Doing a FULL COVARIANCE MATRIX fit"); } else { // Here the whitening matrix is just a diagonal // weighting matrix. Store diagonal matrix as 1xN // so that types match later. uinv=malloc_blas(1,psr_ndata); if(psr[ipsr].fitMode == 0){ // if we are doing an unweighted fit then we should set the errors to 1.0 // to give uniform weighting. logdbg("Doing an UNWEIGHTED fit"); for (unsigned int i=0; i < psr_ndata; i++){ psr_e[i]=1.0; } } else { logdbg("Doing a WEIGHTED fit"); } } assert(uinv!=NULL); /** * Now we form the whitening matrix, uinv. * Note that getCholeskyMatrix() is clever enough to see that we * have created a 1 x ndata matrix if we have only diagonal elements. */ getCholeskyMatrix(uinv,covarFuncFile,psr+ipsr, psr_x,psr_y,psr_e, psr_ndata,0,psr_toaidx); logtchk("got Uinv"); // define some convinience variables const unsigned nParams=psr[ipsr].fitinfo.nParams; const unsigned nConstraints=psr[ipsr].fitinfo.nConstraints; /** * The design matrix is the matrix of gradients for the least-squares. * If the design matrix is M, parameters p, and data d, we are solving * M.p = d * It is ndata x nparams in size. We also allocate the whitened DM here. */ double** designMatrix = malloc_blas(psr_ndata,nParams); double** white_designMatrix = malloc_blas(psr_ndata,nParams); for (unsigned int idata =0; idata < psr_ndata; ++idata){ // t2Fit_buildDesignMatrix is a replacement for the old FITfuncs routine. // it fills one row of the design matrix. t2Fit_buildDesignMatrix(psr,ipsr,psr_x[idata], psr_toaidx[idata], designMatrix[idata]); } logtchk("made design matrix"); /** * The constraints matrix is similar to the design matrix, but here we are solving: * B.p = 0 * Where B is the constraints matrix and p is the parameters. we solve both this * and the DM equation set simultaniously. TKleastSquares will do this for us. * * If there are no constraints we leave it as NULL, which is detected in TKfit as * no constraints anyway. */ double** constraintsMatrix =NULL; if(psr[ipsr].fitinfo.nConstraints > 0){ computeConstraintWeights(psr+ipsr); constraintsMatrix = malloc_blas(nConstraints,nParams); for (unsigned int iconstraint =0; iconstraint < nConstraints; ++iconstraint){ // similar to t2Fit_buildDesignMatrix, t2Fit_buildConstraintsMatrix // creates one row of the constraints matrix. t2Fit_buildConstraintsMatrix(psr, ipsr, iconstraint, constraintsMatrix[iconstraint]); } } logtchk("made constraints matrix"); /** * Now we multiply the design matrix and the data vector by the whitening matrix. * If we just have variances (uinv is diagonal) then we do it traditionally, otherwise * we use TKmultMatrix as this is usually backed by LAPACK and so is fast :) */ if(haveCovar){ TKmultMatrixVec(uinv,psr_y,psr_ndata,psr_ndata,psr_white_y); TKmultMatrix_sq(uinv,designMatrix,psr_ndata,nParams,white_designMatrix); } else { for(unsigned i=0;i<psr_ndata;++i){ psr_white_y[i]=psr_y[i]*uinv[0][i]; for(unsigned j=0;j<nParams;++j){ white_designMatrix[i][j] = designMatrix[i][j]*uinv[0][i]; } } } free_blas(uinv); free(psr_e); free(psr_toaidx); logtchk("done whitening"); /* * Now - if we are going to do a global fit, we store all the above for later * otherwise */ if (doGlobalFit){ // we are going to do a global fit, so need to store the values for later gX[ipsr] = psr_x; gY[ipsr] = psr_y; gW[ipsr] = psr_white_y; gDM[ipsr] = designMatrix; gWDM[ipsr] = white_designMatrix; gCM[ipsr] = constraintsMatrix; gNdata[ipsr] = psr_ndata; totalGlobalData += psr_ndata; totalGlobalParams += nParams - gParams; totalGlobalConstraints += nConstraints - gConstraints; } else { // NOT GLOBAL // so do one fit at a time... double chisq; // the post-fit chi-squared // allocate memory for the output of TKleastSquares double* parameterEstimates = (double*)malloc(sizeof(double)*nParams); double* errorEstimates = (double*)malloc(sizeof(double)*nParams); /* * Call TKleastSquares, or in fact, TKrobustConstrainedLeastSquares, * since we might want robust fitting and/or constraints/ * * The arguments here are explained in TKfit.C * */ chisq = TKrobustConstrainedLeastSquares(psr_y,psr_white_y, designMatrix,white_designMatrix,constraintsMatrix, psr_ndata,nParams,nConstraints, T2_SVD_TOL,1,parameterEstimates,errorEstimates,psr[ipsr].covar, psr[ipsr].robust); // update the pulsar struct as appropriate psr[ipsr].fitChisq = chisq; psr[ipsr].fitNfree = psr_ndata + nConstraints - nParams; logdbg("Updating the parameters"); logtchk("updating the parameter values"); /* * This routine calls the appropriate update functions to apply the result of the fit * to the origianal (non-linearised) pulsar parameters. */ t2Fit_updateParameters(psr,ipsr,parameterEstimates,errorEstimates); logtchk("complete updating the parameter values"); logdbg("Completed updating the parameters"); /* * If we are not doing a global fit, we can clean up the memory for this pulsar. * Might make a difference for very large datasets. */ logdbg("Free fit memory"); free(parameterEstimates); free(errorEstimates); free_blas(designMatrix); free_blas(white_designMatrix); if (constraintsMatrix) free_blas(constraintsMatrix); free(psr_x); free(psr_y); free(psr_white_y); } } if (doGlobalFit){ const unsigned int nobs = totalGlobalData; double** designMatrix = malloc_blas(nobs,totalGlobalParams); double** white_designMatrix = malloc_blas(nobs,totalGlobalParams); double** constraintsMatrix = malloc_blas(totalGlobalConstraints,totalGlobalParams); double *y = (double*)malloc(sizeof(double)*nobs); double *white_y = (double*)malloc(sizeof(double)*nobs); unsigned int off_f = gParams; // leave space for globals unsigned int off_r = 0; unsigned int off_c = gConstraints; logdbg("Building matricies for global fit... npsr=%u",npsr); logdbg("nobs=%u, totalGlobalParams=%u, totalGlobalConstraints=%u",nobs,totalGlobalParams,totalGlobalConstraints); logwarn("This mode is not supported yet!!!"); for (unsigned int ipsr = 0; ipsr < npsr ; ++ipsr){ unsigned int nLocal = psr[ipsr].fitinfo.nParams-gParams; logdbg("ipsr=%u, off_r = %u, off_c=%u, off_f=%u, nlocal=%u", ipsr,off_r,off_c,off_f,nLocal); // the fit parameters for(unsigned int i=0; i < gNdata[ipsr]; i++){ // the global params (they go first) for(unsigned int g= 0; g < gParams; g++){ unsigned int j = g+nLocal; if(ipsr==0 && i==0 && writeResiduals){ logmsg("Row %d = %s %s(%d)",g,"global",label_str[global_fitinfo.paramIndex[g]],global_fitinfo.paramCounters[g]); } designMatrix[i+off_r][g] = gDM[ipsr][i][j]; white_designMatrix[i+off_r][g] = gWDM[ipsr][i][j]; } for(unsigned int j=0; j < nLocal; j++){ if(i==0 && writeResiduals){ logmsg("Row %d = %s %s(%d)",j+off_f,psr[ipsr].name,label_str[psr[ipsr].fitinfo.paramIndex[j]],psr[ipsr].fitinfo.paramCounters[j]); } designMatrix[i+off_r][j+off_f] = gDM[ipsr][i][j]; white_designMatrix[i+off_r][j+off_f] = gWDM[ipsr][i][j]; } } // the data for(unsigned int i=0; i < gNdata[ipsr]; ++i){ y[i+off_r] = gY[ipsr][i]; white_y[i+off_r] = gW[ipsr][i]; } for(unsigned int i=0; i < psr[ipsr].fitinfo.nConstraints; i++){ for(unsigned int j=0; j < nLocal; j++){ constraintsMatrix[i+off_c][j+off_f] = gCM[ipsr][i][j]; } // the global params (they go first) for(unsigned int g= 0; g < gParams; g++){ unsigned int j = g+nLocal; constraintsMatrix[i+off_c][g] = gCM[ipsr][i][j]; } } off_r += gNdata[ipsr]; off_f += nLocal; off_c += psr[ipsr].fitinfo.nConstraints; free(gY[ipsr]); free(gW[ipsr]); free_blas(gDM[ipsr]); if (gCM[ipsr]) free_blas(gCM[ipsr]); free_blas(gWDM[ipsr]); } double chisq; // the post-fit chi-squared double* parameterEstimates = (double*)malloc(sizeof(double)*totalGlobalParams); double* errorEstimates = (double*)malloc(sizeof(double)*totalGlobalParams); chisq = TKrobustConstrainedLeastSquares(y,white_y, designMatrix,white_designMatrix,constraintsMatrix, nobs,totalGlobalParams,totalGlobalConstraints, T2_SVD_TOL,1,parameterEstimates,errorEstimates,psr[0].covar, psr[0].robust); // for now the CVM ends up in psr[0].covar. int off_p = gParams; for (unsigned int ipsr = 0; ipsr < npsr ; ++ipsr){ // update the pulsar struct as appropriate psr[ipsr].fitChisq = chisq; psr[ipsr].fitNfree = nobs + totalGlobalConstraints - totalGlobalParams; double* psr_parameterEstimates = (double*)malloc(sizeof(double)*psr[ipsr].fitinfo.nParams); double* psr_errorEstimates = (double*)malloc(sizeof(double)*psr[ipsr].fitinfo.nParams); const unsigned np = psr[ipsr].fitinfo.nParams-gParams; /* extract the fit output for the individual pulsars. * I.e. detangle the global fit * Notice: Globals go at the end of the individual pulsar arrays. */ for (unsigned i = 0; i < np; ++i){ psr_parameterEstimates[i] = parameterEstimates[off_p]; psr_errorEstimates[i] = errorEstimates[off_p]; ++off_p; } for (unsigned i = 0; i < gParams; ++i){ psr_parameterEstimates[i+np] = parameterEstimates[i]; psr_errorEstimates[i] = errorEstimates[off_p]; } logdbg("Updating the parameters"); logtchk("updating the parameter values"); /* * This routine calls the appropriate update functions to apply the result of the fit * to the origianal (non-linearised) pulsar parameters. */ t2Fit_updateParameters(psr,ipsr,psr_parameterEstimates,psr_errorEstimates); logtchk("complete updating the parameter values"); logdbg("Completed updating the parameters"); free(psr_parameterEstimates); free(psr_errorEstimates); } free(parameterEstimates); free(errorEstimates); free(white_y); free(y); free_blas(designMatrix); free_blas(white_designMatrix); free_blas(constraintsMatrix); } }