int main(int argc, char* argv[]){ /*dsp *RLMc1=dspread("RLMc_old.bin"); */ if(argc!=2){ error("Need 1 argument\n"); } dspcell *RLM=dspcellread("%s",argv[1]); dsp *RLMc=dspcell2sp(RLM); tic;info2("chol ..."); spchol *R1=chol_factorize(RLMc); toc("done"); rand_t rstat; seed_rand(&rstat,1); dmat *y=dnew(RLMc->m, 1); drandn(y, 1, &rstat); dmat *x=NULL, *x2=NULL, *x3=NULL; chol_convert(R1, 1); tic; chol_solve(&x, R1, y); toc("cholmod");tic; chol_solve(&x, R1, y); toc("cholmod");tic; chol_solve_upper(&x3, R1, y); toc("upper");tic; chol_solve_upper(&x3, R1, y); toc("upper");tic; chol_solve_lower(&x2, R1,y); toc("lower");tic; chol_solve_lower(&x2, R1,y); toc("lower");tic; chol_solve(&x, R1, y); toc("cholmod");tic; chol_solve(&x, R1, y); toc("cholmod");tic; writebin(y,"y"); writebin(x,"x"); writebin(x2,"x2"); writebin(x3,"x3"); chol_free(R1); dspfree(RLMc); dspcellfree(RLM); }
/** 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 */ } } }
/** 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.); }