Exemple #1
0
int lrosback2(sf_complex **img, sf_complex ***wavfld, float **sill, sf_complex **rcd, bool adj,
	      bool verb, bool wantwf, sf_complex **lt, sf_complex **rt, int m2,
              geopar geop, int pad1, sf_complex ***wavfld2)  
/*< low-rank one-step backward propagation + imaging >*/
{
    int it,iz,im,ik,ix,i,j;     /* index variables */
    int nxb,nzb,dx,dz,gpz,gpx,gpl,snpint,dt,wfit;
    int nt,nz,nx, nk, nzx, nz2, nx2, nzx2;
    sf_complex c;
    sf_complex *cwave, *cwavem, *currm;
    sf_complex **wave, *curr;
    sf_complex **ccr;

    nx = geop->nx;
    nz = geop->nz;
    nxb = geop->nxb;
    nzb = geop->nzb;
    dx = geop->dx;
    dz = geop->dz;
    
    gpz  = geop->gpz;
    gpx  = geop->gpx;
    gpl  = geop->gpl;
    snpint = geop->snpint;
    
    nt = geop->nt;
    dt = geop->dt;

    ccr = sf_complexalloc2(nz, nx);

    nk = cfft2_init(pad1,nzb,nxb,&nz2,&nx2);
    nzx = nzb*nxb;
    nzx2 = nz2*nx2;

    curr = sf_complexalloc(nzx2);
    cwave  = sf_complexalloc(nk);
    cwavem = sf_complexalloc(nk);
    wave = sf_complexalloc2(nzx2,m2);

    if (!adj) {
	currm  = sf_complexalloc(nzx2);
	icfft2_allocate(cwave);
    } else {
	cwavem = sf_complexalloc(nk);
	icfft2_allocate(cwavem);
    }

#ifdef _OPENMP
#pragma omp parallel for private(iz)
#endif
    for (iz=0; iz < nzx2; iz++) {
	curr[iz] = sf_cmplx(0.,0.);
    }

#ifdef _OPENMP
#pragma omp parallel for private(ix, iz)
#endif
    for (ix = 0; ix < nx; ix++) {
	for (iz = 0; iz < nz; iz++) {
	  ccr[ix][iz] = sf_cmplx(0.,0.);
	}
    }

    if (adj) { /* migration */
      /* step backward in time */
      /*Main loop*/
      wfit = (int)(nt-1)/snpint;
      for (it = nt-1; it>=0; it--) {
	if  (verb) sf_warning("Backward receiver it=%d/%d;", it, nt-1);
#ifdef _OPENMP
#pragma omp parallel for private(ix,j)
#endif
        for (ix=0; ix<gpl; ix++)  {
	  j = (gpz+geop->top)+(ix+gpx+geop->lft)*nz2; /* padded grid */
	  curr[j]+=rcd[ix][it]; /* data injection */
	}
	/*matrix multiplication*/
	cfft2(curr,cwave);
	for (im = 0; im < m2; im++) {
#ifdef _OPENMP
#pragma omp parallel for private(ik)
#endif
	  for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
	    cwavem[ik] = cwave[ik]*rt[ik][im];
#else
	    cwavem[ik] = sf_cmul(cwave[ik],rt[ik][im]);
#endif
	  }
	  icfft2(wave[im],cwavem);
	}
	
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz,i,j,im,c) shared(curr,lt,wave)
#endif
	for (ix = 0; ix < nxb; ix++) {
	  for (iz=0; iz < nzb; iz++) {
	    i = iz+ix*nzb;  /* original grid */
	    j = iz+ix*nz2; /* padded grid */
	    c = sf_cmplx(0.,0.); // initialize
	    for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
	      c += lt[im][i]*wave[im][j];
#else
	      c += sf_cmul(lt[im][i], wave[im][j]);
#endif
	    }
	    curr[j] = c;
	  }
	}

        if ( wantwf && it%snpint == 0 ) {
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz,j)
#endif
	  for ( ix = 0; ix < nx; ix++) {
	    for ( iz = 0; iz<nz; iz++ ) { 
	      j = (iz+geop->top)+(ix+geop->lft)*nz2; /* padded grid */
	      wavfld2[wfit][ix][iz] = curr[j];
	    }
	  }
        }
	/*cross-correlation imaging condition*/
	if (it%snpint == 0 ) {
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz,j)
#endif
	  for (ix=0; ix<nx; ix++) {
	    for (iz=0; iz<nz; iz++) {
	      j = (iz+geop->top)+(ix+geop->lft)*nz2; /* padded grid */
#ifdef SF_HAS_COMPLEX_H
	      ccr[ix][iz] += conjf(wavfld[wfit][ix][iz])*curr[j];
#else
	      ccr[ix][iz] += sf_cmul(conjf(wavfld[wfit][ix][iz]),curr[j]);
#endif
	    }
	  }
	  wfit--;
	}
      } /*Main loop*/
      if (verb) sf_warning(".");
#ifdef _OPENMP
#pragma omp parallel for private(ix, iz)
#endif    
      for (ix=0; ix<nx; ix++) {
	for (iz=0; iz<nz; iz++) {
#ifdef SF_HAS_COMPLEX_H
	  img[ix][iz] = ccr[ix][iz]/(sill[ix][iz]+SF_EPS);
#else
	  img[ix][iz] = sf_crmul(ccr[ix][iz],1./(sill[ix][iz]+SF_EPS));
#endif
	}
      } 
    } else { /* modeling */
      /* adjoint of source illumination */
#ifdef _OPENMP
#pragma omp parallel for private(ix, iz)
#endif    
      for (ix=0; ix<nx; ix++) {
	for (iz=0; iz<nz; iz++) {
#ifdef SF_HAS_COMPLEX_H
	  ccr[ix][iz] = img[ix][iz]/(sill[ix][iz]+SF_EPS);
#else
	  ccr[ix][iz] = sf_crmul(img[ix][iz],1./(sill[ix][iz]+SF_EPS));
#endif
	}
      } 
      /* step forward in time */
      /*Main loop*/
      wfit=0;
      for (it=0; it<nt; it++) {
	if (verb) sf_warning("Forward receiver it=%d/%d;", it, nt-1);
        if ( wantwf && it%snpint == 0 ) {
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz,j)
#endif
	  for ( ix = 0; ix < nx; ix++) {
	    for ( iz = 0; iz<nz; iz++ ) { 
	      j = (iz+geop->top)+(ix+geop->lft)*nz2; /* padded grid */
	      wavfld2[wfit][ix][iz] = curr[j];
	    }
	  }
        }
	/*adjoint of cross-correlation imaging condition*/
	if (it%snpint == 0 ) {
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz,j)
#endif
	  for (ix=0; ix<nx; ix++) {
	    for (iz=0; iz<nz; iz++) {
	      j = (iz+geop->top)+(ix+geop->lft)*nz2; /* padded grid */
#ifdef SF_HAS_COMPLEX_H
	      curr[j] += (wavfld[wfit][ix][iz])*ccr[ix][iz];//adjoint of ccr[ix][iz] += conjf(wavfld[wfit][ix][iz])*curr[j]; ???
#else
	      curr[j] += sf_cmul((wavfld[wfit][ix][iz]),ccr[ix][iz]);
#endif
	    }
	  }
	  wfit++;
	}
	/*matrix multiplication*/
	for (im = 0; im < m2; im++) {
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz,i,j) shared(currm,lt,curr)
#endif
	  for (ix = 0; ix < nxb; ix++) {
	    for (iz=0; iz < nzb; iz++) {
	      i = iz+ix*nzb;  /* original grid */
	      j = iz+ix*nz2; /* padded grid */
#ifdef SF_HAS_COMPLEX_H
	      currm[j] = conjf(lt[im][i])*curr[j];
#else
	      currm[j] = sf_cmul(conjf(lt[im][i]), curr[j]);
#endif
	    }
	  }
	  cfft2(currm,wave[im]);
	}
#ifdef _OPENMP
#pragma omp parallel for private(ik,im,c) shared(wave,rt,cwave)
#endif	    
	for (ik = 0; ik < nk; ik++) {
	  c = sf_cmplx(0.,0.);
	  for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
	    c += wave[im][ik]*conjf(rt[ik][im]);
#else
	    c += sf_cmul(wave[im][ik],conjf(rt[ik][im])); //complex multiplies complex
#endif
	  }
	  cwave[ik] = c;
	}
	icfft2(curr,cwave);

