예제 #1
0
파일: setup_aster.c 프로젝트: bitursa/maos
/**
   Free the ASTER_S array.
 */
void free_aster(ASTER_S *aster, int naster, const PARMS_S *parms){
    (void) parms;
    for(int iaster=0; iaster<naster; iaster++){
	int ndtrat=parms->skyc.ndtrat;
	if(aster[iaster].kalman){
	    if(parms->skyc.multirate){
		kalman_free(aster[iaster].kalman[0]);
		dcellfreearr(aster[iaster].neam, 1);
	    }else{
		for(int i=0; i<ndtrat; i++){
		    kalman_free(aster[iaster].kalman[i]);
		}
		dcellfreearr(aster[iaster].neam, ndtrat);
	    }
	    free(aster[iaster].kalman);
	    aster[iaster].kalman=0;
	}
	dcellfree(aster[iaster].gain);
	dcellfree(aster[iaster].pgm);
	dcellfree(aster[iaster].sigman);
	dfree(aster[iaster].res_ws);
	dfree(aster[iaster].res_ngs);

	free(aster[iaster].wfs);
	dcellfree(aster[iaster].g);
	dfree(aster[iaster].gm);
	dfree(aster[iaster].dtrats);
	dfree(aster[iaster].idtrats);
	free(aster[iaster].ngs);
    }
    free(aster);
}
예제 #2
0
void TomoL(dcell **xout, const void *A, 
	   const dcell *xin, const double alpha){

    const RECON_T *recon=(const RECON_T *)A;
    dcell *gg=NULL;
    dspcellmulmat_thread(&gg, recon->G0tomo, xin, 1.,recon->nthread);
    TTFR(gg, recon->TTF, recon->PTTF);
    dcell *gg2=NULL;
    dspcellmulmat_thread(&gg2, recon->saneai, gg,1,recon->nthread);
    sptcellmulmat_thread(xout,recon->G0tomo,gg2,alpha,recon->nthread);
    dcellfree(gg);
    dcellfree(gg2);
    if(recon->L2){
	apply_L2(xout, recon->L2, xin, alpha, recon->nthread);
    }else{
	apply_invpsd(xout, recon->xloc_embed, recon->invpsd,
		     recon->fftxopd, xin, alpha);
    }
    if(recon->ZZT){/*single point piston constraint */
	sptcellmulmat_thread(xout, recon->ZZT, xin, alpha,
			     recon->nthread);
    }
    /*Tikhonov regularization is not added because it is not
      necessary in CG mode.*/
}
예제 #3
0
파일: servo.c 프로젝트: bitursa/maos
/**
   Free SERVO_T struct
*/
void servo_free(SERVO_T *st){
    if(!st) return;
    dcellfree(st->mlead);
    dcellfree(st->merrlast);
    dcellfree(st->mpreint);
    cellfree(st->merrhist);
    cellfree(st->mint);
    dfree(st->ap);
    dfree(st->ep);
    free(st);
}
예제 #4
0
void TomoR(dcell **xout, const void *A, 
	   const dcell *xin, const double alpha){
    
    const RECON_T *recon=(const RECON_T *)A;
    dcell *x2=NULL;
    dcellcp(&x2, xin);
    TTFR(x2, recon->TTF, recon->PTTF);
    dcell *x3=NULL;
    dspcellmulmat_thread(&x3,recon->saneai, x2, 1,recon->nthread);
    sptcellmulmat_thread(xout,recon->G0tomo,x3,alpha,recon->nthread);
    dcellfree(x2);
    dcellfree(x3);
}
예제 #5
0
static int test_fit(){
    info("Fit\n");
    dcell *opdr=dcellread("opdr.bin");
    MUV_T FR;
    FR.M=dspcellread("FRM.bin");
    FR.U=dcellread("FRU.bin");
    FR.V=dcellread("FRV.bin");
    MUV_T FL;
    FL.M=dspcellread("FLM.bin");
    FL.U=dcellread("FLU.bin");
    FL.V=dcellread("FLV.bin");
    dcell *rhs=NULL;
    tic;
    for(int i=0; i<10; i++)
	MUV(&rhs, &FR, opdr, 1);
    toc("");
    dcell *MUV_f=NULL;
    tic;
    for(int i=0; i<10; i++)
	MUV(&MUV_f, &FL, rhs, 1);
    toc("");
    writebin(rhs,"fit_rhs1.bin");
    writebin(MUV_f,"MUV_f.bin");
    RECON_T *recon=mycalloc(1,RECON_T);
    recon->HX=dspcellread("HX.bin");
    recon->HA=dspcellread("HA.bin");
    recon->W1=dread("W1.bin");
    recon->W0=dspread("W0.bin");
    recon->NW=dcellread("NW.bin");
    recon->fitwt=dread("fitwt.bin");
    dcell *rhs2=NULL;
    tic;
    for(int i=0; i<10; i++)
	FitR(&rhs2, recon, opdr, 1);
    toc("");
    writebin(rhs2,"fit_rhs2.bin");
    tic;
    dcell *FitL_f=NULL;
    for(int i=0; i<10; i++)
	FitL(&FitL_f, recon, rhs2, 1);
    toc("");
    writebin(FitL_f,"FitL_f.bin");
    info("Diff between rhs is %g\n", dcelldiff(rhs, rhs2));
    info("Diff between lhs is %g\n", dcelldiff(MUV_f, FitL_f));
    dcellfree(rhs);
    dcellfree(MUV_f);
    dcellfree(rhs2);
    dcellfree(FitL_f);
    return 0;
}
예제 #6
0
파일: servo.c 프로젝트: bitursa/maos
/**
   test type I/II filter with ideal measurement to make sure it is implemented correctly.
*/
dmat* servo_test(dmat *input, double dt, int dtrat, dmat *sigma2n, dmat *gain){
    if(input->ny==1){/*single mode. each column is for a mode.*/
	input->ny=input->nx;
	input->nx=1;
    }
    int nmod=input->nx;
    PDMAT(input,pinput);
    dmat *merr=dnew(nmod,1);
    dcell *mreal=cellnew(1,1);
    dmat *mres=dnew(nmod,input->ny);
    dmat *sigman=NULL;
    if(dnorm(sigma2n)>0){
	sigman=dchol(sigma2n);
    }
    dcell *meas=cellnew(1,1);
    dmat *noise=dnew(nmod, 1);
    SERVO_T *st2t=servo_new(NULL, NULL, 0, dt*dtrat, gain);
    rand_t rstat;
    seed_rand(&rstat, 1);
    PDMAT(mres,pmres);
    /*two step delay is ensured with the order of using, copy, acc*/
    for(int istep=0; istep<input->ny; istep++){
	memcpy(merr->p, pinput[istep], nmod*sizeof(double));
	dadd(&merr, 1, mreal->p[0], -1);
	memcpy(pmres[istep],merr->p,sizeof(double)*nmod);
	if(istep % dtrat == 0){
	    dzero(meas->p[0]);
	}
	dadd(&meas->p[0], 1, merr, 1);/*average the error. */
	dcellcp(&mreal, st2t->mint->p[0]);
	if((istep+1) % dtrat == 0){
	    if(dtrat!=1) dscale(meas->p[0], 1./dtrat);
	    if(sigman){
		drandn(noise, 1, &rstat);
		if(sigman->nx>0){
		    dmm(&meas->p[0], 1, sigman, noise, "nn", 1);
		}else{
		    dadd(&meas->p[0], 1, noise, sigman->p[0]);
		}
	    }
	    servo_filter(st2t, meas);
	}
    }
    dfree(sigman);
    dfree(merr);
    dcellfree(mreal);
    dcellfree(meas);
    servo_free(st2t);
    return mres;
}
예제 #7
0
파일: setup_aster.c 프로젝트: bitursa/maos
void setup_aster_lsr(ASTER_S *aster, STAR_S *star, const PARMS_S *parms){
    int ndtrat=parms->skyc.ndtrat;
    if(aster->pgm){
	dcellfree(aster->pgm);
	dcellfree(aster->sigman);
    }
    aster->pgm=cellnew(ndtrat,1);
    aster->sigman=cellnew(ndtrat,1);
    dmat *gm=ddup(aster->gm);
    if(aster->nwfs==1 && parms->maos.nmod==6 && gm->nx==8){
	info2("set 3rd column of gm to zero\n");
	memset(gm->p+gm->nx*2, 0, sizeof(double)*gm->nx);
    }

    for(int idtrat=0; idtrat<ndtrat; idtrat++){
	dcell *nea=cellnew(aster->nwfs, 1);
	for(int iwfs=0; iwfs<aster->nwfs; iwfs++){
	    nea->p[iwfs]=ddup(aster->wfs[iwfs].pistat->sanea->p[idtrat]);
	    dcwpow(nea->p[iwfs], 2);
	}
	dmat *neam=dcell2m(nea);//measurement error covariance
	dcellfree(nea); 
	dcwpow(neam, -1);//inverse
	/*Reconstructor */
	aster->pgm->p[idtrat]=dpinv(gm, neam);
	/*sigman is error due to noise. */
	dcwpow(neam, -1);//inverse again
	aster->sigman->p[idtrat]=calc_recon_error(aster->pgm->p[idtrat],neam,parms->maos.mcc);
	dfree(neam);
    }	
    if(parms->skyc.dbg){
	writebin(gm,"%s/aster%d_gm",dirsetup,aster->iaster);
	writebin(aster->pgm,    "%s/aster%d_pgm", dirsetup,aster->iaster);
	writebin(aster->sigman, "%s/aster%d_sigman", dirsetup,aster->iaster);
    }
    dfree(gm);
}
예제 #8
0
파일: servo.c 프로젝트: bitursa/maos
/*A FIFO queue to add delay*/
static const dcell*servo_shift_al(SERVO_T *st, const dcell *merr){
    if(!st->al){
	return merr;
    }else{
	long nhist=st->merrhist->nx;
	dcell *cycle=st->merrhist->p[0];
	for(int i=0; i<nhist-1; i++){
	    st->merrhist->p[i]=st->merrhist->p[i+1];
	}
	st->merrhist->p[nhist-1]=cycle;
	if(!merr){
	    dcellfree(st->merrhist->p[nhist-1]);
	}else{
	    dcelladd(&st->merrhist->p[nhist-1], 0, merr, 1);
	}
	return st->merrhist->p[0];
    }
}
예제 #9
0
void MUV(dcell **xout, const void *A, 
	 const dcell *xin, const double alpha){
    /**
       Apply the sparse plug low rand compuation to xin
       without scaling of alpha:
       xout=(muv.M-muv.U*muv.V')*xin*alpha; U,V are low
       rank.
    */
    const MUV_T *muv=(const MUV_T *)A;

    dspcellmulmat(xout, muv->M, xin, alpha);
    dcell *tmp=NULL;
    dcellmm(&tmp,muv->V, xin, "tn", -1.);
    dcellmm(xout,muv->U, tmp, "nn", alpha);
    dcellfree(tmp);
    if(muv->invpsd){
	apply_invpsd(xout, muv->xembed, muv->invpsd, muv->fftxopd, xin, alpha);
    }
}
예제 #10
0
/**
   Assemble the DM fitting matrix

   The fitting is done by minimizing \f$||H_X x - H_A a||^2_W\f$ where \f$H_X,
   H_A\f$ are ray tracing operator from tomography grid xloc, and deformable
   mirror grid aloc to pupil grid ploc. The norm is weighted using bilinear
   influence functions within the telescope aperture. We have
   
   \f$a=\left[H_A^T(W_0-W_1 W_1^T)H_A\right]^{-1} H_A^T (W_0-W_1) H_X x\f$

   For details see www.opticsinfobase.org/abstract.cfm?URI=josaa-19-9-1803 
*/
static void
setup_recon_fit_matrix(RECON_T *recon, const PARMS_T *parms){
    const int nfit=parms->fit.nfit;
    const int ndm=parms->ndm;
    if(ndm==0) return;
    dspcell *HATc=dspcelltrans(recon->HA);
    PDSPCELL(HATc, HAT);
    PDSPCELL(recon->HA,HA);

    info2("Before assembling fit matrix:\t%.2f MiB\n",get_job_mem()/1024.);
    /*Assemble Fit matrix. */
    int npsr=recon->npsr;
    if(parms->load.fit){
	if(!(zfexist("FRM") && zfexist("FRU") && zfexist("FRV"))){
	    error("FRM, FRU, FRV (.bin) not all exist\n");
	}
	warning("Loading saved recon->FR\n");
	recon->FR.M=readbin("FRM");
	recon->FR.U=dcellread("FRU");
	recon->FR.V=dcellread("FRV");
    }else{
	if(recon->HXF){
	    info2("Building recon->FR\n");
	    recon->FR.M=cellnew(ndm, npsr);
	    PDSPCELL(recon->FR.M, FRM);
	    PDSPCELL(recon->HXF, HXF);

	    for(int ips=0; ips<npsr; ips++){
		for(int ifit=0; ifit<nfit; ifit++){
		    if(fabs(recon->fitwt->p[ifit])<1.e-12) continue;
		    dsp *tmp=dspmulsp(recon->W0, HXF[ips][ifit],"nn");
		    for(int idm=0; idm<ndm; idm++){
			dspmulsp2(&FRM[ips][idm],HAT[ifit][idm], tmp, "nn",
				  recon->fitwt->p[ifit]);
		    }
		    dspfree(tmp);
		}
	    }
	    recon->FR.V=cellnew(npsr, 1);
	    dmat **FRV=recon->FR.V->p;  
	
	    for(int ips=0; ips<npsr; ips++){
		int nloc=recon->xloc->p[ips]->nloc;
		FRV[ips]=dnew(nloc,nfit);
		for(int ifit=0; ifit<nfit; ifit++){
		    /*notice the sqrt. */
		    if(fabs(recon->fitwt->p[ifit])<1.e-12) continue;
		    dspmulvec(FRV[ips]->p+ifit*nloc, 
			      HXF[ips][ifit], recon->W1->p, 't',
			      sqrt(recon->fitwt->p[ifit]));
		}
	    }
	    if(parms->save.recon){
		writebin(recon->FR.M,"FRM");
		writebin(recon->FR.V,"FRV");
	    }
	}else{
	    info("Avoid building recon->FR.M\n");
	    recon->FR.M=NULL;
	    recon->FR.V=NULL;
	}
	/*Always need FR.U as it is used to do FL.U, FL.V */
	recon->FR.U=cellnew(ndm, 1);
	dmat **FRU=recon->FR.U->p;
	
	for(int idm=0; idm<ndm; idm++){    
	    int nloc=recon->aloc->p[idm]->nloc;
	    FRU[idm]=dnew(nloc, nfit);
	    for(int ifit=0; ifit<nfit; ifit++){
		/*notice the sart. */
		if(fabs(recon->fitwt->p[ifit])<1.e-12) continue;
		dspmulvec(FRU[idm]->p+ifit*nloc, 
			  HA[idm][ifit], recon->W1->p,'t',
			  sqrt(recon->fitwt->p[ifit]));
	    }
	}
	if(parms->save.recon){
	    writebin(recon->FR.U,"FRU");
	}
    }

    if(parms->load.fit){
	if(!(zfexist("FLM") && zfexist("FLU") && zfexist("FLV"))){
	    error("FLM, FLU, FLV (.bin) not all exist\n");
	}
	warning("Loading saved recon->FL\n");
	recon->FL.M=readbin("FLM");
	recon->FL.U=dcellread("FLU");
	recon->FL.V=dcellread("FLV");
    }else{
	info2("Building recon->FL\n");
	recon->FL.M=cellnew(ndm, ndm);
	dsp *(*FLM)[ndm]=(dsp*(*)[ndm])recon->FL.M->p;
	for(int idm=0; idm<ndm; idm++){
	    for(int ifit=0; ifit<nfit; ifit++){
		if(fabs(recon->fitwt->p[ifit])<1.e-12) continue;
		dsp *tmp=dspmulsp(recon->W0, HA[idm][ifit],"nn");
		for(int jdm=0; jdm<ndm; jdm++){
		    dspmulsp2(&FLM[idm][jdm],HAT[ifit][jdm], tmp,"nn",
			      recon->fitwt->p[ifit]);
		}
		dspfree(tmp);
	    }
	}
	dspcellfree(HATc);
	if(fabs(parms->fit.tikcr)>1.e-15){
	    double tikcr=parms->fit.tikcr;
	    /*Estimated from the formula.  1/nloc is due to W0, the other
	      scaling is due to ray tracing between different sampling freq.*/
	    int nact=0;
	    for(int idm=0; idm<parms->ndm; idm++){
		nact+=recon->aloc->p[idm]->nloc;
	    }
	    double maxeig=4./nact;
	    info2("Adding tikhonov constraint of %g to FLM\n", tikcr);
	    info2("The maximum eigen value is estimated to be around %e\n", maxeig);
	    dcelladdI(recon->FL.M,tikcr*maxeig);
	}

	{/*Low rank terms. */
	    recon->FL.U=dcellcat_each(recon->FR.U, recon->fitNW, 2);
	    dcell *tmp=NULL;/*negative NW. */
	    dcelladd(&tmp, 1, recon->fitNW, -1);
	    recon->FL.V=dcellcat_each(recon->FR.U, tmp, 2);
	    dcellfree(tmp);
	}
	if(recon->actslave){
	    dcelladd(&recon->FL.M, 1, recon->actslave, 1);
	}
	/*dspcellsym(recon->FL.M); */
	info2("DM Fit number of Low rank terms: %ld in RHS, %ld in LHS\n",
	      recon->FR.U->p[0]->ny, recon->FL.U->p[0]->ny);
	if(parms->save.recon){
	    writebin(recon->FL.M,"FLM.bin");
	    writebin(recon->FL.U,"FLU");
	    writebin(recon->FL.V,"FLV");
	}
    }
    if((parms->fit.alg==0 || parms->fit.alg==2) && parms->fit.bgs){
	muv_direct_diag_prep(&(recon->FL),(parms->fit.alg==2)*parms->fit.svdthres);
    }
    if((parms->fit.alg==0 || parms->fit.alg==2) && !parms->fit.bgs){
	if(fabs(parms->fit.tikcr)<1.e-14){
	    warning("tickcr=%g is too small, chol may fail.\n", parms->fit.tikcr);
	}
	muv_direct_prep(&(recon->FL),(parms->fit.alg==2)*parms->fit.svdthres);
	info2("After cholesky/svd on matrix:\t%.2f MiB\n",get_job_mem()/1024.);
    }
 
    if(parms->save.recon){
       	if(recon->FL.C){
	    chol_convert(recon->FL.C, 1);
	    chol_save(recon->FL.C,"FLC.bin");
	}
	if(recon->FL.MI)
	    writebin(recon->FL.MI,"FLMI");
	if(recon->FL.Up)
	    writebin(recon->FL.Up, "FLUp");
	if(recon->FL.Vp)
	    writebin(recon->FL.Vp, "FLVp");
	if(recon->FL.CB){
	    for(int ib=0; ib<recon->FL.nb; ib++){
		chol_save(recon->FL.CB[ib],"FLCB_%d.bin", ib);
	    }
	}
	if(recon->FL.MIB){
	    writebin(recon->FL.MIB,"FLMIB");
	}
    }
    info2("After assemble fit matrix:\t%.2f MiB\n",get_job_mem()/1024.);
}
예제 #11
0
파일: setup_aster.c 프로젝트: bitursa/maos
/**
   Optimize type II servo gains beased on measurement noise and signal PSD. We try to minimize
   \f[
   \sigma^2=\int \textrm{PSD}_{ngs,ws}H_{rej}\textrm{d}\nu + \int_0^{\nu_{nyquist}} \textrm{PSF}\textrm{d}\nu
   \f]
*/
static void setup_aster_servo(SIM_S *simu, ASTER_S *aster, const PARMS_S *parms){
    int ndtrat=parms->skyc.ndtrat;
    if(aster->gain){
	dcellfree(aster->gain);
	dfree(aster->res_ws);
	dfree(aster->res_ngs);
    }
    aster->gain=cellnew(ndtrat,1);
    aster->res_ws=dnew(ndtrat,1);
    aster->res_ngs=dnew(ndtrat,3);
    PDMAT(aster->res_ngs, pres_ngs);
    for(int idtrat=0; idtrat<ndtrat; idtrat++){
	int dtrat=parms->skyc.dtrats->p[idtrat];
	double sigma_ngs= aster->sigman->p[idtrat]->p[0];
	double sigma_tt = aster->sigman->p[idtrat]->p[1];
	double sigma_ps = sigma_ngs-sigma_tt;
	double sigma_focus = aster->sigman->p[idtrat]->p[2];
	long nmod=parms->maos.nmod;
	/*gsplit:
	  0: All modes use the same gain.
	  1: PS, TT, focus (if nmod>5) use different gains. 
	  2: PS, TT use different gains. focus mode (if nmod>5) use PS gains.
	 */

	double res_ngs;/*residual error due to signal after servo rejection. */
	double res_ngsn;/*residual error due to noise. */
	const int servotype=parms->skyc.servo;
	const int ng=parms->skyc.ngain;
	aster->gain->p[idtrat]=dnew(ng,nmod);
	PDMAT(aster->gain->p[idtrat], pgain);
	if(parms->skyc.gsplit){
	    double pg_tt[ng+2];
	    double pg_ps[ng+2];
	    double pg_focus[ng+2];
	    if(parms->skyc.interpg){
		interp_gain(pg_tt, simu->gain_tt[idtrat], simu->gain_x, sigma_tt);
		interp_gain(pg_ps, simu->gain_ps[idtrat], simu->gain_x, sigma_ps);
		interp_gain(pg_focus, simu->gain_focus[idtrat], simu->gain_x, sigma_focus);
	    }else{
		dmat *sigma2=dnew(1,1); 
		dcell *tmp;
		sigma2->p[0]=sigma_tt;
		tmp=servo_optim(simu->psd_tt, parms->maos.dt, dtrat, parms->skyc.pmargin, sigma2, servotype);
		memcpy(pg_tt, tmp->p[0]->p, (ng+2)*sizeof(double)); dcellfree(tmp);

		sigma2->p[0]=sigma_ps;
		tmp=servo_optim(simu->psd_ps,    parms->maos.dt, dtrat, parms->skyc.pmargin, sigma2, servotype);
		memcpy(pg_ps, tmp->p[0]->p, (ng+2)*sizeof(double)); dcellfree(tmp);

		if(nmod>5){
		    sigma2->p[0]=sigma_focus;
		    tmp=servo_optim(simu->psd_focus, parms->maos.dt, dtrat, parms->skyc.pmargin, sigma2, servotype);
		    memcpy(pg_focus, tmp->p[0]->p, (ng+2)*sizeof(double)); dcellfree(tmp);
		}
		dfree(sigma2);
	    }
	    res_ngs  = pg_tt[ng] + pg_ps[ng] + pg_focus[ng];//residual mode
	    res_ngsn = pg_tt[ng+1] + pg_ps[ng+1] + pg_focus[ng+1];//error due to noise
	    for(int imod=0; imod<MIN(nmod,5); imod++){
		memcpy(pgain[imod], imod<2?pg_tt:pg_ps, sizeof(double)*ng);
	    }
	    if(nmod>5){
		memcpy(pgain[5], pg_focus, sizeof(double)*ng);
	    }
	}else{
	    double pg_ngs[ng+2];
	    if(parms->skyc.interpg){
		interp_gain(pg_ngs, simu->gain_ngs[idtrat], simu->gain_x, sigma_ngs);
	    }else{
		dmat *sigma2=dnew(1,1); sigma2->p[0]=sigma_ngs;
		dcell *tmp;
		tmp=servo_optim(simu->psd_ngs, parms->maos.dt, dtrat, parms->skyc.pmargin, sigma2, servotype);
		memcpy(pg_ngs, tmp->p[0]->p, (ng+2)*sizeof(double)); dcellfree(tmp);
	    }
	    res_ngs=pg_ngs[ng];
	    res_ngsn=pg_ngs[ng+1];
	    for(int imod=0; imod<nmod; imod++){
		memcpy(pgain[imod], pg_ngs, sizeof(double)*ng);
	    }
	}
	pres_ngs[0][idtrat]=res_ngs+res_ngsn;/*error due to signal and noise */
	pres_ngs[1][idtrat]=res_ngs;/*error due to signal */
	pres_ngs[2][idtrat]=res_ngsn;/*error due to noise propagation. */
	/*if(parms->skyc.reest){//estiamte error in time domain
	    dmat *sigma2=dnew(nmod,nmod);PDMAT(sigma2, psigma2);
	    PDMAT(parms->maos.mcc, pmcc);
	    //convert noise into mode space from WFE space.
	    psigma2[0][0]=psigma2[1][1]=sigma_tt/(2*pmcc[0][0]);
	    psigma2[2][2]=psigma2[3][3]=psigma2[4][4]=sigma_ps/(3*pmcc[2][2]);
	    if(nmod>5){
		psigma2[5][5]=sigma_focus/pmcc[5][5];
	    }
	    dmat *res=servo_test(simu->mideal, parms->maos.dt, dtrat, sigma2, aster->gain->p[idtrat]);
	    double rms=calc_rms(res,parms->maos.mcc, parms->skyc.evlstart);
	    pres_ngs[0][idtrat]=rms;
	    dfree(sigma2);
	    dfree(res);
	    }*/
	dmat *g_tt=dnew_ref(ng,1,pgain[0]);
	double gain_n;
	aster->res_ws->p[idtrat]=servo_residual(&gain_n, parms->skyc.psd_ws, 
						parms->maos.dt, dtrat, g_tt, 2);
	dfree(g_tt);
    }//for dtrat
    if(parms->skyc.dbg){
	writebin(aster->gain,"%s/aster%d_gain",dirsetup,aster->iaster);
	writebin(aster->res_ws,"%s/aster%d_res_ws",dirsetup,aster->iaster);
	writebin(aster->res_ngs,"%s/aster%d_res_ngs",dirsetup,aster->iaster);
    }
}
예제 #12
0
/**
   Closed loop simulation main loop. It calls init_simu() to initialize the
   simulation struct. Then calls genatm() to generate atmospheric turbulence
   screens. Then for every time step, it calls perfevl() to evaluate
   performance, wfsgrad() to do wfs measurement, reconstruct() to do tomography
   and DM fit, filter() to do DM command filtering. In MOAO mode, it call calls
   moao_recon() for MOAO DM fitting.  \callgraph */
