void save_gradstat(SIM_T *simu) { const PARMS_T *parms=simu->parms; const int isim=simu->isim; //Save pistat in the end of simulation for(int iwfs=0; iwfs<simu->parms->nwfs; iwfs++) { int ipowfs=parms->wfsr[iwfs].powfs; const int dtrat=parms->powfs[ipowfs].dtrat; double scale; if(parms->powfs[ipowfs].usephy) { scale=(simu->isim+1-simu->parms->powfs[ipowfs].phystep)/dtrat; } else { scale=(simu->isim+1)/dtrat; } if(scale<=0) continue; if(simu->pistatout && simu->pistatout->p[iwfs]) { int nstep=isim+1-parms->powfs[ipowfs].pistatstart; scale=1./(double)nstep; dcell *pp=simu->pistatout->p[iwfs]; dcellscale(pp,scale); if(parms->sim.skysim) { /*need peak in corner */ for(long ic=0; ic<pp->nx*pp->ny; ic++) { dfftshift(pp->p[ic]); } writebin(pp,"%s/pistat/pistat_seed%d_sa%d_x%g_y%g.bin", dirskysim,simu->seed, parms->powfs[ipowfs].order, parms->wfs[iwfs].thetax*206265, parms->wfs[iwfs].thetay*206265); for(long ic=0; ic<pp->nx*pp->ny; ic++) { dfftshift(pp->p[ic]); } } else { /*need peak in center */ writebin(pp,"pistat_seed%d_wfs%d.bin", simu->seed,iwfs); } dcellscale(pp,1./scale); } } }
/** prepare the integrator by shifting commands. similar to laos. inte->p[0]=inte->p[0]*ap[0]+inte->p[1]*ap[1]+... */ static void servo_shift_ap(SERVO_T *st){ const dmat *ap=st->ap; if(!ap) return; //no need to shift. if(st->mint->nx<ap->nx){ cellresize(st->mint, ap->nx, 1); } if(!st->initialized) return; dcell **inte=st->mint->p; dcell *cyclic=inte[ap->nx-1]; dcellscale(cyclic, ap->p[ap->nx-1]); for(int iap=ap->nx-2; iap>=0; iap--){ dcelladd(&cyclic,1,inte[iap],ap->p[iap]); } for(int iap=ap->nx-1; iap>0; iap--){ inte[iap]=inte[iap-1];/*shifting */ } inte[0]=cyclic;/*new command. */ }
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 } }
/** 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 */ } } }
/** 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); } } } }