#ifdef _OPENMP
#pragma omp parallel for private(ix,j)
#endif
        for (ix=0; ix<gpl; ix++)  {
	  j = (gpz+geop->top)+(ix+gpx+geop->lft)*nz2; /* padded grid */
	  rcd[ix][it]=curr[j];
	}
      } /*Main loop*/
    }
    cfft2_finalize();
    return 0;
}
Exemple #2
0
int propnewc(sf_complex **ini, sf_complex **lt, sf_complex **rt, int nz, int nx, int nt, int m2, int nkzx, char *mode, int pad1, int snap, sf_complex **cc, sf_complex ***wvfld, bool verb, bool correct, sf_complex *alpha, sf_complex *beta)
/*^*/
{
    /* index variables */
    int it,iz,ix,im,ik,i,j,wfit;
    int nz2,nx2,nk,nzx2;
    sf_complex c;
    /* wavefield */
    sf_complex **wave,**wave2, *curr, *currm, *cwave, *cwavem, *curr1, *curr2;

    nk = cfft2_init(pad1,nz,nx,&nz2,&nx2);
    nzx2 = nz2*nx2;

    if (nk!=nkzx) sf_error("nk discrepancy!");

    curr = sf_complexalloc(nzx2);
    if (correct) {
	curr1 = sf_complexalloc(nzx2);
	curr2 = sf_complexalloc(nzx2);
    }
    currm  = sf_complexalloc(nzx2);
    
    cwave  = sf_complexalloc(nk);
    cwavem = sf_complexalloc(nk);
    wave   = sf_complexalloc2(nk,m2);
    wave2  = sf_complexalloc2(nzx2,m2);

    icfft2_allocate(cwavem);

    /* initialization */
    for (ix = 0; ix < nx2; ix++) {
	for (iz=0; iz < nz2; iz++) {
	    j = iz+ix*nz2;
	    if (ix<nx && iz<nz)
		curr[j] = ini[ix][iz];
	    else 
		curr[j] = sf_cmplx(0.,0.);
	}
    }
    wfit = 0;

    /* MAIN LOOP */
    for (it=0; it<nt; it++) {
	if(verb) sf_warning("it=%d;",it);
	
	/* outout wavefield */
	if(snap>0) {
	    if(it%snap==0 && wfit<=(int)(nt-1)/snap) {
		for (ix=0; ix<nx; ix++)
		    for (iz=0; iz<nz; iz++)
			wvfld[wfit][ix][iz] = curr[iz+ix*nz2];
		wfit++;
	    }
	}

	if (mode[0]=='m') {

	    /* matrix multiplication */
	    for (im = 0; im < m2; im++) {
		for (ix = 0; ix < nx; ix++) {
		    for (iz=0; iz < nz; iz++) {
			i = iz+ix*nz;  /* original grid */
			j = iz+ix*nz2; /* padded grid */
#ifdef SF_HAS_COMPLEX_H
			currm[j] = lt[im][i]*curr[j];
#else
			currm[j] = sf_cmul(lt[im][i], curr[j]);
#endif
		    }
		}
		cfft2(currm,wave[im]);
	    }
	    
	    for (ik = 0; ik < nk; ik++) {
		c = sf_cmplx(0.,0.);
		for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
		    c += wave[im][ik]*rt[ik][im];
#else
		    c += sf_cmul(wave[im][ik],rt[ik][im]); //complex multiplies complex
#endif
		}
		cwave[ik] = c;
	    }

	    /* matrix multiplication */
	    for (im = 0; im < m2; im++) {
		for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
		    cwavem[ik] = cwave[ik]*rt[ik][im];
#else
		    cwavem[ik] = sf_cmul(cwave[ik],rt[ik][im]); //complex multiplies complex
#endif
		}
		icfft2(wave2[im],cwavem);
	    }
	    
	    for (ix = 0; ix < nx; ix++) {
		for (iz=0; iz < nz; iz++) {
		    i = iz+ix*nz;  /* original grid */
		    j = iz+ix*nz2; /* padded grid */
		    c = sf_cmplx(0.,0.);
		    for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
			c += lt[im][i]*wave2[im][j];
#else
			c += sf_cmul(lt[im][i], wave2[im][j]);
#endif
		    }
		    curr[j] = c;
		}
	    }

	    if (correct) {
		for (ix = 0; ix < nx2; ix++) {
		    for (iz=0; iz < nz2; iz++) {
			i = iz+ix*nz;  /* original grid */
			j = iz+ix*nz2; /* padded grid */
			if (ix<nx && iz<nz) {
#ifdef SF_HAS_COMPLEX_H
			    currm[j] = curr[j]/alpha[i];
#else
			    currm[j] = sf_cdiv(curr[j],alpha[i]);
#endif
			} else {
			    currm[j] = sf_cmplx(0.,0.);
			}
		    }
		}
		cfft2(currm,cwave);
		
		for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
		    cwavem[ik] = cwave[ik]/beta[ik];
#else
		    cwavem[ik] = sf_cdiv(cwave[ik],beta[ik]);
#endif
		}
		icfft2(curr1,cwavem);
		
		for (ix = nx; ix < nx2; ix++) {
		    for (iz=nz; iz < nz2; iz++) {
			j = iz+ix*nz2; /* padded grid */	
			curr1[j] = sf_cmplx(0.,0.);
		    }
		}

		/**/
		cfft2(curr,cwave);
		
		for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
		    cwavem[ik] = cwave[ik]/conjf(beta[ik]);
#else
		    cwavem[ik] = sf_cdiv(cwave[ik],conjf(beta[ik]));