void maos_sim(){
    const PARMS_T *parms=global->parms;
    POWFS_T *powfs=global->powfs;
    RECON_T *recon=global->recon;
    APER_T *aper=global->aper;
    int simend=parms->sim.end;
    int simstart=parms->sim.start;
    if(parms->sim.skysim){
	save_skyc(powfs,recon,parms);
    }
    if(parms->evl.psfmean || parms->evl.psfhist){
	/*compute diffraction limited PSF. Save to output directory.*/
	dmat *iopdevl=dnew(aper->locs->nloc,1);
	ccell *psf2s=0;
	locfft_psf(&psf2s, aper->embed, iopdevl, parms->evl.psfsize, 0);
	const int nwvl=parms->evl.nwvl;
	dcell *evlpsfdl=dcellnew(nwvl,1);
	for(int iwvl=0; iwvl<nwvl; iwvl++){
	    cabs22d(&evlpsfdl->p[iwvl], 1, psf2s->p[iwvl], 1);
	    evlpsfdl->p[iwvl]->header=evl_header(parms, aper, -1, iwvl);
	}
	ccellfree(psf2s);
	writebin(evlpsfdl, "evlpsfdl.fits");
	dcellfree(evlpsfdl);
	dfree(iopdevl);
    }
    info2("PARALLEL=%d\n", PARALLEL);
    if(simstart>=simend) return;
    double restot=0; long rescount=0;
    for(int iseed=0; iseed<parms->sim.nseed; iseed++){
	SIM_T *simu=0;
	while(!(simu=maos_iseed(iseed))){
	    iseed++;
	}
#ifdef HAVE_NUMA_H
	numa_set_localalloc();
#endif
	for(int isim=simstart; isim<simend; isim++){
	    maos_isim(isim);
	    if(parms->sim.pause){
		mypause();
	    }
	}/*isim */
	{
	    /*Compute average performance*/
	    int isim0;
	    if(parms->sim.closeloop){
		if(parms->sim.end>100){
		    isim0=MAX(50,parms->sim.end/10);
		}else{
		    isim0=MIN(20, parms->sim.end/2);
		}
	    }else{
		isim0=0;
	    }
	    double sum=0;
	    for(int i=isim0; i<parms->sim.end; i++){
		sum+=simu->cle->p[i*parms->evl.nmod];
	    }
	    restot+=sum/(parms->sim.end-isim0);
	    rescount++;
	}
	free_simu(simu);
	global->simu=0;
    }/*seed */
    printf("%g\n", sqrt(restot/rescount)*1e9);
}
예제 #13
0
/**
   Setup the least square reconstruct by directly inverting GA matrix. 
   The reconstructor is simply the pseudo inverse of GA matrix:
   \f[\hat{x}=(G_a^TC_g^{-1}G_a)^{-1}G_a^TC_g^{-1}\f]

   This is very close to RR except replacing GX with GA.

   We use the tomograhy parameters for lsr, since lsr is simply "tomography" onto DM directly.
*/
void setup_recon_lsr(RECON_T *recon, const PARMS_T *parms){
    const int ndm=parms->ndm;
    const int nwfs=parms->nwfsr;
    cell *GAlsr;
    cell *GAM=parms->recon.modal?(cell*)recon->GM:(cell*)recon->GA;
    if(parms->recon.split){ //high order wfs only in split mode. 
	GAlsr=parms->recon.modal?(cell*)recon->GMhi:(cell*)recon->GAhi;
    }else{ //all wfs in integrated mode. 
	GAlsr=GAM;
    }
    int free_GAlsr=0;
    if(GAlsr->p[0]->id!=M_DBL){
	dsp *tmp=dsp_cast(GAlsr->p[0]);
	if(tmp->nzmax>tmp->nx*tmp->ny*0.2){//not very sparse
	    dcell *tmp2=0;
	    free_GAlsr=1;
	    dcelladd(&tmp2, 1, (dspcell*)GAlsr, 1);
	    GAlsr=(cell*)tmp2;
	}
    }
    info2("Building recon->LR\n");
    recon->LR.M=dcellmm2(GAlsr, recon->saneai, "tn");
    // Tip/tilt and diff focus removal low rand terms for LGS WFS.
    if(recon->TTF){
	dcellmm(&recon->LR.U, recon->LR.M, recon->TTF, "nn", 1);
	recon->LR.V=dcelltrans(recon->PTTF);
    }
    info2("Building recon->LL\n");
    recon->LL.M=dcellmm2(recon->LR.M, GAlsr, "nn");
    if(free_GAlsr){
	cellfree(GAlsr);
    }
    double maxeig=pow(recon->neamhi * recon->aloc->p[0]->dx, -2);
    if(parms->recon.modal){
	double strength=1;
	for(int idm=0; idm<ndm; idm++){
	    strength*=dnorm(recon->amod->p[idm]);
	}
	strength=pow(strength, 2./ndm);
	maxeig*=strength;
    }
    if(fabs(parms->lsr.tikcr)>EPS){
	info2("Adding tikhonov constraint of %g to LLM\n", parms->lsr.tikcr);
	info2("The maximum eigen value is estimated to be around %g\n", maxeig);
	dcelladdI(recon->LL.M, parms->lsr.tikcr*maxeig);
    }
    dcell *NW=NULL;
    if(!parms->recon.modal){
	if(parms->lsr.alg!=2){
	    /* Not SVD, need low rank terms for piston/waffle mode constraint. */
	    NW=dcellnew(ndm,1);
	    int nmod=2;/*two modes. */
	    for(int idm=0; idm<ndm; idm++){
		loc_create_map(recon->aloc->p[idm]);
		const long nloc=recon->aloc->p[idm]->nloc;
		NW->p[idm]=dnew(nloc, ndm*nmod);
		double *p=NW->p[idm]->p+nmod*idm*nloc;
		const double *cpl=recon->actcpl->p[idm]->p;
		for(long iloc=0; iloc<nloc; iloc++){
		    if(cpl[iloc]>0.1){
			p[iloc]=1;/*piston mode */
		    }
		}
		/*notice offset of 1 because map start count at 1 */
		p=NW->p[idm]->p+(1+nmod*idm)*nloc-1;
		map_t *map=recon->aloc->p[idm]->map;
		for(long iy=0; iy<map->ny; iy++){
		    for(long ix=0; ix<map->nx; ix++){
			if(IND(map,ix,iy)){
			    p[(long)IND(map,ix,iy)]=(double)2*((iy+ix)&1)-1;
			}
		    }
		}
	    }
	    /*scale it to match the magnitude of LL.M */
	    dcellscale(NW, sqrt(maxeig));
	    if(parms->save.setup){
		writebin(NW, "lsrNW");
	    }
	}
	if(parms->lsr.actslave){
	    /*actuator slaving. important. change from 0.5 to 0.1 on 2011-07-14. */
	    dspcell *actslave=slaving(recon->aloc, recon->actcpl, NW,
				      recon->actstuck, recon->actfloat, parms->lsr.actthres, maxeig);
	    if(parms->save.setup){
		if(NW){
		    writebin(NW, "lsrNW2");
		}
		writebin(actslave,"actslave");
	    }
	    dcelladd(&recon->LL.M, 1, actslave, 1);
	    cellfree(actslave);
	}
    }
    /*Low rank terms for low order wfs. Only in Integrated tomography. */
    dcell *ULo=dcellnew(ndm,nwfs);
    dcell *VLo=dcellnew(ndm,nwfs);
    dcell*  pULo=ULo/*PDELL*/;
    dcell*  pVLo=VLo/*PDELL*/;
    for(int iwfs=0; iwfs<nwfs; iwfs++){
	int ipowfs=parms->wfsr[iwfs].powfs;
	if(parms->powfs[ipowfs].skip || !parms->powfs[ipowfs].lo){
	    continue;
	}
	for(int idm=0; idm<ndm; idm++){
	    dspfull(PIND(pULo,idm,iwfs), (dsp*)IND(recon->LR.M, idm, iwfs),'n',-1);
	    dspfull(PIND(pVLo,idm,iwfs), (dsp*)IND(GAM, iwfs, idm),'t',1);
	}
    }
    recon->LL.U=dcellcat(recon->LR.U, ULo, 2);
    dcell *GPTTDF=NULL;
    dcellmm(&GPTTDF, GAM, recon->LR.V, "tn", 1);
    recon->LL.V=dcellcat(GPTTDF, VLo, 2);
    dcellfree(GPTTDF);
    dcellfree(ULo);
    dcellfree(VLo);
    if(!parms->recon.modal && NW){
	info2("Create piston and check board modes that are in NULL space of GA.\n");
	/*add to low rank terms. */
	dcell *tmp=recon->LL.U;
	recon->LL.U=dcellcat(tmp, NW, 2);
	dcellfree(tmp);
	dcellscale(NW, -1);
	tmp=recon->LL.V;
	recon->LL.V=dcellcat(tmp, NW, 2);
	dcellfree(tmp);
	dcellfree(NW);
    }
    if(parms->lsr.fnreg){
	warning("Loading LSR regularization from file %s.\n", parms->lsr.fnreg);
	dspcell *tmp=dspcellread("%s", parms->lsr.fnreg);
	dcelladd(&recon->LL.M, 1, tmp, 1);
	dspcellfree(tmp);
    }
    recon->LL.alg = parms->lsr.alg;
    recon->LL.bgs = parms->lsr.bgs;
    recon->LL.warm = parms->recon.warm_restart;
    recon->LL.maxit = parms->lsr.maxit;
    /*Remove empty cells. */
    dcelldropempty(&recon->LR.U,2);
    dcelldropempty(&recon->LR.V,2);
    dcelldropempty(&recon->LL.U,2);
    dcelldropempty(&recon->LL.V,2);
    if(parms->save.recon){
	writebin(recon->LR.M,"LRM");
	writebin(recon->LR.U,"LRU");
	writebin(recon->LR.V,"LRV");
	writebin(recon->LL.M,"LLM.bin");/*disable compression */
	writebin(recon->LL.U,"LLU");
	writebin(recon->LL.V,"LLV"); 
    }
    if(parms->lsr.alg==0 || parms->lsr.alg==2){
	if(!parms->lsr.bgs){
	    muv_direct_prep(&recon->LL, (parms->lsr.alg==2)*parms->lsr.svdthres);
	    if(parms->save.recon){
		if(recon->LL.C)
		    chol_save(recon->LL.C, "LLC.bin");
		else
		    writebin(recon->LL.MI, "LLMI.bin");
	    }
	    cellfree(recon->LL.M);
	    dcellfree(recon->LL.U);
	    dcellfree(recon->LL.V);	
	}else{
	    muv_direct_diag_prep(&(recon->LL), (parms->lsr.alg==2)*parms->lsr.svdthres);
	    if(parms->save.recon){
		for(int ib=0; ib<recon->LL.nb; ib++){
		    if(recon->LL.CB)
			chol_save(recon->LL.CB[ib],"LLCB_%d.bin", ib);
		    else
			writebin(recon->LL.MI,"LLMIB_%d.bin", ib);
		}
	    }
	    /*Don't free M, U, V */
	}
    }
}
예제 #14
0
/**
   Setup the detector transfer functions. See maos/setup_powfs.c
 */
static void setup_powfs_dtf(POWFS_S *powfs, const PARMS_S* parms){
    const int npowfs=parms->maos.npowfs;
    for(int ipowfs=0; ipowfs<npowfs; ipowfs++){
	const int ncomp=parms->maos.ncomp[ipowfs];
	const int ncomp2=ncomp>>1;
	const int embfac=parms->maos.embfac[ipowfs];
	const int pixpsa=parms->skyc.pixpsa[ipowfs];
	const double pixtheta=parms->skyc.pixtheta[ipowfs];
	const double blur=parms->skyc.pixblur[ipowfs]*pixtheta;
	const double e0=exp(-2*M_PI*M_PI*blur*blur);
	const double dxsa=parms->maos.dxsa[ipowfs];
	const double pixoffx=parms->skyc.pixoffx[ipowfs];
	const double pixoffy=parms->skyc.pixoffy[ipowfs];
	const double pxo=-(pixpsa/2-0.5+pixoffx)*pixtheta;
	const double pyo=-(pixpsa/2-0.5+pixoffy)*pixtheta;
	loc_t *loc_ccd=mksqloc(pixpsa, pixpsa, pixtheta, pixtheta, pxo, pyo);
	powfs[ipowfs].dtf=mycalloc(parms->maos.nwvl,DTF_S);
	for(int iwvl=0; iwvl<parms->maos.nwvl; iwvl++){
	    const double wvl=parms->maos.wvl[iwvl];
	    const double dtheta=wvl/(dxsa*embfac);
	    const double pdtheta=pixtheta*pixtheta/(dtheta*dtheta);
	    const double du=1./(dtheta*ncomp);
	    const double du2=du*du;
	    const double dupth=du*pixtheta;
	    cmat *nominal=cnew(ncomp,ncomp);
	    //cfft2plan(nominal,-1);
	    //cfft2plan(nominal,1);
	    cmat* pn=nominal;
	    const double theta=0;
	    const double ct=cos(theta);
	    const double st=sin(theta);
	    for(int iy=0; iy<ncomp; iy++){
		int jy=iy-ncomp2;
		for(int ix=0; ix<ncomp; ix++){
		    int jx=ix-ncomp2;
		    double ir=ct*jx+st*jy;
		    double ia=-st*jx+ct*jy;
		    IND(pn,ix,iy)=sinc(ir*dupth)*sinc(ia*dupth)
			*pow(e0,ir*ir*du2)*pow(e0,ia*ia*du2)
			*pdtheta;
		}
	    }
	    if(parms->skyc.fnpsf1[ipowfs]){
		warning("powfs %d has additional otf to be multiplied\n", ipowfs);
		dcell *psf1c=dcellread("%s", parms->skyc.fnpsf1[ipowfs]);
		dmat *psf1=NULL;
		if(psf1c->nx == 1){
		    psf1=dref(psf1c->p[0]);
		}else if(psf1c->nx==parms->maos.nwvl){
		    psf1=dref(psf1c->p[iwvl]);
		}else{
		    error("skyc.fnpsf1 has wrong dimension\n");
		}
		dcellfree(psf1c);
		if(psf1->ny!=2){
		    error("skyc.fnpsf1 has wrong dimension\n");
		}
		dmat *psf1x=dnew_ref(psf1->nx, 1, psf1->p);
		dmat *psf1y=dnew_ref(psf1->nx, 1, psf1->p+psf1->nx);
		dmat *psf2x=dnew(ncomp*ncomp, 1);
		for(int iy=0; iy<ncomp; iy++){
		    int jy=iy-ncomp2;
		    for(int ix=0; ix<ncomp; ix++){
			int jx=ix-ncomp2;
			psf2x->p[ix+iy*ncomp]=sqrt(jx*jx+jy*jy)*dtheta;
		    }
		}
		info("powfs %d, iwvl=%d, dtheta=%g\n", ipowfs, iwvl, dtheta*206265000);
		writebin(psf2x, "powfs%d_psf2x_%d", ipowfs,iwvl);
		dmat *psf2=dinterp1(psf1x, psf1y, psf2x, 0);
		normalize_sum(psf2->p, psf2->nx*psf2->ny, 1);
		psf2->nx=ncomp; psf2->ny=ncomp;
		writebin(psf2, "powfs%d_psf2_%d", ipowfs,iwvl);
		cmat *otf2=cnew(ncomp, ncomp);
		//cfft2plan(otf2, -1);
		ccpd(&otf2, psf2);//peak in center
		cfftshift(otf2);//peak in corner
		cfft2(otf2, -1);
		cfftshift(otf2);//peak in center
		writebin(otf2, "powfs%d_otf2_%d", ipowfs, iwvl);
		writebin(nominal, "powfs%d_dtf%d_nominal_0",ipowfs,iwvl);
		for(int i=0; i<ncomp*ncomp; i++){
		    nominal->p[i]*=otf2->p[i];
		}
		writebin(nominal, "powfs%d_dtf%d_nominal_1",ipowfs,iwvl);
		dfree(psf1x);
		dfree(psf1y);
		dfree(psf2x);
		dfree(psf1);
		cfree(otf2);
		dfree(psf2);
	    }
	    cfftshift(nominal);//peak in corner
	    cfft2(nominal,-1);
	    cfftshift(nominal);//peak in center
	    cfft2i(nominal,1);
	    warning_once("double check nominal for off centered skyc.fnpsf1\n");
	    /*This nominal will multiply to OTF with peak in corner. But after
	      inverse fft, peak will be in center*/
	    ccp(&powfs[ipowfs].dtf[iwvl].nominal, nominal);
	    cfree(nominal);

	    loc_t *loc_psf=mksqloc(ncomp, ncomp, dtheta, dtheta, -ncomp2*dtheta, -ncomp2*dtheta);
	    powfs[ipowfs].dtf[iwvl].si=mkh(loc_psf,loc_ccd,0,0,1);
	    locfree(loc_psf);
	    if(parms->skyc.dbg){
		writebin(powfs[ipowfs].dtf[iwvl].nominal,
		       "%s/powfs%d_dtf%d_nominal",dirsetup,ipowfs,iwvl);
		writebin(powfs[ipowfs].dtf[iwvl].si,
			"%s/powfs%d_dtf%d_si",dirsetup,ipowfs,iwvl);
	    }
	    powfs[ipowfs].dtf[iwvl].U=cnew(ncomp,1);
	    dcomplex *U=powfs[ipowfs].dtf[iwvl].U->p;

	    for(int ix=0; ix<ncomp; ix++){
		int jx=ix<ncomp2?ix:(ix-ncomp);
		U[ix]=COMPLEX(0, -2.*M_PI*jx*du);
	    }
	}/*iwvl */
	locfree(loc_ccd);
    }/*ipowfs */
}
예제 #15
0
파일: filter.c 프로젝트: bitursa/maos
/**
   Update DM command for next cycle using info from last cycle (two cycle delay)
in closed loop mode */
static void filter_cl(SIM_T *simu){
    /*
      2009-11-02: Moved to the end of isim loop to update
      for next step.  only need to cache a single dmerrlast
      now.

      2009-12-23: Updated low fs to do lead filter/type II
      
      2010-01-07: Create an option to merge the last
      integrator in the hi/lo loop to simulation the actual
      block diagram. removed dmreal_hi, Mreal_lo;
      
      2010-01-08: Changed the filtering scheme by computing
      dm command for next cycle instead of maintianing last
      step error information.

      2010-01-13: Implemented apdm. 
      a(n)=a(n-1)+ep*e(n-2) or 
      a(n)=0.5*(a(n-1)+a(n-2))+ep*e(n-2);
    */
    const PARMS_T *parms=simu->parms;
    RECON_T *recon=simu->recon;
    assert(parms->sim.closeloop);
    /*copy dm computed in last cycle. This is used in next cycle (already after perfevl) */
    const SIM_CFG_T *simcfg=&(parms->sim);
    const int isim=simu->isim;
    {/*Auto adjusting epdm for testing different epdm*/
    	static int epdm_is_auto=0;
	if(simcfg->epdm->p[0]<0){
	    epdm_is_auto=1;
	    simcfg->epdm->p[0]=0.5;
	}
	if(epdm_is_auto){
	    if((isim*10)<parms->sim.end){//initial steps
		simcfg->epdm->p[0]=0.5;
	    }else if((isim*10)%parms->sim.end==0){
		simcfg->epdm->p[0]=(double)isim/(double)parms->sim.end;
		info("epdm is set to %.1f at step %d\n", simcfg->epdm->p[0], isim);
	    }
	}
    }
    
    /*Do the servo filtering. First simulate a drop frame*/
    int drop=0;
    if(simu->dmerr && parms->sim.dtrat_skip){
	if(parms->sim.dtrat_skip>0){
	    if((isim+1)%parms->sim.dtrat_skip==0){//evenly
		drop=1;
	    }
	}else if(parms->sim.dtrat_skip<0){//use random draws
	    double tmp=randu(simu->misc_rand);
	    if(tmp*(-parms->sim.dtrat_skip)<1.){
		drop=1;
	    }
	}
    }
    dcell *dmerr=0;
    if(drop){
	warning("Drop a frame at step %d\n", isim);
    }else if(simu->dmerr){
	dmerr=simu->dmerr;
    }
    //always run servo_filter even if dmerr is NULL.
    int hiout=servo_filter(simu->dmint, dmerr);
    if(parms->recon.split){ 
	/*Low order in split tomography only. fused integrator*/
	if(servo_filter(simu->Mint_lo, simu->Merr_lo) && parms->sim.fuseint){
	    /*accumulate to the main integrator.*/
	    addlow2dm(&simu->dmint->mint->p[0], simu, simu->Mint_lo->mpreint, 1);
	}
    }
    /*The following are moved from the beginning to the end because the
      gradients are now from last step.*/
    dcellcp(&simu->dmcmd0,simu->dmint->mint->p[0]);
    if(!parms->sim.fuseint){
	addlow2dm(&simu->dmcmd0,simu,simu->Mint_lo->mint->p[0], 1);
    }
    for(int ipowfs=0; ipowfs<parms->npowfs; ipowfs++){
	//Record dmpsol for this time step for each powfs before updating it (z^-1).
	//Do not reference the data, even for dtrat==1
	if(!parms->powfs[ipowfs].psol || !parms->powfs[ipowfs].dtrat) continue;
	double alpha=(isim % parms->powfs[ipowfs].dtrat == 0)?0:1;
	dcelladd(&simu->wfspsol->p[ipowfs], alpha, simu->dmpsol, 1./parms->powfs[ipowfs].dtrat);
    }
    dcellcp(&simu->dmpsol, simu->dmcmd0);
    if(parms->recon.modal){
	dcellzero(simu->dmcmd);
	dcellmm(&simu->dmcmd, simu->recon->amod, simu->dmcmd0, "nn", 1);
	//convert DM command from modal to zonal spae
    }else if(simu->recon->actinterp && !parms->recon.psol){
	//Extrapolate to edge actuators
	dcellzero(simu->dmcmd);
	dcellmm(&simu->dmcmd, simu->recon->actinterp, simu->dmcmd0, "nn", 1);
    }else{
	dcellcp(&simu->dmcmd, simu->dmcmd0);
    }
    
    //The DM commands are always on zonal modes from this moment

    if(simu->ttmreal){
	ttsplit_do(recon, simu->dmcmd, simu->ttmreal, parms->sim.lpttm);
    }
    if(parms->sim.focus2tel && hiout){
	dcellcp(&simu->telfocusreal, simu->telfocusint);
	dcellmm(&simu->telfocusint, recon->RFdm, simu->dmcmd, "nn", parms->sim.epfocus2tel);
    }
    if(recon->dither_m){
	//Change phase in calc_dither_amp if phase of dithering is changed
	//this is for step isim+1
	double anglei=((isim+1)/recon->dither_dtrat)*(2*M_PI/recon->dither_npoint);
	dcelladd(&simu->dmcmd, 1, recon->dither_m, sin(anglei));
    }

    if(!parms->dbg.ncpa_preload && recon->dm_ncpa){
	info_once("Add NCPA after integrator\n");
	dcelladd(&simu->dmcmd, 1, recon->dm_ncpa, 1);
    }
    if(parms->sim.dmclip || parms->sim.dmclipia || recon->actstuck){
	dcell *tmp=dcelldup(simu->dmcmd);
	if(recon->actstuck){//zero stuck actuators
	    act_stuck_cmd(recon->aloc, simu->dmerr, recon->actstuck);
	}
	clipdm(simu, simu->dmcmd);
	dcelladd(&tmp, 1, simu->dmcmd, -1); //find what is clipped
	dcelladd(&simu->dmint->mint->p[0], 1, tmp, -1);//remove from integrator (anti wind up)
	dcelladd(&simu->dmpsol, 1, tmp, -1);//also feed to PSOL (is this really necessary?)
	dcellfree(tmp);
    }
    /*This is after the integrator output and clipping*/
    if(simu->dmhist){
	for(int idm=0; idm<parms->ndm; idm++){
	    if(simu->dmhist->p[idm]){
		dhistfill(&simu->dmhist->p[idm], simu->dmcmd->p[idm],0,
			  parms->dm[idm].histbin, parms->dm[idm].histn);
	    }
	}
    }
   
    /*hysteresis. */
    if(simu->hyst){
	hyst_dcell(simu->hyst, simu->dmreal, simu->dmcmd);
    }
    
    if(recon->moao && !parms->gpu.moao){
	warning_once("moao filter implemented with LPF\n");
	if(simu->dm_wfs){
	    const int nwfs=parms->nwfs;
	    for(int iwfs=0; iwfs<nwfs; iwfs++){
		int ipowfs=parms->wfs[iwfs].powfs;
		int imoao=parms->powfs[ipowfs].moao;
		if(imoao<0) continue;
		double g=parms->moao[imoao].gdm;
		dadd(&simu->dm_wfs->p[iwfs], 1-g, simu->dm_wfs->p[iwfs+nwfs], g);
	    }
	}
	if(simu->dm_evl){
	    const int nevl=parms->evl.nevl;
	    int imoao=parms->evl.moao;
	    double g=parms->moao[imoao].gdm;
	    for(int ievl=0; ievl<nevl; ievl++){
		dadd(&simu->dm_evl->p[ievl], 1-g, simu->dm_evl->p[ievl+nevl], g);
	    }
	}
    }
    if(simu->fsmint){
	/*fsmerr is from gradients from this time step. so copy before update for correct delay*/
	dcellcp(&simu->fsmreal, simu->fsmint->mint->p[0]);
	servo_filter(simu->fsmint, simu->fsmerr);
	/*Inject dithering command, for step isim+1*/
	for(int iwfs=0; iwfs<parms->nwfs; iwfs++){
	    const int ipowfs=parms->wfs[iwfs].powfs;
	    if(parms->powfs[ipowfs].dither==1){//T/T dithering.
		//adjust delay due to propagation, and computation delay.
		const int adjust=parms->sim.alfsm+1-parms->powfs[ipowfs].dtrat;
		//Use isim+1 because the command is for next time step.
		//minus adjust for delay
		double anglei=(2*M_PI/parms->powfs[ipowfs].dither_npoint);
		double angle=((isim+1-adjust)/parms->powfs[ipowfs].dtrat)*anglei;
		simu->fsmreal->p[iwfs]->p[0]-=parms->powfs[ipowfs].dither_amp*cos(angle);
		simu->fsmreal->p[iwfs]->p[1]-=parms->powfs[ipowfs].dither_amp*sin(angle);
	    }
	}
    }
}
예제 #16
0
/**
   Time domain physical simulation.
   
   noisy: 
   - 0: no noise at all; 
   - 1: poisson and read out noise. 
   - 2: only poisson noise.   
*/
dmat *skysim_sim(dmat **mresout, const dmat *mideal, const dmat *mideal_oa, double ngsol, 
		 ASTER_S *aster, const POWFS_S *powfs, 
		 const PARMS_S *parms, int idtratc, int noisy, int phystart){
    int dtratc=0;
    if(!parms->skyc.multirate){
	dtratc=parms->skyc.dtrats->p[idtratc];
    }
    int hasphy;
    if(phystart>-1 && phystart<aster->nstep){
	hasphy=1;
    }else{
	hasphy=0;
    }
    const int nmod=mideal->nx;
    dmat *res=dnew(6,1);/*Results. 1-2: NGS and TT modes., 
			  3-4:On axis NGS and TT modes,
			  4-6: On axis NGS and TT wihtout considering un-orthogonality.*/
    dmat *mreal=NULL;/*modal correction at this step. */
    dmat *merr=dnew(nmod,1);/*modal error */
    dcell *merrm=dcellnew(1,1);dcell *pmerrm=NULL;
    const int nstep=aster->nstep?aster->nstep:parms->maos.nstep;
    dmat *mres=dnew(nmod,nstep);
    dmat* rnefs=parms->skyc.rnefs;
    dcell *zgradc=dcellnew3(aster->nwfs, 1, aster->ngs, 0);
    dcell *gradout=dcellnew3(aster->nwfs, 1, aster->ngs, 0);
    dmat *gradsave=0;
    if(parms->skyc.dbg){
	gradsave=dnew(aster->tsa*2,nstep);
    }
   
    
    SERVO_T *st2t=0;
    kalman_t *kalman=0;
    dcell *mpsol=0;
    dmat *pgm=0;
    dmat *dtrats=0;
    int multirate=parms->skyc.multirate;
    if(multirate){
	kalman=aster->kalman[0];
	dtrats=aster->dtrats;
    }else{
	if(parms->skyc.servo>0){
	    const double dtngs=parms->maos.dt*dtratc;
	    st2t=servo_new(merrm, NULL, 0, dtngs, aster->gain->p[idtratc]);
	    pgm=aster->pgm->p[idtratc];
	}else{
	    kalman=aster->kalman[idtratc];
	}
    }
    if(kalman){
	kalman_init(kalman);
	mpsol=dcellnew(aster->nwfs, 1); //for psol grad.
    }
    const long nwvl=parms->maos.nwvl;
    dcell **psf=0, **mtche=0, **ints=0;
    ccell *wvf=0,*wvfc=0, *otf=0;
    if(hasphy){
	psf=mycalloc(aster->nwfs,dcell*);
	wvf=ccellnew(aster->nwfs,1);
	wvfc=ccellnew(aster->nwfs,1);
	mtche=mycalloc(aster->nwfs,dcell*);
	ints=mycalloc(aster->nwfs,dcell*);
	otf=ccellnew(aster->nwfs,1);
    
	for(long iwfs=0; iwfs<aster->nwfs; iwfs++){
	    const int ipowfs=aster->wfs[iwfs].ipowfs;
	    const long ncomp=parms->maos.ncomp[ipowfs];
	    const long nsa=parms->maos.nsa[ipowfs];
	    wvf->p[iwfs]=cnew(ncomp,ncomp);
	    wvfc->p[iwfs]=NULL;
	    psf[iwfs]=dcellnew(nsa,nwvl);
	    //cfft2plan(wvf->p[iwfs], -1);
	    if(parms->skyc.multirate){
		mtche[iwfs]=aster->wfs[iwfs].pistat->mtche[(int)aster->idtrats->p[iwfs]];
	    }else{
		mtche[iwfs]=aster->wfs[iwfs].pistat->mtche[idtratc];
	    }
	    otf->p[iwfs]=cnew(ncomp,ncomp);
	    //cfft2plan(otf->p[iwfs],-1);
	    //cfft2plan(otf->p[iwfs],1);
	    ints[iwfs]=dcellnew(nsa,1);
	    int pixpsa=parms->skyc.pixpsa[ipowfs];
	    for(long isa=0; isa<nsa; isa++){
		ints[iwfs]->p[isa]=dnew(pixpsa,pixpsa);
	    }
	}
    }
    for(int irep=0; irep<parms->skyc.navg; irep++){
	if(kalman){
	    kalman_init(kalman);
	}else{
	    servo_reset(st2t);
	}
	dcellzero(zgradc);
	dcellzero(gradout);
	if(ints){
	    for(int iwfs=0; iwfs<aster->nwfs; iwfs++){
		dcellzero(ints[iwfs]);
	    }
	}
	for(int istep=0; istep<nstep; istep++){
	    memcpy(merr->p, PCOL(mideal,istep), nmod*sizeof(double));
	    dadd(&merr, 1, mreal, -1);/*form NGS mode error; */
	    memcpy(PCOL(mres,istep),merr->p,sizeof(double)*nmod);
	    if(mpsol){//collect averaged modes for PSOL.
		for(long iwfs=0; iwfs<aster->nwfs; iwfs++){
		    dadd(&mpsol->p[iwfs], 1, mreal, 1);
		}
	    }
	    pmerrm=0;
	    if(istep>=parms->skyc.evlstart){/*performance evaluation*/
		double res_ngs=dwdot(merr->p,parms->maos.mcc,merr->p);
		if(res_ngs>ngsol*100){
		    dfree(res); res=NULL;
		    break;
		}
		{
		    res->p[0]+=res_ngs;
		    res->p[1]+=dwdot2(merr->p,parms->maos.mcc_tt,merr->p);
		    double dot_oa=dwdot(merr->p, parms->maos.mcc_oa, merr->p);
		    double dot_res_ideal=dwdot(merr->p, parms->maos.mcc_oa, PCOL(mideal,istep));
		    double dot_res_oa=0;
		    for(int imod=0; imod<nmod; imod++){
			dot_res_oa+=merr->p[imod]*IND(mideal_oa,imod,istep);
		    }
		    res->p[2]+=dot_oa-2*dot_res_ideal+2*dot_res_oa;
		    res->p[4]+=dot_oa;
		}
		{
		    double dot_oa_tt=dwdot2(merr->p, parms->maos.mcc_oa_tt, merr->p);
		    /*Notice that mcc_oa_tt2 is 2x5 marix. */
		    double dot_res_ideal_tt=dwdot(merr->p, parms->maos.mcc_oa_tt2, PCOL(mideal,istep));
		    double dot_res_oa_tt=0;
		    for(int imod=0; imod<2; imod++){
			dot_res_oa_tt+=merr->p[imod]*IND(mideal_oa,imod,istep);
		    }
		    res->p[3]+=dot_oa_tt-2*dot_res_ideal_tt+2*dot_res_oa_tt;
		    res->p[5]+=dot_oa_tt;
		}
	    }//if evl

	    if(istep<phystart || phystart<0){
		/*Ztilt, noise free simulation for acquisition. */
		dmm(&zgradc->m, 1, aster->gm, merr, "nn", 1);/*grad due to residual NGS mode. */
		for(int iwfs=0; iwfs<aster->nwfs; iwfs++){
		    const int ipowfs=aster->wfs[iwfs].ipowfs;
		    const long ng=parms->maos.nsa[ipowfs]*2;
		    for(long ig=0; ig<ng; ig++){
			zgradc->p[iwfs]->p[ig]+=aster->wfs[iwfs].ztiltout->p[istep*ng+ig];
		    }
		}
	
		for(int iwfs=0; iwfs<aster->nwfs; iwfs++){
		    int dtrati=(multirate?(int)dtrats->p[iwfs]:dtratc);
		    if((istep+1) % dtrati==0){
			dadd(&gradout->p[iwfs], 0, zgradc->p[iwfs], 1./dtrati);
			dzero(zgradc->p[iwfs]);
			if(noisy){
			    int idtrati=(multirate?(int)aster->idtrats->p[iwfs]:idtratc);
			    dmat *nea=aster->wfs[iwfs].pistat->sanea->p[idtrati];
			    for(int i=0; i<nea->nx; i++){
				gradout->p[iwfs]->p[i]+=nea->p[i]*randn(&aster->rand);
			    }
			}
			pmerrm=merrm;//record output.
		    }
		}
	    }else{
		/*Accumulate PSF intensities*/
		for(long iwfs=0; iwfs<aster->nwfs; iwfs++){
		    const double thetax=aster->wfs[iwfs].thetax;
		    const double thetay=aster->wfs[iwfs].thetay;
		    const int ipowfs=aster->wfs[iwfs].ipowfs;
		    const long nsa=parms->maos.nsa[ipowfs];
		    ccell* wvfout=aster->wfs[iwfs].wvfout[istep];
		    for(long iwvl=0; iwvl<nwvl; iwvl++){
			double wvl=parms->maos.wvl[iwvl];
			for(long isa=0; isa<nsa; isa++){
			    ccp(&wvfc->p[iwfs], IND(wvfout,isa,iwvl));
			    /*Apply NGS mode error to PSF. */
			    ngsmod2wvf(wvfc->p[iwfs], wvl, merr, powfs+ipowfs, isa,
				       thetax, thetay, parms);
			    cembedc(wvf->p[iwfs],wvfc->p[iwfs],0,C_FULL);
			    cfft2(wvf->p[iwfs],-1);
			    /*peak in corner. */
			    cabs22d(&psf[iwfs]->p[isa+nsa*iwvl], 1., wvf->p[iwfs], 1.);
			}/*isa */
		    }/*iwvl */
		}/*iwfs */
	
		/*Form detector image from accumulated PSFs*/
		double igrad[2];
		for(long iwfs=0; iwfs<aster->nwfs; iwfs++){
		    int dtrati=dtratc, idtrat=idtratc;
		    if(multirate){//multirate
			idtrat=aster->idtrats->p[iwfs];
			dtrati=dtrats->p[iwfs];
		    }
		    if((istep+1) % dtrati == 0){/*has output */
			dcellzero(ints[iwfs]);
			const int ipowfs=aster->wfs[iwfs].ipowfs;
			const long nsa=parms->maos.nsa[ipowfs];
			for(long isa=0; isa<nsa; isa++){
			    for(long iwvl=0; iwvl<nwvl; iwvl++){
				double siglev=aster->wfs[iwfs].siglev->p[iwvl];
				ccpd(&otf->p[iwfs],psf[iwfs]->p[isa+nsa*iwvl]);
				cfft2i(otf->p[iwfs], 1); /*turn to OTF, peak in corner */
				ccwm(otf->p[iwfs], powfs[ipowfs].dtf[iwvl].nominal);
				cfft2(otf->p[iwfs], -1);
				dspmulcreal(ints[iwfs]->p[isa]->p, powfs[ipowfs].dtf[iwvl].si, 
					   otf->p[iwfs]->p, siglev);
			    }
		
			    /*Add noise and apply matched filter. */
#if _OPENMP >= 200805 
#pragma omp critical 
#endif
			    switch(noisy){
			    case 0:/*no noise at all. */
				break;
			    case 1:/*both poisson and read out noise. */
				{
				    double bkgrnd=aster->wfs[iwfs].bkgrnd*dtrati;
				    addnoise(ints[iwfs]->p[isa], &aster->rand, bkgrnd, bkgrnd, 0,0,IND(rnefs,idtrat,ipowfs));
				}
				break;
			    case 2:/*there is still poisson noise. */
				addnoise(ints[iwfs]->p[isa], &aster->rand, 0, 0, 0,0,0);
				break;
			    default:
				error("Invalid noisy\n");
			    }
		
			    igrad[0]=0;
			    igrad[1]=0;
			    double pixtheta=parms->skyc.pixtheta[ipowfs];
			    if(parms->skyc.mtch){
				dmulvec(igrad, mtche[iwfs]->p[isa], ints[iwfs]->p[isa]->p, 1);
			    }
			    if(!parms->skyc.mtch || fabs(igrad[0])>pixtheta || fabs(igrad[1])>pixtheta){
				if(!parms->skyc.mtch){
				    warning2("fall back to cog\n");
				}else{
				    warning_once("mtch is out of range\n");
				}
				dcog(igrad, ints[iwfs]->p[isa], 0, 0, 0, 3*IND(rnefs,idtrat,ipowfs), 0); 
				igrad[0]*=pixtheta;
				igrad[1]*=pixtheta;
			    }
			    gradout->p[iwfs]->p[isa]=igrad[0];
			    gradout->p[iwfs]->p[isa+nsa]=igrad[1];
			}/*isa */
			pmerrm=merrm;
			dcellzero(psf[iwfs]);/*reset accumulation.*/
		    }/*if iwfs has output*/
		}/*for wfs*/
	    }/*if phystart */
	    //output to mreal after using it to ensure two cycle delay.
	    if(st2t){//Type I or II control.
		if(st2t->mint->p[0]){//has output.
		    dcp(&mreal, st2t->mint->p[0]->p[0]);
		}
	    }else{//LQG control
		kalman_output(kalman, &mreal, 0, 1);
	    }
	    if(kalman){//LQG control
		int indk=0;
		//Form PSOL grads and obtain index to LQG M
		for(int iwfs=0; iwfs<aster->nwfs; iwfs++){
		    int dtrati=(multirate?(int)dtrats->p[iwfs]:dtratc);
		    if((istep+1) % dtrati==0){
			indk|=1<<iwfs;
			dmm(&gradout->p[iwfs], 1, aster->g->p[iwfs], mpsol->p[iwfs], "nn", 1./dtrati);
			dzero(mpsol->p[iwfs]);
		    }
		}
		if(indk){
		    kalman_update(kalman, gradout->m, indk-1);
		}
	    }else if(st2t){
		if(pmerrm){
		    dmm(&merrm->p[0], 0, pgm, gradout->m, "nn", 1);	
		}
		servo_filter(st2t, pmerrm);//do even if merrm is zero. to simulate additional latency
	    }
	    if(parms->skyc.dbg){
		memcpy(PCOL(gradsave, istep), gradout->m->p, sizeof(double)*gradsave->nx);
	    }
	}/*istep; */
    }
    if(parms->skyc.dbg){
	int dtrati=(multirate?(int)dtrats->p[0]:dtratc);
	writebin(gradsave,"%s/skysim_grads_aster%d_dtrat%d",dirsetup, aster->iaster,dtrati);
	writebin(mres,"%s/skysim_sim_mres_aster%d_dtrat%d",dirsetup,aster->iaster,dtrati);
    }
  
    dfree(mreal);
    dcellfree(mpsol);
    dfree(merr);
    dcellfree(merrm);
    dcellfree(zgradc);
    dcellfree(gradout);
    dfree(gradsave);
    if(hasphy){
	dcellfreearr(psf, aster->nwfs);
	dcellfreearr(ints, aster->nwfs);
        ccellfree(wvf);
	ccellfree(wvfc);
	ccellfree(otf);
	free(mtche);
    }
    servo_free(st2t);
    /*dfree(mres); */
    if(mresout) {
	*mresout=mres;
    }else{
	dfree(mres);
    }
    dscale(res, 1./((nstep-parms->skyc.evlstart)*parms->skyc.navg));
    return res;
}
예제 #17
0
/**
   Setup matched filter for stars.
 */