#endif
		}
		icfft2(curr,cwavem);
		
		for (ix = 0; ix < nx2; ix++) {
		    for (iz=0; iz < nz2; iz++) {
			i = iz+ix*nz;  /* original grid */
			j = iz+ix*nz2; /* padded grid */
			if (ix<nx && iz<nz) {
#ifdef SF_HAS_COMPLEX_H
			    curr2[j] = curr[j]/conjf(alpha[i]);
#else
			    curr2[j] = sf_cdiv(curr[j],conjf(alpha[i]));
#endif
			} else {
			    curr2[j] = sf_cmplx(0.,0.);
			}
		    }
		}

		for (ix = 0; ix < nx2; ix++) {
		    for (iz=0; iz < nz2; iz++) {
			j = iz+ix*nz2; /* padded grid */
#ifdef SF_HAS_COMPLEX_H
			curr[j] = (curr1[j] + curr2[j])/2.;
#else
			curr[j] = sf_crmul(curr1[j]+curr2[j],0.5);
#endif
		    }
		}
	    }
	    
	} else if (mode[0]=='x') {
	 
	    cfft2(curr,cwave);

	    /* matrix multiplication */
	    for (im = 0; im < m2; im++) {
		for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
		    cwavem[ik] = cwave[ik]*rt[ik][im];
#else
		    cwavem[ik] = sf_cmul(cwave[ik],rt[ik][im]); //complex multiplies complex
#endif
		}
		icfft2(wave2[im],cwavem);
	    }
	    
	    for (ix = 0; ix < nx; ix++) {
		for (iz=0; iz < nz; iz++) {
		    i = iz+ix*nz;  /* original grid */
		    j = iz+ix*nz2; /* padded grid */
		    c = sf_cmplx(0.,0.);
		    for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
			c += lt[im][i]*wave2[im][j];
#else
			c += sf_cmul(lt[im][i], wave2[im][j]);
#endif
		    }
		    curr[j] = c;
		}
	    }

	    /* matrix multiplication */
	    for (im = 0; im < m2; im++) {
		for (ix = 0; ix < nx; ix++) {
		    for (iz=0; iz < nz; iz++) {
			i = iz+ix*nz;  /* original grid */
			j = iz+ix*nz2; /* padded grid */
#ifdef SF_HAS_COMPLEX_H
			currm[j] = lt[im][i]*curr[j];
#else
			currm[j] = sf_cmul(lt[im][i], curr[j]);
#endif
		    }
		}
		cfft2(currm,wave[im]);
	    }
	    
	    for (ik = 0; ik < nk; ik++) {
		c = sf_cmplx(0.,0.);
		for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
		    c += wave[im][ik]*rt[ik][im];
#else
		    c += sf_cmul(wave[im][ik],rt[ik][im]); //complex multiplies complex
#endif
		}
		cwavem[ik] = c;
	    }
	    
	    icfft2(curr,cwavem);

	    if (correct) {
		for (ix = 0; ix < nx2; ix++) {
		    for (iz=0; iz < nz2; iz++) {
			i = iz+ix*nz;  /* original grid */
			j = iz+ix*nz2; /* padded grid */
			if (ix<nx && iz<nz) {
#ifdef SF_HAS_COMPLEX_H
			    currm[j] = curr[j]/alpha[i];
#else
			    currm[j] = sf_cdiv(curr[j],alpha[i]);
#endif
			} else {
			    currm[j] = sf_cmplx(0.,0.);
			}
		    }
		}
		cfft2(currm,cwave);
		
		for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
		    cwavem[ik] = cwave[ik]/beta[ik];
#else
		    cwavem[ik] = sf_cdiv(cwave[ik],beta[ik]);
#endif
		}
		icfft2(curr,cwavem);
		
		for (ix = nx; ix < nx2; ix++) {
		    for (iz=nz; iz < nz2; iz++) {
			j = iz+ix*nz2; /* padded grid */	
			curr[j] = sf_cmplx(0.,0.);
		    }
		}
	    }
	    
	} else if (mode[0]=='n') {

	    /* matrix multiplication */
	    for (im = 0; im < m2; im++) {
		for (ix = 0; ix < nx; ix++) {
		    for (iz=0; iz < nz; iz++) {
			i = iz+ix*nz;  /* original grid */
			j = iz+ix*nz2; /* padded grid */
#ifdef SF_HAS_COMPLEX_H
			currm[j] = lt[im][i]*curr[j];
#else
			currm[j] = sf_cmul(lt[im][i], curr[j]);
#endif
		    }
		}
		cfft2(currm,wave[im]);
	    }
	    
	    for (ik = 0; ik < nk; ik++) {
		c = sf_cmplx(0.,0.);
		for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
		    c += wave[im][ik]*rt[ik][im];
#else
		    c += sf_cmul(wave[im][ik],rt[ik][im]); //complex multiplies complex
#endif
		}
		cwavem[ik] = c;
	    }
	    icfft2(curr,cwavem);

	    /* matrix multiplication */
	    for (im = 0; im < m2; im++) {
		for (ix = 0; ix < nx; ix++) {
		    for (iz=0; iz < nz; iz++) {
			i = iz+ix*nz;  /* original grid */
			j = iz+ix*nz2; /* padded grid */
#ifdef SF_HAS_COMPLEX_H
			currm[j] = lt[im][i]*curr[j];
#else
			currm[j] = sf_cmul(lt[im][i], curr[j]);
#endif
		    }
		}
		cfft2(currm,wave[im]);
	    }
	    
	    for (ik = 0; ik < nk; ik++) {
		c = sf_cmplx(0.,0.);
		for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
		    c += wave[im][ik]*rt[ik][im];
#else
		    c += sf_cmul(wave[im][ik],rt[ik][im]); //complex multiplies complex
#endif
		}
		cwavem[ik] = c;
	    }
	    icfft2(curr,cwavem);
	    
	} else if (mode[0]=='p') {

	    cfft2(curr,cwave);

	    /* matrix multiplication */
	    for (im = 0; im < m2; im++) {
		for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
		    cwavem[ik] = cwave[ik]*rt[ik][im];
#else
		    cwavem[ik] = sf_cmul(cwave[ik],rt[ik][im]); //complex multiplies complex
#endif
		}
		icfft2(wave2[im],cwavem);
	    }
	    
	    for (ix = 0; ix < nx; ix++) {
		for (iz=0; iz < nz; iz++) {
		    i = iz+ix*nz;  /* original grid */
		    j = iz+ix*nz2; /* padded grid */
		    c = sf_cmplx(0.,0.);
		    for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
			c += lt[im][i]*wave2[im][j];
#else
			c += sf_cmul(lt[im][i], wave2[im][j]);
#endif
		    }
		    curr[j] = c;
		}
	    }

	    cfft2(curr,cwave);

	    /* matrix multiplication */
	    for (im = 0; im < m2; im++) {
		for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
		    cwavem[ik] = cwave[ik]*rt[ik][im];
#else
		    cwavem[ik] = sf_cmul(cwave[ik],rt[ik][im]); //complex multiplies complex
#endif
		}
		icfft2(wave2[im],cwavem);
	    }
	    
	    for (ix = 0; ix < nx; ix++) {
		for (iz=0; iz < nz; iz++) {
		    i = iz+ix*nz;  /* original grid */
		    j = iz+ix*nz2; /* padded grid */
		    c = sf_cmplx(0.,0.);
		    for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
			c += lt[im][i]*wave2[im][j];
#else
			c += sf_cmul(lt[im][i], wave2[im][j]);
#endif
		    }
		    curr[j] = c;
		}
	    }

	} else sf_error("Check mode parameter!");

    } /* time stepping */
    if(verb) sf_warning("."); 
    /* output final result*/
    for (ix=0; ix<nx; ix++)
	for (iz=0; iz<nz; iz++)
	    cc[ix][iz] = curr[iz+ix*nz2];
    
    cfft2_finalize();
    return 0;
}
Exemple #3
0
int lrexp(sf_complex **img, sf_complex **dat, bool adj, sf_complex **lt, sf_complex **rt, sf_complex *ww, geopar geop, int pad1, bool verb, int snap, sf_complex ***wvfld)
/*< zero-offset exploding reflector modeling/migration >*/
{
    int it, nt, ix, nx, nx2, iz, nz, nz2, nzx2,  wfnt, wfit;
    int im, i, j, m2, ik, nk;
    float dt, dx, dz, ox;
    sf_complex *curr, **wave, *cwave, *cwavem, c;
    sf_complex *currm;

    nx  = geop->nx;
    nz  = geop->nz;
    dx  = geop->dx;
    dz  = geop->dz;
    ox  = geop->ox;
    nt  = geop->nt;
    dt  = geop->dt;
    snap= geop->snap;
    nzx2= geop->nzx2;
    m2  = geop->m2;
    wfnt= geop->wfnt;

    nk = cfft2_init(pad1,nz,nx,&nz2,&nx2);
    if (nk!=geop->nk) sf_error("nk discrepancy!");

    curr = sf_complexalloc(nzx2);
    cwave  = sf_complexalloc(nk);
    wave = sf_complexalloc2(nzx2,m2);
    if (adj) {
	currm  = sf_complexalloc(nzx2);
	icfft2_allocate(cwave);
    } else {
	cwavem = sf_complexalloc(nk);
	icfft2_allocate(cwavem);
    }

#ifdef _OPENMP
#pragma omp parallel for private(iz)
#endif
    for (iz=0; iz < nzx2; iz++) {
	curr[iz] = sf_cmplx(0.,0.);
    }

    if (adj) { /* migration <- read wavefield */
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz)
#endif
	for (ix=0; ix < nx; ix++) {
	    for (iz=0; iz < nz; iz++) {
		curr[iz+ix*nz2]=dat[ix][iz];
	    }
	}
	wfit = (int)(nt-1)/snap; // wfnt-1
	/* time stepping */
	for (it=nt-1; it > -1; it--) {
	    if (verb) sf_warning("it=%d;",it);
	
	    /* matrix multiplication */
	    for (im = 0; im < m2; im++) {
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz,i,j) shared(currm,lt,curr)
#endif
		for (ix = 0; ix < nx; ix++) {
		    for (iz=0; iz < nz; iz++) {
			i = iz+ix*nz;  /* original grid */
			j = iz+ix*nz2; /* padded grid */
#ifdef SF_HAS_COMPLEX_H
			currm[j] = conjf(lt[im][i])*curr[j];
#else
			currm[j] = sf_cmul(conjf(lt[im][i]), curr[j]);
#endif
		    }
		}
		cfft2(currm,wave[im]);
	    }
#ifdef _OPENMP
#pragma omp parallel for private(ik,im,c) shared(wave,rt,cwave)
#endif	    
	    for (ik = 0; ik < nk; ik++) {
		c = sf_cmplx(0.,0.);
		for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
		    c += wave[im][ik]*conjf(rt[ik][im]);
#else
		    c += sf_cmul(wave[im][ik],conjf(rt[ik][im])); //complex multiplies complex
#endif
		}
		cwave[ik] = c;
	    }

	    icfft2(curr,cwave);

	    if (snap > 0 && it%snap == 0) {
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz,j)
#endif
		for ( ix = 0; ix < nx; ix++) {
		    for ( iz = 0; iz<nz; iz++ ) { 
			j = iz+ix*nz2; /* padded grid */
			wvfld[wfit][ix][iz] = curr[j];
		    }
		}
		wfit--;
	    }
	} /*time iteration*/
	/*generate image*/
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz)
#endif
	for (ix=0; ix < nx; ix++) {
	    for (iz=0; iz < nz; iz++) {
		img[ix][iz] = curr[iz+ix*nz2];
	    }
	}
    } else { /* modeling -> write data */
	/*point source*/
	wfit = 0;
	/* time stepping */
	for (it=0; it < nt; it++) {
	    if (verb) sf_warning("it=%d;",it);

	    /* matrix multiplication */
	    cfft2(curr,cwave);
	    
	    for (im = 0; im < m2; im++) {
#ifdef _OPENMP
#pragma omp parallel for private(ik)
#endif
		for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
		    cwavem[ik] = cwave[ik]*rt[ik][im];
#else
		    cwavem[ik] = sf_cmul(cwave[ik],rt[ik][im]);
#endif
		}
		icfft2(wave[im],cwavem);
	    }
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz,i,j,im,c) shared(curr,lt,wave)
#endif
	    for (ix = 0; ix < nx; ix++) {
		for (iz=0; iz < nz; iz++) {
		    i = iz+ix*nz;  /* original grid */
		    j = iz+ix*nz2; /* padded grid */

#ifdef SF_HAS_COMPLEX_H
		c = ww[it] * crealf(img[ix][iz]); // source term
#else
		c = sf_crmul(ww[it], crealf(img[ix][iz])); // source term
#endif
		    
		    for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
			c += lt[im][i]*wave[im][j];
#else
			c += sf_cmul(lt[im][i], wave[im][j]);
#endif	    
		    }
		    curr[j] = c;
		}
	    }
	    /* record wavefield*/
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz)
#endif
	for (ix=0; ix < nx; ix++) {
	    for (iz=0; iz < nz; iz++) {
		dat[ix][iz] = curr[iz+ix*nz2];
	    }
	}
	    if (snap > 0 && it%snap == 0) {
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz,j)
#endif
		for ( ix = 0; ix < nx; ix++) {
		    for ( iz = 0; iz<nz; iz++ ) { 
			j = iz+ix*nz2; /* padded grid */
			wvfld[wfit][ix][iz] = curr[j];
		    }
		}
		wfit++;
	    }
	}
    }
    if (verb) sf_warning(".");
    cfft2_finalize();

    return 0;
}
Exemple #4
0
int lrosfor2(sf_complex ***wavfld, float **sill, sf_complex **rcd, bool verb,
	     sf_complex **lt, sf_complex **rt, int m2,
	     geopar geop, sf_complex *ww, float *rr, int pad1)