static void setup_star_mtch(const PARMS_S *parms, POWFS_S *powfs, STAR_S *star, int nstar, dcell**nonlin){
    const long nwvl=parms->maos.nwvl;
    const long npowfs=parms->maos.npowfs;
    dmat* rnefs=parms->skyc.rnefs;
 
    for(int istar=0; istar<nstar; istar++){
	if(!star[istar].idtrat){
	    star[istar].idtrat=dnew(npowfs, 1);
	}
	double radius=sqrt(pow(star[istar].thetax,2)+pow(star[istar].thetay,2));
	int igg=round(radius*206265/parms->maos.ngsgrid);
	//info("radius=%g as, igg=%d\n", radius*206265, igg);
	for(int ipowfs=0; ipowfs<npowfs; ipowfs++){
	    const long nsa=parms->maos.nsa[ipowfs];
	    const long pixpsa=parms->skyc.pixpsa[ipowfs];
	    //size of PSF
	    const double sigma_theta=parms->skyc.wvlmean/parms->maos.dxsa[ipowfs];
	    PISTAT_S *pistat=&star[istar].pistat[ipowfs];
	    pistat->i0=dcellnew(nsa,nwvl);
	    pistat->gx=dcellnew(nsa,nwvl);
	    pistat->gy=dcellnew(nsa,nwvl);
	    
	    pistat->i0s=dcellnew(nsa,1);
	    pistat->gxs=dcellnew(nsa,1);
	    pistat->gys=dcellnew(nsa,1);

	    dcell*  psf=pistat->psf;
	    dcell*  i0=pistat->i0;
	    dcell*  gx=pistat->gx;
	    dcell*  gy=pistat->gy;
	    for(long iwvl=0; iwvl<nwvl; iwvl++){
		for(long isa=0; isa<nsa; isa++){
		    double siglev=star[istar].siglev->p[ipowfs]->p[iwvl];
		    IND(i0,isa,iwvl)=dnew(pixpsa,pixpsa);
		    IND(gx,isa,iwvl)=dnew(pixpsa,pixpsa);
		    IND(gy,isa,iwvl)=dnew(pixpsa,pixpsa);
		    psf2i0gxgy(IND(i0,isa,iwvl),IND(gx,isa,iwvl),IND(gy,isa,iwvl),
			       IND(psf,isa,iwvl),powfs[ipowfs].dtf+iwvl);
		    dadd(&pistat->i0s->p[isa], 1, IND(i0,isa,iwvl), siglev);
		    dadd(&pistat->gxs->p[isa], 1, IND(gx,isa,iwvl), siglev);
		    dadd(&pistat->gys->p[isa], 1, IND(gy,isa,iwvl), siglev);
		}
		 
	    }
	    if(parms->skyc.dbg){
		writebin(pistat->i0s, "%s/star%d_ipowfs%d_i0s", dirsetup,istar,ipowfs);
	    }
	    const double pixtheta=parms->skyc.pixtheta[ipowfs];
	    int ndtrat=parms->skyc.ndtrat;
	    pistat->mtche=mycalloc(ndtrat,dcell*);
	    pistat->sanea=dcellnew(ndtrat,1);
	    pistat->sanea0=dcellnew(ndtrat,1);
	    pistat->snr=dnew(ndtrat,1);
	    dcell *i0s=NULL; dcell *gxs=NULL; dcell *gys=NULL;

	    for(int idtrat=0; idtrat<ndtrat; idtrat++){
		int dtrat=parms->skyc.dtrats->p[idtrat];
		dcelladd(&i0s, 0, pistat->i0s, dtrat);
		dcelladd(&gxs, 0, pistat->gxs, dtrat);
		dcelladd(&gys, 0, pistat->gys, dtrat);
		genmtch(&pistat->mtche[idtrat], &pistat->sanea->p[idtrat],
			i0s, gxs, gys, pixtheta, IND(rnefs,idtrat,ipowfs), 
			star[istar].bkgrnd->p[ipowfs]*dtrat, parms->skyc.mtchcr);
		/*Add nolinearity*/
		if(nonlin){
		    //add linearly not quadratically since the errors are related.
		    dmat *nea_nonlin=dinterp1(nonlin[ipowfs]->p[igg], NULL, pistat->sanea->p[idtrat], 0);
		    for(int i=0; i<nsa*2; i++){
			//info2("%g mas", pistat->sanea->p[idtrat]->p[i]*206265000);
			pistat->sanea->p[idtrat]->p[i]=sqrt(pow(pistat->sanea->p[idtrat]->p[i],2)
							    +pow(nea_nonlin->p[i],2));
			//info2("-->%g mas\n", pistat->sanea->p[idtrat]->p[i]*206265000);
		    }
		    dfree(nea_nonlin);
		}
		dcp(&pistat->sanea0->p[idtrat], pistat->sanea->p[idtrat]);
		if(parms->skyc.neaaniso){
		    for(int i=0; i<nsa*2; i++){
			pistat->sanea->p[idtrat]->p[i]=sqrt(pow(pistat->sanea->p[idtrat]->p[i],2)
							    +pow(star[istar].pistat[ipowfs].neaspec->p[i]->p[idtrat], 2));
		    }
		}
		if(parms->skyc.dbg){
		    writebin(pistat->mtche[idtrat], "%s/star%d_ipowfs%d_mtche_dtrat%d",
			       dirsetup,istar,ipowfs,dtrat);
		}
#if 1
		double nea=sqrt(dsumsq(pistat->sanea->p[idtrat])/(nsa*2));
#else
		double nea=dmax(pistat->sanea->p[idtrat]);
#endif
		double snr=sigma_theta/nea;
		pistat->snr->p[idtrat]=snr;
		if(parms->skyc.verbose) info2("dtrat=%3d, nea=%4.1f, snr=%4.1f\n",
					      (int)parms->skyc.dtrats->p[idtrat], nea*206265000, snr);
		if(snr>parms->skyc.snrmin->p[parms->skyc.snrmin->nx==1?0:idtrat]){
		    star[istar].idtrat->p[ipowfs]=idtrat;
		}
	    }//for idtrat
	    if(parms->skyc.dbg){
		info2("star %2d optim: powfs %1d: dtrat=%3d\n", istar, ipowfs,
		      (int)parms->skyc.dtrats->p[(int)star[istar].idtrat->p[ipowfs]]);
		writebin(pistat->sanea, "%s/star%d_ipowfs%d_sanea",
			   dirsetup,istar,ipowfs);
	    }/*idtrat */
	    dcellfree(i0s);
	    dcellfree(gxs);
	    dcellfree(gys);
	}/*for istar */
    }/*for ipowfs */
}
예제 #18
0
/**
   Save NGS WFS and other information for later use in MAOS simulations.*/
void skysim_save(const SIM_S *simu, const ASTER_S *aster, const double *ipres, int selaster, int seldtrat, int isky){
    const PARMS_S* parms=simu->parms;
    const int nwvl=parms->maos.nwvl;
    char path[PATH_MAX];
    snprintf(path,PATH_MAX,"Res%d_%d_maos/sky%d",simu->seed_maos,parms->skyc.seed,isky);
    mymkdir("%s",path);
    for(int iwfs=0; iwfs<aster[selaster].nwfs; iwfs++){
	dcell *sepsf=dcelldup(aster[selaster].wfs[iwfs].pistat->psf);
	for(int ic=0; ic<sepsf->nx*sepsf->ny; ic++){
	    dfftshift(sepsf->p[ic]);/*put peak in center. required by MAOS. */
	}
	writebin(sepsf, "%s/pistat_wfs%d",path,iwfs+6);
	dcellfree(sepsf);
	writebin(aster->wfs[iwfs].pistat->sanea->p[seldtrat], "%s/nea_tot_wfs%d",path,iwfs+6);
	writebin(aster[selaster].wfs[iwfs].pistat->sanea->p[seldtrat], 
	       "%s/nea_wfs%d",path,iwfs+6);
	writebin(aster[selaster].wfs[iwfs].pistat->sanea, 
		   "%s/neafull_wfs%d",path,iwfs+6);
    }
    writebin(aster[selaster].gain->p[seldtrat], "%s/gain",path);
    writebin(simu->mres->p[isky], "%s/mres",path);
    writebin(simu->psd_tt,"%s/psd_tt",path);
    writebin(simu->psd_ps,"%s/psd_ps",path);
    char fnconf[PATH_MAX];
    snprintf(fnconf,PATH_MAX,"%s/base.conf",path);
    FILE *fp=fopen(fnconf,"w");

    fprintf(fp,"sim.seeds=[%d]\n",simu->seed_maos);
    fprintf(fp,"sim.end=%d\n", parms->maos.nstep);
    fprintf(fp,"sim.dt=%g\n", parms->maos.dt);
    fprintf(fp,"sim.zadeg=%g\n", parms->maos.zadeg);
    fprintf(fp,"sim.mffocus=%d\n", parms->maos.mffocus);
    fprintf(fp,"sim.ahstfocus=%d\n", parms->maos.ahstfocus);
    fprintf(fp,"tomo.ahst_wt=3\n");
    fprintf(fp,"sim.servotype_lo=2\n");/*type II */
    fprintf(fp,"sim.eplo='gain.bin'\n");
    fprintf(fp,"powfs0_llt.fnrange='%s'\n", parms->maos.fnrange);
    fprintf(fp,"atm.r0z=%.4f\n", parms->maos.r0z);
    fprintf(fp,"atm.size=[128 128]\n");
    if(parms->maos.wddeg){
	fprintf(fp, "atm.wddeg=[");
	for(int ips=0; ips<parms->maos.nwddeg; ips++){
	    fprintf(fp, "%.2f ", parms->maos.wddeg[ips]);
	}
	fprintf(fp, "]\n");
    }
    fprintf(fp,"wfs.thetax=[0 0  -33.287 -20.5725  20.5725 33.287");
    for(int iwfs=0; iwfs<aster[selaster].nwfs; iwfs++){
	fprintf(fp," %.4f", aster[selaster].wfs[iwfs].thetax*206265);
    }
    fprintf(fp,"]\n");
    fprintf(fp,"wfs.thetay=[0 35 10.8156 -28.3156 -28.3156 10.8156");
    for(int iwfs=0; iwfs<aster[selaster].nwfs; iwfs++){
	fprintf(fp," %.4f", aster[selaster].wfs[iwfs].thetay*206265);
    }
    fprintf(fp,"]\n");

    fprintf(fp,"wfs.siglev=[900 900 900 900 900 900");
    for(int iwfs=0; iwfs<aster[selaster].nwfs; iwfs++){
	fprintf(fp, " %.2f", aster[selaster].wfs[iwfs].siglevtot);
    }
    fprintf(fp,"]\n");
    fprintf(fp,"wfs.wvlwts=[1 1 1 1 1 1");
    for(int iwfs=0; iwfs<aster[selaster].nwfs; iwfs++){
	for(int iwvl=0; iwvl<nwvl; iwvl++){
	    fprintf(fp," %.2f ", aster[selaster].wfs[iwfs].siglev->p[iwvl]
		    /aster[selaster].wfs[iwfs].siglevtot);
	}
    }
    fprintf(fp,"]\n");
    fprintf(fp,"wfs.powfs=[0 0 0 0 0 0");
    for(int iwfs=0; iwfs<aster[selaster].nwfs; iwfs++){
	fprintf(fp, " %d", aster[selaster].wfs[iwfs].ipowfs+1);
    }
    fprintf(fp,"]\n");

    dmat* rnefs=parms->skyc.rnefs;
    double rne=IND(rnefs,seldtrat,0);
    double bkgrnd=aster[selaster].wfs[0].bkgrnd;

    if(parms->maos.npowfs==1){
	fprintf(fp, "powfs.piinfile=[\"\" \"pistat\" ]\n");
	fprintf(fp, "powfs.neareconfile=[\"\" \"nea_tot\"]\n");
	fprintf(fp, "powfs.phyusenea=[0 1]\n");
	fprintf(fp, "powfs.dtrat=[1 %d]\n", (int)parms->skyc.dtrats->p[seldtrat]);
	fprintf(fp, "powfs.bkgrnd=[0 %.2f]\n", bkgrnd);
	fprintf(fp, "powfs.rne=[3 %.2f]\n", rne);
	fprintf(fp, "powfs.phystep=[0 %ld]\n", 50+(long)parms->skyc.dtrats->p[seldtrat]*20);
	fprintf(fp, "powfs.noisy=[1 1 ]\n");
	fprintf(fp, "powfs.pixtheta=[0.5/206265 %g/206265000]\n", parms->skyc.pixtheta[1]*206265000);
	fprintf(fp, "powfs.pixpsa=[6 %d]\n", parms->skyc.pixpsa[0]);
	fprintf(fp, "powfs.ncomp=[64 %d]\n", parms->maos.ncomp[0]);
	fprintf(fp, "powfs.nwvl=[1 %d]\n",nwvl);
	fprintf(fp, "powfs.wvl=[0.589e-6");
	for(int ip=0; ip<1; ip++){
	    for(int iwvl=0; iwvl<nwvl; iwvl++){
		fprintf(fp, " %.4g", parms->maos.wvl[iwvl]);
	    }
	}
	fprintf(fp,"]\n");
    }else if(parms->maos.npowfs==2){
	fprintf(fp, "powfs.piinfile=[\"\" \"pistat\" \"pistat\"]\n");
	fprintf(fp, "powfs.neareconfile=[\"\" \"nea_tot\" \"nea_tot\"]\n");
	fprintf(fp, "powfs.phyusenea=[0 1 1]\n");
	fprintf(fp, "powfs.dtrat=[1 %d %d]\n", (int)parms->skyc.dtrats->p[seldtrat],
		(int)parms->skyc.dtrats->p[seldtrat]);
	fprintf(fp, "powfs.bkgrnd=[0 %.2f %.2f]\n", bkgrnd, bkgrnd);
	fprintf(fp, "powfs.rne=[3 %.2f %.2f]\n", rne,rne);
	fprintf(fp, "powfs.phystep=[0 %ld %ld]\n", 
		50+(long)parms->skyc.dtrats->p[seldtrat]*20, 
		50+(long)parms->skyc.dtrats->p[seldtrat]*20);
	fprintf(fp, "powfs.noisy=[1 1 1]\n");
	fprintf(fp, "powfs.pixtheta=[0.5/206265 %g/206265000 %g/206265000]\n",
		parms->skyc.pixtheta[0]*206265000,
		parms->skyc.pixtheta[1]*206265000);
	fprintf(fp, "powfs.pixpsa=[6 %d %d]\n",
		parms->skyc.pixpsa[0], 
		parms->skyc.pixpsa[1]);
	fprintf(fp, "powfs.ncomp=[64 %d %d]\n", 
		parms->maos.ncomp[0], parms->maos.ncomp[1]);
	fprintf(fp, "powfs.nwvl=[1 %d %d]\n",nwvl,nwvl);
	fprintf(fp, "powfs.wvl=[0.589e-6");
	for(int ip=0; ip<2; ip++){
	    for(int iwvl=0; iwvl<nwvl; iwvl++){
		fprintf(fp, " %.4g", parms->maos.wvl[iwvl]);
	    }
	}
	fprintf(fp,"]\n");
	fprintf(fp, "powfs.wvlwts=[]\n");
    }else{
	error("Fill this out please\n");
    }
 
    fclose(fp);
    snprintf(fnconf,PATH_MAX,"%s/skyres.txt",path);
    fp=fopen(fnconf,"w");
    fprintf(fp, "TotAll\tNGS\tTT\n");
    fprintf(fp, "%g\t%g\t%g\n",
	    sqrt(ipres[0])*1e9, sqrt(ipres[1])*1e9, sqrt(ipres[2])*1e9);
    fclose(fp);
}
예제 #19
0
파일: save.c 프로젝트: bitursa/maos
void save_recon(SIM_T *simu) {
    const PARMS_T *parms=simu->parms;
    const RECON_T *recon=simu->recon;
    if(parms->plot.run) {
        if(parms->recon.alg==0) {
            for(int i=0; simu->opdr && i<simu->opdr->nx; i++) {
                if(simu->opdr->p[i]) {
                    drawopd("opdr", recon->xloc->p[i], simu->opdr->p[i]->p, NULL,
                            "Reconstructed Atmosphere","x (m)","y (m)","opdr %d",i);
                }
            }
            for(int i=0; simu->dmfit && i<simu->dmfit->nx; i++) {
                if(simu->dmfit->p[i]) {
                    drawopd("DM", recon->aloc->p[i], simu->dmfit->p[i]->p,NULL,
                            "DM Fitting Output","x (m)", "y (m)","Fit %d",i);
                }
            }
        }
        if(!parms->recon.modal) {
            for(int idm=0; simu->dmerr && idm<parms->ndm; idm++) {
                if(simu->dmerr->p[idm]) {
                    drawopd("DM",recon->aloc->p[idm], simu->dmerr->p[idm]->p,NULL,
                            "DM Error Signal (Hi)","x (m)","y (m)",
                            "Err Hi %d",idm);
                }
            }
        }
        for(int idm=0; simu->dmerr && idm<parms->ndm; idm++) {
            if(simu->dmint->mint->p[0]->p[idm]) {
                drawopd("DM",recon->aloc->p[idm], simu->dmint->mint->p[0]->p[idm]->p,NULL,
                        "DM Integrator (Hi)","x (m)","y (m)",
                        "Int Hi %d",idm);
            }
        }
        if(simu->dm_wfs) {
            for(int iwfs=0; iwfs<parms->nwfs; iwfs++) {
                int ipowfs=parms->wfs[iwfs].powfs;
                int imoao=parms->powfs[ipowfs].moao;
                if(imoao<0) continue;
                drawopd("moao", recon->moao[imoao].aloc->p[0], simu->dm_wfs->p[iwfs]->p, NULL,
                        "MOAO", "x(m)", "y(m)", "WFS %d", iwfs);
            }
        }
        if(simu->dm_evl) {
            int imoao=parms->evl.moao;
            for(int ievl=0; ievl<parms->evl.nevl && imoao>=0; ievl++) {
                drawopd("moao", recon->moao[imoao].aloc->p[0], simu->dm_evl->p[ievl]->p, NULL,
                        "MOAO", "x(m)", "y(m)", "Evl %d", ievl);
            }
        }
    }
    if(parms->plot.run && simu->Merr_lo) {
        dcell *dmlo=NULL;
        switch(simu->parms->recon.split) {
        case 1:
            ngsmod2dm(&dmlo, recon, simu->Merr_lo, 1);
            break;
        case 2:
            dcellmm(&dmlo, simu->recon->MVModes, simu->Merr_lo, "nn", 1);
            break;
        }
        for(int idm=0; dmlo && idm<parms->ndm; idm++) {
            drawopd("DM",recon->aloc->p[idm], dmlo->p[idm]->p,NULL,
                    "DM Error Signal (Lo)","x (m)","y (m)",
                    "Err Lo %d",idm);
        }
        dcellfree(dmlo);
    }
    if(parms->plot.run && simu->Mint_lo && simu->Mint_lo->mint->p[0]) {
        dcell *dmlo=NULL;
        switch(simu->parms->recon.split) {
        case 1:
            ngsmod2dm(&dmlo, recon, simu->Mint_lo->mint->p[0], 1);
            break;
        case 2:
            dcellmm(&dmlo, simu->recon->MVModes, simu->Mint_lo->mint->p[0], "nn", 1);
            break;
        }
        for(int idm=0; dmlo && idm<parms->ndm; idm++) {
            drawopd("DM",recon->aloc->p[idm], dmlo->p[idm]->p,NULL,
                    "DM Integrator (Lo)","x (m)","y (m)",
                    "Int Lo %d",idm);
        }
        dcellfree(dmlo);
    }
    if(parms->recon.alg==0) { /*minimum variance tomo/fit reconstructor */
        if(parms->save.opdr) {
            cellarr_dcell(simu->save->opdr, simu->reconisim, simu->opdr);
        }
        if(parms->save.opdx || parms->plot.opdx) {
            dcell *opdx=simu->opdx;
            if(!opdx) {
                atm2xloc(&opdx, simu);
            }
            if(parms->save.opdx) {
                cellarr_dcell(simu->save->opdx, simu->isim, opdx);
            }
            if(parms->plot.opdx) { /*draw opdx */
                for(int i=0; i<opdx->nx; i++) {
                    if(opdx->p[i]) {
                        drawopd("opdx", recon->xloc->p[i], opdx->p[i]->p, NULL,
                                "Atmosphere Projected to XLOC","x (m)","y (m)","opdx %d",i);
                    }
                }
            }
            if(!parms->sim.idealfit) {
                dcellfree(opdx);
            }
        }
    }
    if(parms->save.dm && (!parms->sim.closeloop || simu->isim>0)) {
        if(simu->dmfit) {
            cellarr_dcell(simu->save->dmfit, simu->reconisim, simu->dmfit);
        }
        if(simu->dmerr) {
            cellarr_dcell(simu->save->dmerr, simu->reconisim, simu->dmerr);
        }
        if(simu->dmint->mint->p[0]) {
            cellarr_dcell(simu->save->dmint, simu->reconisim, simu->dmint->mint->p[0]);
        }
        if(simu->Merr_lo) {
            cellarr_dcell(simu->save->Merr_lo, simu->reconisim, simu->Merr_lo);
            if(!parms->sim.fuseint && simu->Mint_lo->mint->p[0]) {
                cellarr_dcell(simu->save->Mint_lo, simu->reconisim, simu->Mint_lo->mint->p[0]);
            }
        }
    }
    const int seed=simu->seed;
    if(parms->save.ngcov>0 && CHECK_SAVE(parms->sim.start, parms->sim.end-(parms->sim.closeloop?1:0), simu->reconisim, parms->save.gcovp)) {
        double scale=1./(double)(simu->reconisim-parms->sim.start+1);
        dcellscale(simu->gcov, scale);
        for(int igcov=0; igcov<parms->save.ngcov; igcov++) {
            writebin(simu->gcov->p[igcov], "gcov_%d_wfs%ld_%ld_%d.bin", seed,
                     parms->save.gcov->p[igcov*2], parms->save.gcov->p[igcov*2+1],
                     simu->reconisim+1);
        }
        dcellscale(simu->gcov, 1./scale);
    }
    if(parms->sim.psfr && CHECK_SAVE(parms->evl.psfisim, parms->sim.end-(parms->sim.closeloop?1:0), simu->reconisim, parms->sim.psfr)) {
        info2("Output PSF Recon Telemetry\n");
        long nstep=simu->reconisim+1-parms->evl.psfisim;
        double scale=1./nstep;
        dcellscale(simu->ecov, scale);
        if(!parms->dbg.useopdr || parms->sim.idealfit) {
            writebin(simu->ecov, "ecov_%d_%ld", seed, nstep);
        } else { /*deprecated */
            char strht[24];
            for(int ievl=0; ievl<parms->evl.nevl; ievl++) {
                if(!simu->ecov->p[ievl]) continue;
                if(isfinite(parms->evl.hs->p[ievl])) {
                    snprintf(strht, 24, "_%g", parms->evl.hs->p[ievl]);
                } else {
                    strht[0]='\0';
                }
                writebin(simu->ecov->p[ievl], "ecov_%d_x%g_y%g%s_%ld.bin", seed,
                         parms->evl.thetax->p[ievl]*206265,
                         parms->evl.thetay->p[ievl]*206265, strht, nstep);
            }
        }
        dcellscale(simu->ecov, 1./scale);//scale back to continuous accumulation
    }
}
예제 #20
0
/**
   Read in pistat information, used to compute matched filter, and SANEA.
*/
static void setup_star_read_pistat(SIM_S *simu, STAR_S *star, int nstar, int seed){
    const PARMS_S *parms=simu->parms;
    const int npowfs=parms->maos.npowfs;
    const int nwvl=parms->maos.nwvl;
    const double ngsgrid=parms->maos.ngsgrid;
    for(int istar=0; istar<nstar; istar++){
	STAR_S *stari=&star[istar];
	stari->pistat=mycalloc(npowfs,PISTAT_S);
	const double thetax=stari->thetax*206265;/*in as */
	const double thetay=stari->thetay*206265;
	double thxnorm=thetax/ngsgrid;
	double thynorm=thetay/ngsgrid;
	long thxl=(long)floor(thxnorm);
	long thyl=(long)floor(thynorm);
	double wtx=thxnorm-thxl;
	double wty=thynorm-thyl;
	for(int ipowfs=0; ipowfs<npowfs; ipowfs++){
	    const int msa=parms->maos.msa[ipowfs];
	    const int nsa=parms->maos.nsa[ipowfs];
	    dcell *avgpsf=NULL;
	    dcell *neaspec=NULL;
	    double wtsum=0;
	    for(int ix=0; ix<2; ix++){
		double thx=(thxl+ix)*ngsgrid;
		for(int iy=0; iy<2; iy++){
		    double thy=(thyl+iy)*ngsgrid;
		    double wtxi=fabs(((1-ix)-wtx)*((1-iy)-wty));
		    if(wtxi<0.01){
			/*info("skipping ix=%d,iy=%d because wt=%g\n",ix,iy,wtxi); */
			continue;
		    }
		    char fn[PATH_MAX];
		    snprintf(fn,PATH_MAX,"%s/pistat/pistat_seed%d_sa%d_x%g_y%g",
			     dirstart, seed,msa,thx,thy);
		    if(!zfexist(fn)){
			/*warning("%s doesn't exist\n",fn); */
		    }else{
			dcell *avgpsfi=dcellread("%s",fn);
			dcelladd(&avgpsf, 1, avgpsfi, wtxi);
			dcellfree(avgpsfi);
			wtsum+=wtxi;
			
			snprintf(fn,PATH_MAX,"%s/neaspec/neaspec_seed%d_sa%d_x%g_y%g",
				 dirstart, seed, msa, thx, thy);
			dcell *neaspeci=dcellread("%s",fn);
			dcelladd(&neaspec, 1, neaspeci, wtxi);
			dcellfree(neaspeci);
		    }
		}
	    }
	    if(wtsum<0.01){
		warning("PISTAT is not available for (%g,%g) msa=%d\n",thetax,thetay,msa);
	    }
	    dcellscale(neaspec, 1./wtsum);
	    dcellscale(avgpsf, 1./wtsum);
	    dmat *scale=NULL;
	    if(parms->skyc.bspstrehl){
		scale=dnew(nsa,nwvl);
		dmat *gx=dnew(1,1); gx->p[0]=thxnorm;
		dmat *gy=dnew(1,1); gy->p[0]=thynorm;
		if(nsa!=avgpsf->nx || nwvl!=avgpsf->ny){
		    error("Mismatch: nsa=%d, nwvl=%d, avgpsf->nx=%ld, avgpsf->ny=%ld\n",
			  nsa, nwvl, avgpsf->nx, avgpsf->ny);
		}
		for(int ic=0; ic<nsa*nwvl; ic++){
		    dmat *val=dbspline_eval(simu->bspstrehl[ipowfs][ic],
					    simu->bspstrehlxy,simu->bspstrehlxy,
					    gx, gy);
		    double ratio=val->p[0]/avgpsf->p[ic]->p[0];
		    /*info("strehl: bilinear: %g, cubic: %g\n", avgpsf->p[ic]->p[0],val->p[0]); */
		    if(ratio<0){
			warning("Ratio=%g is less than zero.\n", ratio);
			scale->p[ic]=1;
		    }else{
			dscale(avgpsf->p[ic], ratio);
			scale->p[ic]=ratio;
		    }
		    dfree(val);
		}
		dfree(gx);
		dfree(gy);
	    }

	    stari->pistat[ipowfs].psf=avgpsf;/*PSF is in corner. */
	    stari->pistat[ipowfs].neaspec=dcellnew(nsa*2, 1);
	    for(int ig=0; ig<nsa*2; ig++){
		dmat *tmp=0;
		for(int iwvl=0; iwvl<nwvl; iwvl++){
		    dadd(&tmp, 0, neaspec->p[ig+nsa*2*iwvl], parms->skyc.wvlwt->p[iwvl]);
		}
		stari->pistat[ipowfs].neaspec->p[ig]=dinterp1(simu->neaspec_dtrats, tmp, parms->skyc.dtrats, 0);
		dfree(tmp);
	    }
	    dcellfree(neaspec);
	    stari->pistat[ipowfs].scale=scale;
	    {/* skip stars with large PSF.*/
		int size=INT_MAX;
		for(int ic=0; ic<avgpsf->nx*avgpsf->ny; ic++){
		    int size0=dfwhm(avgpsf->p[ic]);
		    if(size0<size) size=size0;
		}
		if(size>6){
		    stari->use[ipowfs]=-1;
		}
	    }
	    if(parms->skyc.dbg){
		writebin(avgpsf, "%s/avgpsf_star%d_ipowfs%d_psf",dirsetup,istar,ipowfs);
		writebin(stari->pistat[ipowfs].neaspec, "%s/pistat_star%d_ipowfs%d_neaspec",dirsetup,istar,ipowfs);
	    }
	}
    }
}