/*< low-rank one-step forward modeling >*/
{
    int it,iz,im,ik,ix,i,j;     /* index variables */
    int nxb,nzb,dx,dz,spx,spz,gpz,gpx,gpl,snpint,dt,nth=1,wfit;
    int nt,nz,nx, nk, nzx, nz2, nx2, nzx2;
    sf_complex c;
    sf_complex *cwave, *cwavem;
    sf_complex **wave, *curr;

    nx = geop->nx;
    nz = geop->nz;
    nxb = geop->nxb;
    nzb = geop->nzb;
    dx = geop->dx;
    dz = geop->dz;

    spx = geop->spx;
    spz = geop->spz;
    gpz  = geop->gpz;
    gpx  = geop->gpx;
    gpl  = geop->gpl;
    snpint = geop->snpint;
    
    nt = geop->nt;
    dt = geop->dt;

#ifdef _OPENMP
#pragma omp parallel  
{
    nth = omp_get_num_threads();
}
    sf_warning(">>>> Using %d threads <<<<<", nth);
#endif
    
    /*Matrix dimensions*/
    nk = cfft2_init(pad1,nzb,nxb,&nz2,&nx2);
    nzx = nzb*nxb;
    nzx2 = nz2*nx2;

    curr   = sf_complexalloc(nzx2);
    cwave  = sf_complexalloc(nk);
    cwavem = sf_complexalloc(nk);
    wave   = sf_complexalloc2(nzx2,m2);

    icfft2_allocate(cwavem);

#ifdef _OPENMP
#pragma omp parallel for private(iz)
#endif
    for (iz=0; iz < nzx2; iz++) {
	curr[iz] = sf_cmplx(0.,0.);
    }

    /*Main loop*/
    wfit = 0;
    for (it = 0; it < nt; it++) {
	if (verb) sf_warning("Forward source it=%d/%d;", it, nt-1);
	
	/*matrix multiplication*/
	cfft2(curr,cwave);

	for (im = 0; im < m2; im++) {
#ifdef _OPENMP
#pragma omp parallel for private(ik)
#endif
	    for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
		cwavem[ik] = cwave[ik]*rt[ik][im];
#else
		cwavem[ik] = sf_cmul(cwave[ik],rt[ik][im]);
#endif
	    }
	    icfft2(wave[im],cwavem);
	}

#ifdef _OPENMP
#pragma omp parallel for private(ix,iz,i,j,im,c) shared(curr,lt,wave)
#endif
	for (ix = 0; ix < nxb; ix++) {
	    for (iz=0; iz < nzb; iz++) {
		i = iz+ix*nzb;  /* original grid */
		j = iz+ix*nz2; /* padded grid */
		if ((it*dt)<=geop->trunc) {
#ifdef SF_HAS_COMPLEX_H
		  c = ww[it] * rr[i]; // source term
#else
		  c = sf_crmul(ww[it], rr[i]); // source term
#endif
		} else {
		  c = sf_cmplx(0.,0.);
		}
		for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
		    c += lt[im][i]*wave[im][j];
#else
		    c += sf_cmul(lt[im][i], wave[im][j]);
#endif
		}
		curr[j] = c;
	    }
	}

#ifdef _OPENMP
#pragma omp parallel for private(ix,j)
#endif	 
	for ( ix =0 ; ix < gpl; ix++) {
	    j = (gpz+geop->top)+(ix+gpx+geop->lft)*nz2; /* padded grid */
	    rcd[ix][it] = curr[j];
	}
	
	if ( it%snpint == 0 ) {
#ifdef _OPENMP
#pragma omp parallel for private(ix,iz,j)
#endif
	    for ( ix = 0; ix < nx; ix++) {
		for ( iz = 0; iz<nz; iz++ ) { 
		    j = (iz+geop->top)+(ix+geop->lft)*nz2; /* padded grid */
		    wavfld[wfit][ix][iz] = curr[j];
		    sill[ix][iz] += pow(hypotf(crealf(curr[j]),cimagf(curr[j])),2);
		    //sill[ix][iz] += pow(hypotf(crealf(wavfld[wfit][ix][iz]),cimagf(wavfld[wfit][ix][iz])),2);
		}
	    }
	    wfit++;
	}
    } /*Main loop*/
    if (verb) sf_warning(".");
    cfft2_finalize();
    return wfit;
}
Exemple #5
0
int main(int argc, char *argv[])
{
	bool wantwf, verb;

	int ix, iz, is, it, wfit, im, ik, i, j, itau;
    int ns, nx, nz, nt, wfnt, rnx, rnz, nzx, rnzx, vnx, ntau, htau, nds;
	int scalet, snap, snapshot, fnx, fnz, fnzx, nk, nb;
	int rectx, rectz, repeat, gpz, n, m, pad1, trunc, spx, spz;

	float dt, t0, z0, dz, x0, dx, s0, ds, wfdt, srctrunc;
    float dtau, tau0, tau;

	int nr, ndr, nr0;

	char *path1, *path2, number[5], *left, *right;

	double tstart, tend;
	struct timeval tim;

	/*wavenumber domain tapering*/
	int taper;
	float *ktp;
	float ktmp,kx_trs,kz_trs,thresh;
	float dkx,dkz,kx0,kz0;
	float kx,kz;
	int nkz;

	sf_complex c, **lt, **rt;
	sf_complex *ww, **dd, ***dd3;
	float ***img1, **img2, ***mig1, **mig2;
    float *rr, **ccr, **sill, ***fwf, ***bwf;
	sf_complex *cwave, *cwavem, **wave, *curr;

	sf_axis at, ax, az, atau;

	sf_file Fdat, Fsrc, Fimg1, Fimg2;
	sf_file Ffwf, Fbwf, Fvel;
	sf_file Fleft, Fright;

	int cpuid, numprocs, nth, nspad, iturn;
    float *sendbuf, *recvbuf;
	sf_complex *sendbufc, *recvbufc;
	MPI_Comm comm=MPI_COMM_WORLD;

	MPI_Init(&argc, &argv);
	MPI_Comm_rank(comm, &cpuid);
	MPI_Comm_size(comm, &numprocs);

	sf_init(argc, argv);

#ifdef _OPENMP
#pragma omp parallel
	{
		nth=omp_get_num_threads();
	}
	sf_warning(">>> Using %d threads <<<", nth);
#endif

	gettimeofday(&tim, NULL);
	tstart=tim.tv_sec+(tim.tv_usec/1000000.0);

	if (!sf_getint("taper",&taper)) taper=0; /* tapering in the frequency domain */
	if (!sf_getfloat("thresh",&thresh)) thresh=0.92; /* tapering threshold */

	if(!sf_getbool("wantwf", &wantwf)) wantwf=false;
    if(!sf_getbool("verb", &verb)) verb=false;
	if(!sf_getint("pad1", &pad1)) pad1=1;
	/* padding factor on the first axis */

	if(!sf_getint("nb", &nb)) sf_error("Need nb= ");
	if(!sf_getfloat("srctrunc", &srctrunc)) srctrunc=0.4;
	if(!sf_getint("rectx", &rectx)) rectx=2;
	if(!sf_getint("rectz", &rectz)) rectz=2;
	if(!sf_getint("repeat", &repeat)) repeat=2;

	if(!sf_getint("scalet", &scalet)) scalet=1;
	if(!sf_getint("snap", &snap)) snap=100;
	/* interval of the output wavefield */
	if(!sf_getint("snapshot", &snapshot)) snapshot=0;
	/* print out the wavefield snapshots of this shot */
    if(!sf_getint("nds", &nds)) sf_error("Need nds=!");
    
    /* source and receiver positions */
	if(!sf_getint("gpz", &gpz)) sf_error("Need gpz=");
	if(!sf_getint("spx", &spx)) sf_error("Need spx=");
	if(!sf_getint("spz", &spz)) sf_error("Need spz=");
    
    /* tau parameters */
    if(!sf_getint("ntau", &ntau)) sf_error("Need ntau=");
    if(!sf_getfloat("dtau", &dtau)) sf_error("Need dtau=");
    if(!sf_getfloat("tau0", &tau0)) sf_error("Need tau0=");

	/* geometry parameters */
	if(!sf_getint("rnx", &rnx)) sf_error("Need rnx=");
	if(!sf_getint("ndr", &ndr)) ndr=1;
	if(!sf_getint("nr0", &nr0)) nr0=0;

	/* input/output files */
	Fdat=sf_input("--input");
	Fimg1=sf_output("--output");
    Fimg2=sf_output("Fimg2");
    Fsrc=sf_input("Fsrc");
    Fvel=sf_input("Fpadvel");

	if(wantwf){
		Ffwf=sf_output("Ffwf");
        Fbwf=sf_output("Fbwf");
	}

	at=sf_iaxa(Fsrc, 1); nt=sf_n(at); dt=sf_d(at); t0=sf_o(at);
    ax=sf_iaxa(Fvel, 2); vnx=sf_n(ax); dx=sf_d(ax); x0=sf_o(ax);
	az=sf_iaxa(Fvel, 1); rnz=sf_n(az); dz=sf_d(az); z0=sf_o(az);
    if(!sf_histint(Fdat, "n2", &nr)) sf_error("Need n2= in input!");
    if(!sf_histint(Fdat, "n3", &ns)) sf_error("Need n3= in input!");
    if(!sf_histfloat(Fdat, "d3", &ds)) sf_error("Need d3= in input!");
    if(!sf_histfloat(Fdat, "o3", &s0)) sf_error("Need o3= in input!");
    
    wfnt=(nt-1)/scalet+1;
    wfdt=dt*scalet;
    
    /* double check the geometry parameters */
    if(nds != (int)(ds/dx)) sf_error("Need ds/dx= %d", nds);
	//sf_warning("s0=%g, x0+(rnx-1)*dx/2=%g", s0, x0+(rnx-1)*dx/2);
    //if(s0 != x0+(rnx-1)*dx/2) sf_error("Wrong origin information!");
    if(vnx != nds*(ns-1)+rnx) sf_error("Wrong dimension in x axis!");

    /* set up the output files */
    atau=sf_iaxa(Fsrc, 1);
    sf_setn(atau, ntau);
    sf_setd(atau, dtau);
    sf_seto(atau, tau0);
    sf_setlabel(atau, "Tau");
    sf_setunit(atau, "s");
    
    sf_oaxa(Fimg1, az, 1);
    sf_oaxa(Fimg1, ax, 2);
    sf_oaxa(Fimg1, atau, 3);
    sf_oaxa(Fimg2, az, 1);
    sf_oaxa(Fimg2, ax, 2);
    sf_putint(Fimg2, "n3", 1);
    sf_settype(Fimg1, SF_FLOAT);
    sf_settype(Fimg2, SF_FLOAT);
    
    if(wantwf){
		sf_setn(ax, rnx);
        sf_seto(ax, -(rnx-1)*dx/2.0);
        sf_oaxa(Ffwf, az, 1);
        sf_oaxa(Ffwf, ax, 2);
        sf_putint(Ffwf, "n3", (wfnt-1)/snap+1);
        sf_putfloat(Ffwf, "d3", snap*wfdt);
        sf_putfloat(Ffwf, "o3", t0);
        sf_putstring(Ffwf, "label3", "Time");
        sf_putstring(Ffwf, "unit3", "s");
        sf_settype(Ffwf, SF_FLOAT);
        
        sf_oaxa(Fbwf, az, 1);
        sf_oaxa(Fbwf, ax, 2);
        sf_putint(Fbwf, "n3", (wfnt-1)/snap+1);
        sf_putfloat(Fbwf, "d3", -snap*wfdt);
        sf_putfloat(Fbwf, "o3", (wfnt-1)*wfdt);
        sf_putstring(Fbwf, "label3", "Time");
        sf_putstring(Fbwf, "unit3", "s");
        sf_settype(Fbwf, SF_FLOAT);
	}
	
    nx=rnx+2*nb; nz=rnz+2*nb;
	nzx=nx*nz; rnzx=rnz*rnx;
    nk=cfft2_init(pad1, nz, nx, &fnz, &fnx);
	fnzx=fnz*fnx;

	if(ns%numprocs==0) nspad=ns;
	else nspad=(ns/numprocs+1)*numprocs;
    
	/* print axies parameters for double check */
    sf_warning("cpuid=%d, numprocs=%d, nspad=%d", cpuid, numprocs, nspad);
	sf_warning("nt=%d, dt=%g, scalet=%d, wfnt=%d, wfdt=%g",nt, dt, scalet, wfnt, wfdt);
	sf_warning("vnx=%d, nx=%d, dx=%g, nb=%d, rnx=%d", vnx, nx, dx, nb, rnx);
	sf_warning("nr=%d, ndr=%d, nr0=%g", nr, ndr, nr0);
	sf_warning("nz=%d, rnz=%d, dz=%g, z0=%g", nz, rnz, dz, z0);
	sf_warning("spx=%d, spz=%d, gpz=%d", spx, spz, gpz);
	sf_warning("ns=%d, ds=%g, s0=%g", ns, ds, s0);
    sf_warning("ntau=%d, dtau=%g, tau0=%g", ntau, dtau, tau0);
    sf_warning("nzx=%d, fnzx=%d, nk=%d", nzx, fnzx, nk);

	/* allocate storage and read data */
	ww=sf_complexalloc(nt);
	sf_complexread(ww, nt, Fsrc);
	sf_fileclose(Fsrc);
	
    gpz=gpz+nb;
    spz=spz+nb;
    spx=spx+nb;
	nr0=nr0+nb;
    trunc=srctrunc/dt+0.5;
    
	dd=sf_complexalloc2(nt, nr);
	if(cpuid==0) dd3=sf_complexalloc3(nt, nr, numprocs);
	rr=sf_floatalloc(nzx);
	reflgen(nz, nx, spz, spx, rectz, rectx, repeat, rr);
    
    fwf=sf_floatalloc3(rnz, rnx, wfnt);
    bwf=sf_floatalloc3(rnz, rnx, wfnt);
    img1=sf_floatalloc3(rnz, vnx, ntau);
    img2=sf_floatalloc2(rnz, vnx);
    mig1=sf_floatalloc3(rnz, rnx, ntau);
    mig2=sf_floatalloc2(rnz, rnx);
    
    ccr=sf_floatalloc2(rnz, rnx);
    sill=sf_floatalloc2(rnz, rnx);
    
    curr=sf_complexalloc(fnzx);
	cwave=sf_complexalloc(nk);
	cwavem=sf_complexalloc(nk);
	icfft2_allocate(cwavem);

	if (taper!=0) {
		dkz = 1./(fnz*dz); kz0 = -0.5/dz;
		dkx = 1./(fnx*dx); kx0 = -0.5/dx;
		nkz = fnz;

		sf_warning("dkz=%f,dkx=%f,kz0=%f,kx0=%f",dkz,dkx,kz0,kx0);
		sf_warning("nk=%d,nkz=%d,nkx=%d",nk,nkz,fnx);

		kx_trs = thresh*fabs(0.5/dx);
		kz_trs = thresh*fabs(0.5/dz);
		sf_warning("Applying kz tapering below %f",kz_trs);
		sf_warning("Applying kx tapering below %f",kx_trs);
		ktp = sf_floatalloc(nk);
		/* constructing the tapering op */
		for (ix=0; ix < fnx; ix++) {
			kx = kx0+ix*dkx;
			for (iz=0; iz < nkz; iz++) {
				kz = kz0+iz*dkz;
				ktmp = 1.;
				if (fabs(kx) > kx_trs)
					ktmp *= powf((2*kx_trs - fabs(kx))/(kx_trs),2);
				if (fabs(kz) > kz_trs)
					ktmp *= powf((2*kz_trs - fabs(kz))/(kz_trs),2);
				ktp[iz+ix*nkz] = ktmp;
			}
		}
	}

	/* initialize image tables that would be used for summing images */
#ifdef _OPENMP
#pragma omp parallel for private(ix, iz, itau)
#endif
    for(ix=0; ix<vnx; ix++){
        for(iz=0; iz<rnz; iz++){
            img2[ix][iz]=0.;
            for(itau=0; itau<ntau; itau++){
                img1[itau][ix][iz]=0.;
            }
        }
    }

	path1=sf_getstring("path1");
	path2=sf_getstring("path2");
	if(path1==NULL) path1="./mat/left";
	if(path2==NULL) path2="./mat/right";

	/* shot loop */
	for (iturn=0; iturn*numprocs<nspad; iturn++){
		is=iturn*numprocs+cpuid;
        
        /* read data */
		if(cpuid==0){
			sf_seek(Fdat, ((off_t) is)*((off_t) nr)*((off_t) nt)*sizeof(float complex), SEEK_SET);

			if((iturn+1)*numprocs<=ns){
				sf_complexread(dd3[0][0], nr*nt*numprocs, Fdat);
			}else{
				sf_complexread(dd3[0][0], nr*nt*(ns-iturn*numprocs), Fdat);
				for(is=ns; is<nspad; is++)
					for(ix=0; ix<nr; ix++)
						for(it=0; it<nt; it++)
							dd3[is-iturn*numprocs][ix][it]=sf_cmplx(0.,0.);
				is=iturn*numprocs;
			}

			sendbufc=dd3[0][0];
			recvbufc=dd[0];
		}else{
			sendbufc=NULL;
			recvbufc=dd[0];
		}
		MPI_Scatter(sendbufc, nt*nr, MPI_COMPLEX, recvbufc, nt*nr, MPI_COMPLEX, 0, comm);

		if(is<ns){ /* effective shot loop */

			/* construct the names of left and right matrices */
			left=sf_charalloc(strlen(path1));
			right=sf_charalloc(strlen(path2));
			strcpy(left, path1);
			strcpy(right, path2);
			sprintf(number, "%d", is+1);
			strcat(left, number);
			strcat(right, number);

			Fleft=sf_input(left);
			Fright=sf_input(right);

			if(!sf_histint(Fleft, "n1", &n) || n != nzx) sf_error("Need n1=%d in Fleft", nzx);
			if(!sf_histint(Fleft, "n2", &m)) sf_error("No n2 in Fleft");
			if(!sf_histint(Fright, "n1", &n) || n != m) sf_error("Need n1=%d in Fright", m);
			if(!sf_histint(Fright, "n2", &n) || n != nk) sf_error("Need n2=%d in Fright", nk);

			/* allocate storage for each shot migration */
			lt=sf_complexalloc2(nzx, m);
			rt=sf_complexalloc2(m, nk);
			sf_complexread(lt[0], nzx*m, Fleft);
			sf_complexread(rt[0], m*nk, Fright);
			sf_fileclose(Fleft);
			sf_fileclose(Fright);

			/* initialize curr and imaging variables */
#ifdef _OPENMP
#pragma omp parallel for private(iz)
#endif
			for(iz=0; iz<fnzx; iz++){
				curr[iz]=sf_cmplx(0.,0.);
			}
#ifdef _OPENMP
#pragma omp parallel for private(ix, iz, itau)
#endif
			for(ix=0; ix<rnx; ix++){
				for(iz=0; iz<rnz; iz++){
					mig2[ix][iz]=0.;
					ccr[ix][iz]=0.;
					sill[ix][iz]=0.;
					for(itau=0; itau<ntau; itau++){
						mig1[itau][ix][iz]=0.;
					}
				}
			}

			/* wave */
			wave=sf_complexalloc2(fnzx, m);

			/* snapshot */
			if(wantwf && is==snapshot) wantwf=true;
			else wantwf=false;

			/* forward propagation */
			wfit=0;
			for(it=0; it<nt; it++){
				if(verb) sf_warning("Forward propagation it=%d/%d",it+1, nt);

				cfft2(curr, cwave);
				for(im=0; im<m; im++){
#ifdef _OPENMP
#pragma omp parallel for private(ik)
#endif
					for(ik=0; ik<nk; ik++){
#ifdef SF_HAS_COMPLEX_H
						cwavem[ik]=cwave[ik]*rt[ik][im];
#else
						cwavem[ik]=sf_cmul(cwave[ik],rt[ik][im]);
#endif
					}
					icfft2(wave[im],cwavem);
				}

#ifdef _OPENMP
#pragma omp parallel for private(ix, iz, i, j, im, c) shared(curr, it)
#endif
				for(ix=0; ix<nx; ix++){
					for(iz=0; iz<nz; iz++){
						i=iz+ix*nz;
						j=iz+ix*fnz;

						if(it<trunc){
#ifdef SF_HAS_COMPLEX_H
							c=ww[it]*rr[i];
#else
							c=sf_crmul(ww[it],rr[i]);
#endif
						}else{
							c=sf_cmplx(0.,0.);
						}

						//                    c += curr[j];

						for(im=0; im<m; im++){
#ifdef SF_HAS_COMPLEX_H
							c += lt[im][i]*wave[im][j];
#else
							c += sf_cmul(lt[im][i], wave[im][j]);
#endif
						}
						curr[j]=c;
					}
				}

				if (taper!=0) {
					if (it%taper == 0) {
						cfft2(curr,cwave);
						for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
							cwavem[ik] = cwave[ik]*ktp[ik];
#else
							cwavem[ik] = sf_crmul(cwave[ik],ktp[ik]);
#endif
						}
						icfft2(curr,cwavem);
					}
				}

				if(it%scalet==0){
#ifdef _OPENMP
#pragma omp parallel for private(ix, iz)
#endif
					for(ix=0; ix<rnx; ix++){
						for(iz=0; iz<rnz; iz++){
							fwf[wfit][ix][iz]=crealf(curr[(ix+nb)*fnz+(iz+nb)]);
						}
					}
					wfit++;
				}
			} //end of it

			/* check wfnt */
			if(wfit != wfnt) sf_error("At this point, wfit should be equal to wfnt");

			/* backward propagation starts from here... */
#ifdef _OPENMP
#pragma omp parallel for private(iz)
#endif
			for(iz=0; iz<fnzx; iz++){
				curr[iz]=sf_cmplx(0.,0.);
			}

			wfit=wfnt-1;
			for(it=nt-1; it>=0; it--){
				if(verb) sf_warning("Backward propagation it=%d/%d",it+1, nt);
#ifdef _OPENMP
#pragma omp parallel for private(ix)
#endif
				for(ix=0; ix<nr; ix++){
					curr[(nr0+ix*ndr)*fnz+gpz]+=dd[ix][it];
				}

				cfft2(curr, cwave);

				for(im=0; im<m; im++){
#ifdef _OPENMP
#pragma omp parallel for private(ik)
#endif
					for(ik=0; ik<nk; ik++){
#ifdef SF_HAS_COMPLEX_H
						cwavem[ik]=cwave[ik]*conjf(rt[ik][im]);
#else
						cwavem[ik]=sf_cmul(cwave[ik],conjf(rt[ik][im]));
#endif
					}
					icfft2(wave[im],cwavem);
				}

#ifdef _OPENMP
#pragma omp parallel for private(ix, iz, i, j, im, c) shared(curr, it)
#endif
				for(ix=0; ix<nx; ix++){
					for(iz=0; iz<nz; iz++){
						i=iz+ix*nz;
						j=iz+ix*fnz;

						//                    c=curr[j];
						c=sf_cmplx(0.,0.);

						for(im=0; im<m; im++){
#ifdef SF_HAS_COMPLEX_H
							c += conjf(lt[im][i])*wave[im][j];
#else
							c += sf_cmul(conjf(lt[im][i]), wave[im][j]);
#endif
						}
						curr[j]=c;
					}
				}

				if (taper!=0) {
					if (it%taper == 0) {
						cfft2(curr,cwave);
						for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
							cwavem[ik] = cwave[ik]*ktp[ik];
#else
							cwavem[ik] = sf_crmul(cwave[ik],ktp[ik]);
#endif
						}
						icfft2(curr,cwavem);
					}
				}

				if(it%scalet==0){
#ifdef _OPENMP
#pragma omp parallel for private(ix, iz)
#endif
					for(ix=0; ix<rnx; ix++){
						for(iz=0; iz<rnz; iz++){
							bwf[wfit][ix][iz]=crealf(curr[(ix+nb)*fnz+(iz+nb)]);
							ccr[ix][iz] += fwf[wfit][ix][iz]*bwf[wfit][ix][iz];
							sill[ix][iz] += fwf[wfit][ix][iz]*fwf[wfit][ix][iz];
						}
					}
					wfit--;
				}
			} //end of it
			if(wfit != -1) sf_error("Check program! The final wfit should be -1!");

			/* free storage */
			free(*rt); free(rt);
			free(*lt); free(lt);
			free(*wave); free(wave);
			free(left); free(right);

			/* normalized image */
#ifdef _OPENMP
#pragma omp parallel for private(ix, iz)
#endif
			for (ix=0; ix<rnx; ix++){
				for(iz=0; iz<rnz; iz++){
					mig2[ix][iz]=ccr[ix][iz]/(sill[ix][iz]+SF_EPS);
					//		sill[ix][iz]=0.;
				}
			}

			/* time-shift imaging condition */
			for(itau=0; itau<ntau; itau++){
				//sf_warning("itau/ntau=%d/%d", itau+1, ntau);
				tau=itau*dtau+tau0;
				htau=tau/wfdt;

				for(it=abs(htau); it<wfnt-abs(htau); it++){
#ifdef _OPENMP
#pragma omp parallel for private(ix, iz)
#endif
					for(ix=0; ix<rnx; ix++){
						for(iz=0; iz<rnz; iz++){
							mig1[itau][ix][iz]+=fwf[it+htau][ix][iz]*bwf[it-htau][ix][iz];
							//	sill[ix][iz]+=fwf[it+htau][ix][iz]*fwf[it+htau][ix][iz];
						} // end of iz
					} // end of ix
				} // end of it


				//#ifdef _OPENMP
				//#pragma omp parallel for private(ix, iz)
				//#endif 
				/* source illumination */
				//	for(ix=0; ix<rnx; ix++){
				//		for(iz=0; iz<rnz; iz++){
				//			mig1[itau][ix][iz] = mig1[itau][ix][iz]/(sill[ix][iz]+SF_EPS);
				//		}
				//	} 
			} //end of itau

			/* output wavefield snapshot */
			if(wantwf){
				for(it=0; it<wfnt; it++){
					if(it%snap==0){
						sf_floatwrite(fwf[it][0], rnzx, Ffwf);
						sf_floatwrite(bwf[wfnt-1-it][0], rnzx, Fbwf);
					}
				}
				sf_fileclose(Ffwf);
				sf_fileclose(Fbwf);
			}

			/* add all the shot images that are on the same node */
#ifdef _OPENMP
#pragma omp parallel for private(itau, ix, iz)
#endif
			for(itau=0; itau<ntau; itau++){
				for(ix=0; ix<rnx; ix++){
					for(iz=0; iz<rnz; iz++){
						img1[itau][ix+is*nds][iz] += mig1[itau][ix][iz];
					}
				}
			}

#ifdef _OPENMP
#pragma omp parallel for private(ix, iz)
#endif
			for(ix=0; ix<rnx; ix++){
				for(iz=0; iz<rnz; iz++){
					img2[ix+is*nds][iz] += mig2[ix][iz];
				}
			}
		} // end of is<ns
	} // end of iturn
	////////////////end of ishot
	MPI_Barrier(comm);

	cfft2_finalize();
    sf_fileclose(Fdat);
    
    free(ww); free(rr);
	free(*dd); free(dd);
	if(cpuid==0) {free(**dd3); free(*dd3); free(dd3);}
	free(cwave); free(cwavem); free(curr);
    free(*ccr); free(ccr);
    free(*sill); free(sill);
    free(**fwf); free(*fwf); free(fwf);
    free(**bwf); free(*bwf); free(bwf);
    free(**mig1); free(*mig1); free(mig1);
    free(*mig2); free(mig2);
    
    /* sum image */
    if(cpuid==0){
        sendbuf=(float *)MPI_IN_PLACE;
        recvbuf=img1[0][0];
    }else{
        sendbuf=img1[0][0];
        recvbuf=NULL;
    }
    MPI_Reduce(sendbuf, recvbuf, ntau*vnx*rnz, MPI_FLOAT, MPI_SUM, 0, comm);
    
    if(cpuid==0){
        sendbuf=MPI_IN_PLACE;
        recvbuf=img2[0];
    }else{
        sendbuf=img2[0];
        recvbuf=NULL;
    }
    MPI_Reduce(sendbuf, recvbuf, vnx*rnz, MPI_FLOAT, MPI_SUM, 0, comm);
    
    /* output image */
    if(cpuid==0){
        sf_floatwrite(img1[0][0], ntau*vnx*rnz, Fimg1);
        sf_floatwrite(img2[0], vnx*rnz, Fimg2);
    }
	MPI_Barrier(comm);

	sf_fileclose(Fimg1);
    sf_fileclose(Fimg2);
    free(**img1); free(*img1); free(img1);
    free(*img2); free(img2);
    
	gettimeofday(&tim, NULL);
	tend=tim.tv_sec+(tim.tv_usec/1000000.0);
	sf_warning(">> The computing time is %.3lf minutes <<", (tend-tstart)/60.);

	MPI_Finalize();
	exit(0);
}
Exemple #6
0
int prop1Pa(sf_complex *input, sf_complex *output, sf_complex *lt, sf_complex *rt, int nz, int nx, int nkzx, int m2)
/*< Just nsps(-) >*/
{
    int iz, ix, im, ik, i, j;
    int nz2, nx2, nk, nzx, nzx2;
    int pad1 = 1;
    sf_complex **wave, **wave2, *curr, *currm, *cwave, *cwavem, c;

    nk = cfft2_init(pad1,nz,nx,&nz2,&nx2);
    if (nk!=nkzx) sf_error("nk discrepancy!");
    
    nzx = nz*nx;
    nzx2 = nz2*nx2;

    curr   = sf_complexalloc(nzx2);
    currm  = sf_complexalloc(nzx2);
    
    cwave  = sf_complexalloc(nk);
    cwavem = sf_complexalloc(nk);
    
    wave   = sf_complexalloc2(nk,m2);
    wave2  = sf_complexalloc2(nzx2,m2);

    icfft2_allocate(cwave);

    /* initialization */
    for (ix = 0; ix < nx2; ix++) {
	for (iz=0; iz < nz2; iz++) {
            i = iz+ix*nz;
	    j = iz+ix*nz2;
	    if (ix<nx && iz<nz)
		curr[j] = input[i];
	    else 
		curr[j] = sf_cmplx(0.,0.);
	}
    }
        
        /* nsps(-) */
         
	/* matrix multiplication */
	for (im = 0; im < m2; im++) {
	    for (ix = 0; ix < nx; ix++) {
		for (iz=0; iz < nz; iz++) {
		    i = iz+ix*nz;  /* original grid */
		    j = iz+ix*nz2; /* padded grid */
#ifdef SF_HAS_COMPLEX_H
		    currm[j] = conjf(lt[im*nzx+i])*curr[j];
#else
		    currm[j] = sf_cmul(conjf(lt[im*nzx+i]), curr[j]);
#endif
		}
	    }
	    cfft2(currm,wave[im]);
	}
	
	for (ik = 0; ik < nk; ik++) {
	    c = sf_cmplx(0.,0.);
	    for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
		c += wave[im][ik]*conjf(rt[ik*m2+im]);
#else
		c += sf_cmul(wave[im][ik],conjf(rt[ik*m2+im]));
#endif
	    }
	    cwave[ik] = c;
	}
	
	/* saving a pair of FFTs */
	icfft2(curr,cwave);

    /* output final result*/
    for (ix = 0; ix < nx; ix++) {
	for (iz=0; iz < nz; iz++) {
            i = iz+ix*nz;
	    j = iz+ix*nz2;
	    output[i] = curr[j];
	}
    }
    
    cfft2_finalize();
    return 0;
}
Exemple #7
0
int main(int argc, char* argv[])
{
    bool verb;        
    int it,iz,im,ik,ix,i,j;     /* index variables */
    int nt,nz,nx, m2, nk, nzx, nz2, nx2, nzx2, n2, pad1;
    sf_complex c;

    float  *rr;      /* I/O arrays*/
    sf_complex *ww, *cwave, *cwavem;

    sf_complex **wave, *curr;
    
    sf_file Fw,Fr,Fo;    /* I/O files */
    sf_axis at,az,ax;    /* cube axes */

    sf_complex **lt, **rt;
    sf_file left, right;


    sf_init(argc,argv);
    if(!sf_getbool("verb",&verb)) verb=false; /* verbosity */

    /* setup I/O files */
    Fw = sf_input ("in" );
    Fo = sf_output("out");
    Fr = sf_input ("ref");

    if (SF_COMPLEX != sf_gettype(Fw)) sf_error("Need complex input");
    if (SF_FLOAT != sf_gettype(Fr)) sf_error("Need float ref");

    sf_settype(Fo,SF_COMPLEX);

    /* Read/Write axes */
    at = sf_iaxa(Fw,1); nt = sf_n(at); 
    az = sf_iaxa(Fr,1); nz = sf_n(az); 
    ax = sf_iaxa(Fr,2); nx = sf_n(ax); 

    sf_oaxa(Fo,az,1); 
    sf_oaxa(Fo,ax,2); 
    sf_oaxa(Fo,at,3);
    
    if (!sf_getint("pad1",&pad1)) pad1=1; /* padding factor on the first axis */

    nk = cfft2_init(pad1,nz,nx,&nz2,&nx2);

    nzx = nz*nx;
    nzx2 = nz2*nx2;

    /* propagator matrices */
    left = sf_input("left");
    right = sf_input("right");

    if (!sf_histint(left,"n1",&n2) || n2 != nzx) sf_error("Need n1=%d in left",nzx);
    if (!sf_histint(left,"n2",&m2))  sf_error("Need n2= in left");
    
    if (!sf_histint(right,"n1",&n2) || n2 != m2) sf_error("Need n1=%d in right",m2);
    if (!sf_histint(right,"n2",&n2) || n2 != nk) sf_error("Need n2=%d in right",nk);
//    if (!sf_histint(Fw,"n1",&nxx)) sf_error("No n1= in input");
  
    lt = sf_complexalloc2(nzx,m2);
    rt = sf_complexalloc2(m2,nk);

    sf_complexread(lt[0],nzx*m2,left);
    sf_complexread(rt[0],m2*nk,right);

//    sf_fileclose(left);
//    sf_fileclose(right);

    /* read wavelet & reflectivity */
    ww=sf_complexalloc(nt);  
    sf_complexread(ww,nt ,Fw);

    rr=sf_floatalloc(nzx); 
    sf_floatread(rr,nzx,Fr);

    curr   = sf_complexalloc(nzx2);

    cwave  = sf_complexalloc(nk);
    cwavem = sf_complexalloc(nk);
    wave   = sf_complexalloc2(nzx2,m2);

    icfft2_allocate(cwavem);

    for (iz=0; iz < nzx2; iz++) {
	curr[iz] = sf_cmplx(0.,0.);
    }

    /* MAIN LOOP */
    for (it=0; it<nt; it++) {
	if(verb) sf_warning("it=%d;",it);

	/* matrix multiplication */
	cfft2(curr,cwave);

	for (im = 0; im < m2; im++) {
	    for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
		cwavem[ik] = cwave[ik]*rt[ik][im];
#else
		cwavem[ik] = sf_cmul(cwave[ik],rt[ik][im]); //complex multiplies complex
#endif
//		sf_warning("realcwave=%g, imagcwave=%g", crealf(cwavem[ik]),cimagf(cwavem[ik]));
	    }
	    icfft2(wave[im],cwavem);
	}

	for (ix = 0; ix < nx; ix++) {
	    for (iz=0; iz < nz; iz++) {
		i = iz+ix*nz;  /* original grid */
		j = iz+ix*nz2; /* padded grid */
#ifdef SF_HAS_COMPLEX_H
		c = ww[it] * rr[i]; // source term
#else
		c = sf_crmul(ww[it], rr[i]); // source term
#endif
		for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
		    c += lt[im][i]*wave[im][j];
#else
		    c = sf_cadd(c,sf_cmul(lt[im][i], wave[im][j]));
#endif
		}

		curr[j] = c;
	    }

	    /* write wavefield to output */
	    sf_complexwrite(curr+ix*nz2,nz,Fo);
	}
    }
    if(verb) sf_warning("."); 
    cfft2_finalize();
    exit (0);
}
Exemple #8
0
int main(int argc, char* argv[])
{
    bool mig,timer;
    int it, nt, ix, nx, iz, nz, nx2, nz2, nzx, nzx2, pad1;
    int im, i, j, m2, it1, it2, its, ik, n2, nk;
    float dt, dx, dz,x0;
    sf_complex *curr, **img, *dat, **lft, **rht, **wave, *cwave, *cwavem, c;
    sf_file data, image, left, right;
    double time=0.,t0=0.,t1=0.;

    sf_init(argc,argv);

    if (!sf_getbool("mig",&mig)) mig=false;
    /* if n, modeling; if y, migration */
    if(! sf_getbool("timer",&timer)) timer=false;

    if (!sf_getint("pad1",&pad1)) pad1=1; /* padding factor on the first axis */

    if (mig) { /* migration */
	data = sf_input("in");
	image = sf_output("out");
	sf_settype(image,SF_COMPLEX);

	if (!sf_histint(data,"n1",&nx)) sf_error("No n1= in input");
	if (!sf_histfloat(data,"d1",&dx)) sf_error("No d1= in input");
	if (!sf_histfloat(data,"o1",&x0)) x0=0.; 

	if (!sf_histint(data,"n2",&nt)) sf_error("No n2= in input");
	if (!sf_histfloat(data,"d2",&dt)) sf_error("No d2= in input");

	if (!sf_getint("nz",&nz)) sf_error("Need nz=");
	/* depth samples (if migration) */
	if (!sf_getfloat("dz",&dz)) sf_error("Need dz=");
	/* depth sampling (if migration) */

	sf_putint(image,"n1",nz);
	sf_putfloat(image,"d1",dz);
	sf_putfloat(image,"o1",0.);
	sf_putstring(image,"label1","Depth");

	sf_putint(image,"n2",nx);
	sf_putfloat(image,"d2",dx);
	sf_putfloat(image,"o2",x0);
	sf_putstring(image,"label2","Distance");
    } else { /* modeling */
	image = sf_input("in");
	data = sf_output("out");
	sf_settype(data,SF_COMPLEX);

	if (!sf_histint(image,"n1",&nz)) sf_error("No n1= in input");
	if (!sf_histfloat(image,"d1",&dz)) sf_error("No d1= in input");

	if (!sf_histint(image,"n2",&nx))  sf_error("No n2= in input");
	if (!sf_histfloat(image,"d2",&dx)) sf_error("No d2= in input");
	if (!sf_histfloat(image,"o2",&x0)) x0=0.; 	

	if (!sf_getint("nt",&nt)) sf_error("Need nt=");
	/* time samples (if modeling) */
	if (!sf_getfloat("dt",&dt)) sf_error("Need dt=");
	/* time sampling (if modeling) */

	sf_putint(data,"n1",nx);
	sf_putfloat(data,"d1",dx);
	sf_putfloat(data,"o1",x0);
	sf_putstring(data,"label1","Distance");

	sf_putint(data,"n2",nt);
	sf_putfloat(data,"d2",dt);
	sf_putfloat(data,"o2",0.);
	sf_putstring(data,"label2","Time");
	sf_putstring(data,"unit2","s");
    }

    nk = cfft2_init(pad1,nx,nz,&nx2,&nz2);

    nzx = nz*nx;
    nzx2 = nz2*nx2;

    img = sf_complexalloc2(nz,nx);
    dat = sf_complexalloc(nx);

    /* propagator matrices */
    left = sf_input("left");
    right = sf_input("right");

    if (!sf_histint(left,"n1",&n2) || n2 != nzx) sf_error("Need n1=%d in left",nzx);
    if (!sf_histint(left,"n2",&m2))  sf_error("No n2= in left");
    
    if (!sf_histint(right,"n1",&n2) || n2 != m2) sf_error("Need n1=%d in right",m2);
    if (!sf_histint(right,"n2",&n2) || n2 != nk) sf_error("Need n2=%d in right",nk);
 
    lft = sf_complexalloc2(nzx,m2);
    rht = sf_complexalloc2(m2,nk);

    sf_complexread(lft[0],nzx*m2,left);
    sf_complexread(rht[0],m2*nk,right);

    curr = sf_complexalloc(nzx2);

    cwave  = sf_complexalloc(nk);
    cwavem = sf_complexalloc(nk);
    wave = sf_complexalloc2(nzx2,m2);

    icfft2_allocate(cwavem);

    for (iz=0; iz < nzx2; iz++) {
	curr[iz] = sf_cmplx(0.,0.);
    }


    if (mig) { /* migration */
	/* step backward in time */
	it1 = nt-1;
	it2 = -1;
	its = -1;	
    } else { /* modeling */
	sf_complexread(img[0],nzx,image);

	/* transpose */
	for (ix=0; ix < nx; ix++) {
	    for (iz=0; iz < nz; iz++) {
		curr[ix+iz*nx2]=img[ix][iz];
	    }
	}
	
	/* step forward in time */
	it1 = 0;
	it2 = nt;
	its = +1;
    }

    if (timer) t0 = gtod_timer();

    /* time stepping */
    for (it=it1; it != it2; it += its) {
	sf_warning("it=%d;",it);

	if (mig) { /* migration <- read data */
	    sf_complexread(dat,nx,data);
	} else {
	    for (ix=0; ix < nx; ix++) {
		dat[ix] = sf_cmplx(0.,0.);
	    }
	}

	for (ix=0; ix < nx; ix++) {
	    if (mig) {
#ifdef SF_HAS_COMPLEX_H
		curr[ix] += dat[ix];
#else
		curr[ix] = sf_cadd(curr[ix],dat[ix]);
#endif
	    } else {
		dat[ix] = curr[ix];
	    }
	}

	/* matrix multiplication */
	cfft2(curr,cwave);

	for (im = 0; im < m2; im++) {
	    for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
		cwavem[ik] = cwave[ik]*rht[ik][im];
#else
		cwavem[ik] = sf_cmul(cwave[ik],rht[ik][im]);
#endif
	    }
	    icfft2(wave[im],cwavem);
	}


#ifdef _OPENMP
#pragma omp parallel for private(ix,iz,i,j,im,c) shared(curr,lft,wave)
#endif
	for (ix = 0; ix < nx; ix++) {
	    for (iz=0; iz < nz; iz++) {
		i = ix+iz*nx;  /* original grid */
		j = ix+iz*nx2; /* padded grid */
		
		c = sf_cmplx(0.,0.); /* initialize */

		for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
		    c += lft[im][i]*wave[im][j];
#else
		    c = sf_cadd(c,sf_cmul(lft[im][i], wave[im][j]));
#endif	    
		}

		curr[j] = c;
	    }
	}
	
	if (!mig) { /* modeling -> write out data */
	    sf_complexwrite(dat,nx,data);
	}
    }
    sf_warning(".");

    if (timer)
      {
        t1 = gtod_timer();
        time = t1-t0;
        sf_warning("Time = %lf\n",time);
      }

    if (mig) {
	/* transpose */
	for (ix=0; ix < nx; ix++) {
	    for (iz=0; iz < nz; iz++) {
		img[ix][iz] = curr[ix+iz*nx2];
	    }
	}

	sf_complexwrite(img[0],nzx,image);
    }

    cfft2_finalize();
    exit(0);
}
Exemple #9
0
int main(int argc, char* argv[])
{
    bool verb,complx,sub,os;
    int it,iz,im,ik,ix,i,j;     /* index variables */
    int nt,nz,nx, m2, nk, nzx, nz2, nx2, nzx2, n2, pad1,nth;
    sf_complex c,old;

    /* I/O arrays*/
    sf_complex *ww,*curr,*prev,*cwave,*cwavem,**wave,**lt, **rt;
    float *rcurr,*rr;
    
    sf_file Fw,Fr,Fo;    /* I/O files */
    sf_axis at,az,ax;    /* cube axes */
    sf_file left, right;


    sf_init(argc,argv);
    if(!sf_getbool("verb",&verb)) verb=false; /* verbosity */
    if(!sf_getbool("cmplx",&complx)) complx=true; /* outputs complex wavefield */
    if(!sf_getbool("os",&os)) os=true; /* one-step flag */
    if (os) {
      sf_warning("One-step wave extrapolation");
      if(!sf_getbool("sub",&sub)) sub=false; /* subtraction flag */
    } else {
      sf_warning("Two-step wave extrapolation");
      if(!sf_getbool("sub",&sub)) sub=true; /* subtraction flag */
    }

    /* setup I/O files */
    Fw = sf_input ("in" );
    Fo = sf_output("out");
    Fr = sf_input ("ref");

    if (SF_COMPLEX != sf_gettype(Fw)) sf_error("Need complex input");
    if (SF_FLOAT != sf_gettype(Fr)) sf_error("Need float ref");

    if(complx)
	sf_settype(Fo,SF_COMPLEX);
    else
	sf_settype(Fo,SF_FLOAT);

    /* Read/Write axes */
    at = sf_iaxa(Fw,1); nt = sf_n(at); 
    az = sf_iaxa(Fr,1); nz = sf_n(az); 
    ax = sf_iaxa(Fr,2); nx = sf_n(ax); 

    sf_oaxa(Fo,az,1); 
    sf_oaxa(Fo,ax,2); 
    sf_oaxa(Fo,at,3);
    
    if (!sf_getint("pad1",&pad1)) pad1=1; /* padding factor on the first axis */

#ifdef _OPENMP
#pragma omp parallel
    {
      nth = omp_get_num_threads();
    }
    if (verb) sf_warning(">>>> Using %d threads <<<<<", nth);
#endif

    nk = cfft2_init(pad1,nz,nx,&nz2,&nx2);

    nzx = nz*nx;
    nzx2 = nz2*nx2;

    /* propagator matrices */
    left = sf_input("left");
    right = sf_input("right");

    if (!sf_histint(left,"n1",&n2) || n2 != nzx) sf_error("Need n1=%d in left",nzx);
    if (!sf_histint(left,"n2",&m2))  sf_error("Need n2= in left");
    
    if (!sf_histint(right,"n1",&n2) || n2 != m2) sf_error("Need n1=%d in right",m2);
    if (!sf_histint(right,"n2",&n2) || n2 != nk) sf_error("Need n2=%d in right",nk);
  
    lt = sf_complexalloc2(nzx,m2);
    rt = sf_complexalloc2(m2,nk);

    sf_complexread(lt[0],nzx*m2,left);
    sf_complexread(rt[0],m2*nk,right);

    sf_fileclose(left);
    sf_fileclose(right);

    /* read wavelet & reflectivity */
    ww=sf_complexalloc(nt);  
    sf_complexread(ww,nt ,Fw);

    rr=sf_floatalloc(nzx); 
    sf_floatread(rr,nzx,Fr);

    curr   = sf_complexalloc(nzx2);
    if (!os) prev = sf_complexalloc(nzx2);
    else prev = NULL;
    if(!complx) rcurr  = sf_floatalloc(nzx2);
    else rcurr=NULL;

    cwave  = sf_complexalloc(nk);
    cwavem = sf_complexalloc(nk);
    wave   = sf_complexalloc2(nzx2,m2);

    icfft2_allocate(cwavem);

    for (iz=0; iz < nzx2; iz++) {
	curr[iz] = sf_cmplx(0.,0.);
	if (!os) prev[iz] = sf_cmplx(0.,0.);
	if(!complx) rcurr[iz]= 0.;
    }

    /* MAIN LOOP */
    for (it=0; it<nt; it++) {
	if(verb) sf_warning("it=%d;",it);

	/* matrix multiplication */
	cfft2(curr,cwave);

	for (im = 0; im < m2; im++) {
	    for (ik = 0; ik < nk; ik++) {
#ifdef SF_HAS_COMPLEX_H
		cwavem[ik] = cwave[ik]*rt[ik][im];
#else
		cwavem[ik] = sf_cmul(cwave[ik],rt[ik][im]); //complex multiplies complex
#endif
	    }
	    icfft2(wave[im],cwavem);
	}

	for (ix = 0; ix < nx; ix++) {
	    for (iz=0; iz < nz; iz++) {
	        i = iz+ix*nz;  /* original grid */
		j = iz+ix*nz2; /* padded grid */
#ifdef SF_HAS_COMPLEX_H
		c = ww[it] * rr[i]; // source term
#else
		c = sf_crmul(ww[it], rr[i]); // source term
#endif
		if (sub) c += curr[j];
		if (!os) {
		  old = curr[j];
#ifdef SF_HAS_COMPLEX_H
		  c += sub? (old-prev[j]) : -prev[j];
#else
		  c = sf_cadd(c,sub? sf_csub(old,prev[j]) : sf_cneg(prev[j]));
#endif
		  prev[j] = old;
		}
		for (im = 0; im < m2; im++) {
#ifdef SF_HAS_COMPLEX_H
		    c += lt[im][i]*wave[im][j];
#else
		    c += sf_cmul(lt[im][i], wave[im][j]);
#endif
		}

		curr[j] = c;
		if (!complx) rcurr[j] = crealf(c);

	    }

	    /* write wavefield to output */
	    if (complx)
		sf_complexwrite(curr+ix*nz2,nz,Fo);
	    else
		sf_floatwrite(rcurr+ix*nz2,nz,Fo);
	}
    }
    if(verb) sf_warning("."); 
    cfft2_finalize();
    exit (0);
}