int writeRec(recPar rec, modPar mod, bndPar bnd, wavPar wav, int ixsrc, int izsrc, int nsam, int ishot, int fileno, float *rec_vx, float *rec_vz, float *rec_txx, float *rec_tzz, float *rec_txz, float *rec_p, float *rec_pp, float *rec_ss, float *rec_udp, float *rec_udvz, int verbose) { FILE *fpvx, *fpvz, *fptxx, *fptzz, *fptxz, *fpp, *fppp, *fpss, *fpup, *fpdown; float *rec_up, *rec_down, *trace, *rec_vze, *rec_pe; float dx, dt, cp, rho, fmin, fmax; complex *crec_vz, *crec_p, *crec_up, *crec_dw; int irec, ntfft, nfreq, nkx, xorig, ix, iz, it, ibndx; int append; double ddt; char number[16], filename[1024]; segy hdr; if (!rec.n) return 0; if (ishot) append=1; else append=0; /* if the total number of samples exceeds rec_ntsam then a new (numbered) file is opened */ /* fileno has a non-zero value (from fdelmodc.c) if the number of samples exceeds rec_ntsam. */ strcpy(filename, rec.file_rcv); if (fileno) { sprintf(number,"_%03d",fileno); name_ext(filename, number); } if (verbose>2) vmess("Writing receiver data to file %s", filename); if (nsam != rec.nt && verbose) vmess("Number of samples written to last file = %d",nsam); memset(&hdr,0,TRCBYTES); ddt = (double)mod.dt;/* to avoid rounding in 32 bit precision */ dt = (float)ddt*rec.skipdt; dx = (rec.x[1]-rec.x[0])*mod.dx; hdr.dt = (unsigned short)lround((((double)1.0e6*ddt*rec.skipdt))); hdr.scalco = -1000; hdr.scalel = -1000; hdr.sx = 1000*(mod.x0+ixsrc*mod.dx); hdr.sdepth = 1000*(mod.z0+izsrc*mod.dz); hdr.selev = (int)(-1000.0*(mod.z0+izsrc*mod.dz)); hdr.fldr = ishot+1; hdr.trid = 1; hdr.ns = nsam; hdr.trwf = rec.n; hdr.ntr = (ishot+1)*rec.n; hdr.f1 = 0.0; hdr.d1 = mod.dt*rec.skipdt; hdr.d2 = (rec.x[1]-rec.x[0])*mod.dx; hdr.f2 = mod.x0+rec.x[0]*mod.dx; if (rec.type.vx) fpvx = fileOpen(filename, "_rvx", append); if (rec.type.vz) fpvz = fileOpen(filename, "_rvz", append); if (rec.type.p) fpp = fileOpen(filename, "_rp", append); if (rec.type.txx) fptxx = fileOpen(filename, "_rtxx", append); if (rec.type.tzz) fptzz = fileOpen(filename, "_rtzz", append); if (rec.type.txz) fptxz = fileOpen(filename, "_rtxz", append); if (rec.type.pp) fppp = fileOpen(filename, "_rpp", append); if (rec.type.ss) fpss = fileOpen(filename, "_rss", append); /* decomposed wavefield */ if (rec.type.ud && (mod.ischeme==1 || mod.ischeme==2) ) { fpup = fileOpen(filename, "_ru", append); fpdown = fileOpen(filename, "_rd", append); ntfft = optncr(nsam); nfreq = ntfft/2+1; fmin = 0.0; fmax = wav.fmax; nkx = optncc(2*mod.nax); ibndx = mod.ioPx; if (bnd.lef==4 || bnd.lef==2) ibndx += bnd.ntap; cp = rec.cp; rho = rec.rho; if (verbose) vmess("Decomposition array at z=%.2f with cp=%.2f rho=%.2f", rec.zr[0]+mod.z0, cp, rho); rec_up = (float *)calloc(ntfft*nkx,sizeof(float)); rec_down= (float *)calloc(ntfft*nkx,sizeof(float)); crec_vz = (complex *)malloc(nfreq*nkx*sizeof(complex)); crec_p = (complex *)malloc(nfreq*nkx*sizeof(complex)); crec_up = (complex *)malloc(nfreq*nkx*sizeof(complex)); crec_dw = (complex *)malloc(nfreq*nkx*sizeof(complex)); rec_vze = rec_up; rec_pe = rec_down; /* copy input data into extended arrays with padded zeroes */ for (ix=0; ix<mod.nax; ix++) { memcpy(&rec_vze[ix*ntfft],&rec_udvz[ix*rec.nt],nsam*sizeof(float)); memcpy(&rec_pe[ix*ntfft], &rec_udp[ix*rec.nt], nsam*sizeof(float)); } /* transform from t-x to kx-w */ xorig = ixsrc+ibndx; xt2wkx(rec_vze, crec_vz, ntfft, nkx, ntfft, nkx, xorig); xt2wkx(rec_pe, crec_p, ntfft, nkx, ntfft, nkx, xorig); /* apply decomposition operators */ kxwdecomp(crec_p, crec_vz, crec_up, crec_dw, nkx, mod.dx, nsam, dt, fmin, fmax, cp, rho, verbose); /* transform back to t-x */ wkx2xt(crec_up, rec_up, ntfft, nkx, nkx, ntfft, xorig); wkx2xt(crec_dw, rec_down, ntfft, nkx, nkx, ntfft, xorig); /* reduce array to rec.nt samples rec.n traces */ for (irec=0; irec<rec.n; irec++) { ix = rec.x[irec]+ibndx; for (it=0; it<rec.nt; it++) { rec_up[irec*rec.nt+it] = rec_up[ix*ntfft+it]; rec_down[irec*rec.nt+it] = rec_down[ix*ntfft+it]; } } free(crec_vz); free(crec_p); free(crec_up); free(crec_dw); } if (rec.type.ud && (mod.ischeme==3 || mod.ischeme==4) ) { } for (irec=0; irec<rec.n; irec++) { hdr.tracf = irec+1; hdr.tracl = ishot*rec.n+irec+1; hdr.gx = 1000*(mod.x0+rec.x[irec]*mod.dx); hdr.offset = (rec.x[irec]-ixsrc)*mod.dx; hdr.gelev = (int)(-1000*(mod.z0+rec.z[irec]*mod.dz)); if (rec.type.vx) { traceWrite( &hdr, &rec_vx[irec*rec.nt], nsam, fpvx) ; } if (rec.type.vz) { traceWrite( &hdr, &rec_vz[irec*rec.nt], nsam, fpvz) ; } if (rec.type.p) { traceWrite( &hdr, &rec_p[irec*rec.nt], nsam, fpp) ; } if (rec.type.txx) { traceWrite( &hdr, &rec_txx[irec*rec.nt], nsam, fptxx) ; } if (rec.type.tzz) { traceWrite( &hdr, &rec_tzz[irec*rec.nt], nsam, fptzz) ; } if (rec.type.txz) { traceWrite( &hdr, &rec_txz[irec*rec.nt], nsam, fptxz) ; } if (rec.type.pp) { traceWrite( &hdr, &rec_pp[irec*rec.nt], nsam, fppp) ; } if (rec.type.ss) { traceWrite( &hdr, &rec_ss[irec*rec.nt], nsam, fpss) ; } if (rec.type.ud && mod.ischeme==1) { traceWrite( &hdr, &rec_up[irec*rec.nt], nsam, fpup) ; traceWrite( &hdr, &rec_down[irec*rec.nt], nsam, fpdown) ; } } if (rec.type.vx) fclose(fpvx); if (rec.type.vz) fclose(fpvz); if (rec.type.p) fclose(fpp); if (rec.type.txx) fclose(fptxx); if (rec.type.tzz) fclose(fptzz); if (rec.type.txz) fclose(fptxz); if (rec.type.pp) fclose(fppp); if (rec.type.ss) fclose(fpss); if (rec.type.ud) { fclose(fpup); fclose(fpdown); free(rec_up); free(rec_down); } return 0; }
void kwZoMigr(float *data, int nx, int nt, float dt, float *velmod, int nxm, int nzm, int ixa, int ixb, float fmin, float fmax, float *xrcv, int izrcv, float ox, float dxm, float dz, int ntap, int conjg, int ndepth, float *image, int verbose, float *exrcv, int ndepthex) { int iomin, iomax, iom, ix, d, i, j; int nfreq, optn, nkx, sign, endkx; int ixrcv, ixmin, ixmax, ixo, ixn, ikx; float k, k2, kz2, kx, kx2; float dom, om, c, dkx, df, sr; float *taper, scl, scl2, *pdata; float *trace; complex *ctrace; float t0, t1; complex *cdata, tmp, ez; complex wa, *ctmp, da, *locdat; complex *cexrcv=(complex *) exrcv; /* define some constants */ optn = optncr(nt); nfreq = optn/2 + 1; df = 1.0/(optn*dt); dom = 2.0*M_PI*df; iomin = (int)MIN((fmin*dt*optn), (nfreq-1)); iomin = MAX(iomin, 1); iomax = MIN((int)(fmax*dt*optn), (nfreq-1)); /* transformation of shot record to frequency domain */ trace = (float *)calloc(optn,sizeof(float)); ctrace = (complex *)malloc(optn*sizeof(complex)); cdata = (complex *)calloc(nxm*nfreq, sizeof(complex)); if (conjg) scl = -1.0; else scl = 1.0; sign = -1; for (ix = 0; ix < nx; ix++) { memcpy(trace,&data[ix*nt],nt*sizeof(float)); if (optn > nt) memset( &trace[nt], 0, sizeof(float)*(optn-nt) ); rc1fft(trace,ctrace,optn,sign); ixrcv = NINT((xrcv[ix]-ox)/dxm); if (ixrcv < 0 || ixrcv > nxm-1) { fprintf(stderr,"kwZoMigr: ixrcv %f (%d) outside model\n", xrcv[ix], ixrcv); continue; } for (iom=0; iom<nfreq; iom++) { /* positioning of shot record into velocity model */ cdata[iom*nxm+ixrcv].r = ctrace[iom].r; cdata[iom*nxm+ixrcv].i = ctrace[iom].i*scl; } } /* determine aperture to be calculated */ ixo = nxm; ixn = 0; for (ix = 0; ix < nx; ix++) { ixrcv = NINT((xrcv[ix]-ox)/dxm); if (ixrcv < ixo) ixo = ixrcv; if (ixrcv > ixn) ixn = ixrcv; } ixmin = MAX(0, ixo-ixb-1); ixmax = MIN(ixn+ixa+1, nxm-1); nx = (ixmax-ixmin)+1; if (verbose>=2) { vmess("kwZoMigr: calculation aperture: %.2f (%d) <--> %.2f (%d) (%d positions)", ixmin*dxm+ox, ixmin, ixmax*dxm+ox, ixmax, nx); } /* define some constants */ scl = 2.0/nfreq; scl = 1.0/(dt*dxm*dxm); nkx = optncc(2*ntap+nxm); ntap = (nkx-nxm)/2; scl2 = 1.0/nkx; dkx = 2.0*M_PI/(nkx*dxm); taper = (float *)malloc(ntap*sizeof(float)); for (ix = 0; ix < ntap; ix++) { taper[ix] = exp(-1.0*(pow((0.4*(ntap-ix)/ntap), 2))); } /* calculate image at depth = 0 */ if(izrcv==0 ) { for (ix = ixmin; ix <= ixmax; ix++) { for (iom = iomin; iom <= iomax; iom++) { image[ix*nzm+0] += scl*cdata[iom*nxm+ix].r; } } } t0 = wallclock_time(); locdat = (complex *)malloc(nkx*sizeof(complex)); /* start extrapolation for all frequencies, depths and x-positions */ for (iom = iomin; iom <= iomax; iom++) { memset(locdat,0,nkx*sizeof(complex)); for (ix = ixmin; ix <= ixmax; ix++) { locdat[ntap+ix] = cdata[iom*nxm+ix]; } om = iom*dom; d = izrcv; /* start extrapolation of receiver arrays */ for (; d < ndepth; d++) { /* transform to wavenumber domain */ cc1fft(locdat, nkx, 1); /* Extrapolation of data */ c = 0.0; for (ix = ixmin; ix <= ixmax; ix++) c += velmod[d*nxm+ix]; k = nx*om/c; k2 = k*k; /* kx = 0 */ ez.r = cos(k*dz); ez.i = -sin(k*dz); tmp.r = ez.r*locdat[0].r; tmp.r += ez.i*locdat[0].i; tmp.i = ez.r*locdat[0].i; tmp.i -= ez.i*locdat[0].r; locdat[0] = tmp; /* kx != 0 */ endkx = MIN((int)(k/dkx),nkx/2); for (ikx = 1; ikx <= endkx; ikx++) { kx = ikx*dkx; kx2 = kx*kx; kz2 = k2 - kx2; ez.r = cos(sqrt(kz2)*dz); ez.i = -sin(sqrt(kz2)*dz); tmp.r = ez.r*locdat[ikx].r; tmp.r += ez.i*locdat[ikx].i; tmp.i = ez.r*locdat[ikx].i; tmp.i -= ez.i*locdat[ikx].r; locdat[ikx] = tmp; tmp.r = ez.r*locdat[nkx-ikx].r; tmp.r += ez.i*locdat[nkx-ikx].i; tmp.i = ez.r*locdat[nkx-ikx].i; tmp.i -= ez.i*locdat[nkx-ikx].r; locdat[nkx-ikx] = tmp; } /* transform data back to space domain */ cc1fft(locdat, nkx, -1); for (j = 0; j < nkx; j++) { locdat[j].r *= scl2; locdat[j].i *= scl2; } /* imaging condition */ for (ix = ixmin; ix <= ixmax; ix++) { image[ix*nzm+d+1]+= scl*locdat[ntap+ix].r; } /* save extrapolated field at requested depth */ if (d==ndepthex-1) { if ( cexrcv != NULL ) { for (ix = 0; ix < nxm; ix++) { cexrcv[iom*nxm+ix] = locdat[ntap+ix]; } } } /* taper extrapolated data at edges */ for (j = 0; j < ntap; j++) { locdat[j].r *= taper[j]; locdat[j].i *= taper[j]; locdat[nkx-j-1].r *= taper[j]; locdat[nkx-j-1].i *= taper[j]; } } /* end of depth loop */ } /* end of iom loop */ if(exrcv) wx2xt(cexrcv, exrcv, optn, nxm, nxm, optn); free(locdat); free(cdata); free(taper); t1 = wallclock_time(); vmess("kwZoMigr took: %f seconds", t1-t0); return; }
int main (int argc, char **argv) { FILE *fp; char *file_gp, *file_fp, *file_wav; int nx, nt, ngath, ntraces, ret, size, nxwav; int ntfft, nfreq, nxfft, nkx, i, j, n; float dx, dt, fx, ft, xmin, xmax, scl, *den, dentmp; float df, dw, dkx, eps, reps, leps, sclfk; float *Gpd, *f1pd, *G_pad, *f_pad, *wav, *wav_pad, *outdata; complex *G_w, *f_w, *Gf, *amp, *wav_w, *S, *ZS, *SS; segy *hdr_gp, *hdr_fp, *hdr_wav, *hdr_out; initargs(argc, argv); requestdoc(1); if(!getparstring("file_gp", &file_gp)) file_gp=NULL; if (file_gp==NULL) verr("file %s does not exist",file_gp); if(!getparstring("file_fp", &file_fp)) file_fp=NULL; if (file_fp==NULL) verr("file %s does not exist",file_fp); if(!getparstring("file_wav", &file_wav)) file_wav=NULL; if (file_wav==NULL) verr("file %s does not exist",file_wav); if(!getparfloat("eps", &eps)) eps=0.00; if(!getparfloat("reps", &reps)) reps=0.01; ngath = 1; ret = getFileInfo(file_gp, &nt, &nx, &ngath, &dt, &dx, &ft, &fx, &xmin, &xmax, &scl, &ntraces); size = nt*nx; Gpd = (float *)malloc(size*sizeof(float)); hdr_gp = (segy *) calloc(nx,sizeof(segy)); fp = fopen(file_gp, "r"); if (fp == NULL) verr("error on opening input file_in1=%s", file_gp); nx = readData(fp, Gpd, hdr_gp, nt); fclose(fp); f1pd = (float *)malloc(size*sizeof(float)); hdr_fp = (segy *) calloc(nx,sizeof(segy)); fp = fopen(file_fp, "r"); if (fp == NULL) verr("error on opening input file_in1=%s", file_fp); nx = readData(fp, f1pd, hdr_fp, nt); fclose(fp); wav = (float *)malloc(nt*sizeof(float)); hdr_wav = (segy *) calloc(1,sizeof(segy)); fp = fopen(file_wav, "r"); if (fp == NULL) verr("error on opening input file_in1=%s", file_fp); nxwav = readData(fp, wav, hdr_wav, nt); fclose(fp); /* Start the scaling */ ntfft = optncr(nt); nfreq = ntfft/2+1; df = 1.0/(ntfft*dt); dw = 2.0*PI*df; nkx = optncc(nx); dkx = 2.0*PI/(nkx*dx); sclfk = dt*(dt*dx)*(dt*dx); vmess("ntfft:%d, nfreq:%d, nkx:%d dx:%.3f dt:%.3f",ntfft,nfreq,nkx,dx,dt); /* Allocate the arrays */ G_pad = (float *)calloc(ntfft*nkx,sizeof(float)); if (G_pad == NULL) verr("memory allocation error for G_pad"); f_pad = (float *)calloc(ntfft*nkx,sizeof(float)); if (f_pad == NULL) verr("memory allocation error for f_pad"); wav_pad = (float *)calloc(ntfft,sizeof(float)); if (wav_pad == NULL) verr("memory allocation error for wav_pad"); G_w = (complex *)calloc(nfreq*nkx,sizeof(complex)); if (G_w == NULL) verr("memory allocation error for G_w"); f_w = (complex *)calloc(nfreq*nkx,sizeof(complex)); if (f_w == NULL) verr("memory allocation error for f_w"); Gf = (complex *)calloc(nfreq*nkx,sizeof(complex)); if (Gf == NULL) verr("memory allocation error for Gf"); wav_w = (complex *)calloc(nfreq*nkx,sizeof(complex)); if (wav_w == NULL) verr("memory allocation error for wav_w"); amp = (complex *)calloc(nfreq*nkx,sizeof(complex)); if (amp == NULL) verr("memory allocation error for amp"); S = (complex *)calloc(nfreq*nkx,sizeof(complex)); if (S == NULL) verr("memory allocation error for S"); ZS = (complex *)calloc(nfreq*nkx,sizeof(complex)); if (ZS == NULL) verr("memory allocation error for ZS"); SS = (complex *)calloc(nfreq*nkx,sizeof(complex)); if (SS == NULL) verr("memory allocation error for SS"); den = (float *)calloc(nfreq*nkx,sizeof(float)); if (den == NULL) verr("memory allocation error for den"); /* pad zeroes in 2 directions to reach FFT lengths */ pad2d_data(Gpd, nt,nx,ntfft,nkx,G_pad); pad2d_data(f1pd,nt,nx,ntfft,nkx,f_pad); pad_data( wav, nt, 1,ntfft, wav_pad); /* double forward FFT */ xt2wkx(&G_pad[0], &G_w[0], ntfft, nkx, ntfft, nkx, 0); xt2wkx(&f_pad[0], &f_w[0], ntfft, nkx, ntfft, nkx, 0); rcmfft(&wav_pad[0], &Gf[0], ntfft, 1, ntfft, nfreq, -1); for (i=0; i<nkx; i++) { for (j=0; j<nfreq; j++) { wav_w[j*nkx+i].r = Gf[j].r; wav_w[j*nkx+i].i = Gf[j].i; } } for (i = 0; i < nkx*nfreq; i++) { Gf[i].r = (G_w[i].r*f_w[i].r - G_w[i].i*f_w[i].i); Gf[i].i = (G_w[i].r*f_w[i].i + G_w[i].i*f_w[i].r); S[i].r = (wav_w[i].r*wav_w[i].r + wav_w[i].i*wav_w[i].i); S[i].i = (wav_w[i].r*wav_w[i].i - wav_w[i].i*wav_w[i].r); ZS[i].r = (Gf[i].r*S[i].r + Gf[i].i*S[i].i); ZS[i].i = (Gf[i].r*S[i].i - Gf[i].i*S[i].r); SS[i].r = (S[i].r*S[i].r + S[i].i*S[i].i); SS[i].i = (S[i].r*S[i].i - S[i].i*S[i].r); if (i==0) dentmp=SS[i].r; else dentmp=MAX(dentmp,SS[i].r); } leps = reps*dentmp+eps; vmess("dentmp:%.4e leps:%.4e",dentmp,leps); for (i = 0; i < nkx*nfreq; i++) { S[i].r = (ZS[i].r*SS[i].r+ZS[i].i*SS[i].i)/(SS[i].r*SS[i].r+SS[i].i*SS[i].i+leps); S[i].i = (ZS[i].i*SS[i].r-ZS[i].r*SS[i].i)/(SS[i].r*SS[i].r+SS[i].i*SS[i].i+leps); amp[i].r = sqrtf(S[i].r*S[i].r+S[i].i*S[i].i); amp[i].i = 0.0; // complex_sqrt(&[i]); if (isnan(amp[i].r)) amp[i].r = 0; if (isnan(amp[i].i)) amp[i].i = 0; if (isinf(amp[i].r)) amp[i].r = 0; if (isinf(amp[i].i)) amp[i].i = 0; Gf[i].r = (G_w[i].r*amp[i].r - G_w[i].i*amp[i].i); Gf[i].i = (G_w[i].r*amp[i].i + G_w[i].i*amp[i].r); } // for (i=0; i<nfreq; i++) { // for (j=0; j<nkx; j++) { // Gpd[j*nfreq+i] = sqrtf(amp[i*nkx+j].r*amp[i*nkx+j].r+amp[i*nkx+j].i*amp[i*nkx+j].i); // } // } // conv_small(G_w, amp, Gf, nkx, nfreq); // Scaled data /* inverse double FFT */ wkx2xt(&Gf[0], &G_pad[0], ntfft, nkx, nkx, ntfft, 0); /* select original samples and traces */ scl = (1.0)/(nkx*ntfft); scl_data(G_pad,ntfft,nx,scl,Gpd ,nt); fp = fopen("out.su", "w+"); ret = writeData(fp, Gpd, hdr_gp, nt, nx); if (ret < 0 ) verr("error on writing output file."); fclose(fp); // fp = fopen("wav.su", "w+"); // for (j=0; j<nkx; j++) { // hdr_gp[j].ns = nfreq; // } // ret = writeData(fp, Gpd, hdr_gp, nfreq, nkx); // if (ret < 0 ) verr("error on writing output file."); // fclose(fp); free(f1pd);free(Gpd);free(hdr_gp);free(hdr_fp); return 0; }
void conv_kxw_sr(complex *src, complex *rec, float *velocity, float om, int ntap, Area *ar) { int ix, iy, ikx, iky, nkx, nky, i, j; int ntapx, ntapy, pos, nx, ny; float k, k2, kz2, kx, kx2, ky, ky2; float dx, dy, dz, c, dkx, dky, ic; float *tapery, *taperx, sclx, scly, scl; complex ez, tmp, *locsrc, *locrec; /* define some constants */ if (om==0.0) om=1.0e-6; nx = ar->ixmax - ar->ixmin+1; ny = ar->iymax - ar->iymin+1; dx = ar->dx; dy = ar->dy; dz = ar->dz; nkx = optncc(2*ntap+nx); nky = optncc(2*ntap+ny); ntapx = (nkx-nx)/2; ntapy = (nky-ny)/2; sclx = 1.0/nkx; scly = 1.0/nky; dkx = 2.0*M_PI/(nkx*dx); dky = 2.0*M_PI/(nky*dy); taperx = (float *)malloc(ntapx*sizeof(float)); for (ix = 0; ix < ntapx; ix++) { taperx[ix] = exp(-1.0*(pow((2.0*(ntapx-ix)/ntapx), 2))); } tapery = (float *)malloc(ntapy*sizeof(float)); for (iy = 0; iy < ntapy; iy++) { tapery[iy] = exp(-1.0*(pow((2.0*(ntapy-iy)/ntapy), 2))); } locsrc = (complex *)calloc(nkx*nky,sizeof(complex)); locrec = (complex *)calloc(nkx*nky,sizeof(complex)); for (iy = 0; iy < ny; iy++) { pos = (ar->iymin+iy)*ar->nx + ar->ixmin; memcpy(&locsrc[(iy+ntapy)*nkx+ntapx], &src[pos], nx*sizeof(complex)); memcpy(&locrec[(iy+ntapy)*nkx+ntapx], &rec[pos], nx*sizeof(complex)); } cc2dfft(locsrc, nkx, nky, nkx, 1); cc2dfft(locrec, nkx, nky, nkx, 1); c = 0.0; for (i = 0; i < ar->nx*ar->ny; i++) c += velocity[i]; c = c/(ar->nx*ar->ny); /* average velocity */ ic = 1.0/c; k = om*ic; k2 = k*k; /* kx,ky = 0 */ ez.r = cos(k*dz); ez.i = sin(k*dz); tmp.r = ez.r*locsrc[0].r; tmp.r += ez.i*locsrc[0].i; tmp.i = ez.r*locsrc[0].i; tmp.i -= ez.i*locsrc[0].r; locsrc[0] = tmp; tmp.r = ez.r*locrec[0].r; tmp.r -= ez.i*locrec[0].i; tmp.i = ez.r*locrec[0].i; tmp.i += ez.i*locrec[0].r; locrec[0] = tmp; /* ky = 0 */ for (ikx = 1; ikx <= (nkx/2); ikx++) { kx = ikx*dkx; kx2 = kx*kx; kz2 = k2 - kx2; if (kz2 >= 0.0) { ez.r = cos(sqrt(kz2)*dz); ez.i = sin(sqrt(kz2)*dz); } else { ez.r = exp(-sqrt(-kz2)*dz); ez.i = 0.0; } tmp.r = ez.r*locsrc[ikx].r; tmp.r += ez.i*locsrc[ikx].i; tmp.i = ez.r*locsrc[ikx].i; tmp.i -= ez.i*locsrc[ikx].r; locsrc[ikx] = tmp; tmp.r = ez.r*locsrc[nkx-ikx].r; tmp.r += ez.i*locsrc[nkx-ikx].i; tmp.i = ez.r*locsrc[nkx-ikx].i; tmp.i -= ez.i*locsrc[nkx-ikx].r; locsrc[nkx-ikx] = tmp; tmp.r = ez.r*locrec[ikx].r; tmp.r -= ez.i*locrec[ikx].i; tmp.i = ez.r*locrec[ikx].i; tmp.i += ez.i*locrec[ikx].r; locrec[ikx] = tmp; tmp.r = ez.r*locrec[nkx-ikx].r; tmp.r -= ez.i*locrec[nkx-ikx].i; tmp.i = ez.r*locrec[nkx-ikx].i; tmp.i += ez.i*locrec[nkx-ikx].r; locrec[nkx-ikx] = tmp; } for (iky = 1; iky <= (nky/2); iky++) { ky = iky*dky; ky2 = ky*ky; /* kx = 0 */ kz2 = k2 - ky2; if (kz2 >= 0.0) { ez.r = cos(sqrt(kz2)*dz); ez.i = sin(sqrt(kz2)*dz); } else { ez.r = exp(-sqrt(-kz2)*dz); ez.i = 0.0; } tmp.r = ez.r*locsrc[iky*nkx].r; tmp.r += ez.i*locsrc[iky*nkx].i; tmp.i = ez.r*locsrc[iky*nkx].i; tmp.i -= ez.i*locsrc[iky*nkx].r; locsrc[iky*nkx] = tmp; tmp.r = ez.r*locsrc[(nky-iky)*nkx].r; tmp.r += ez.i*locsrc[(nky-iky)*nkx].i; tmp.i = ez.r*locsrc[(nky-iky)*nkx].i; tmp.i -= ez.i*locsrc[(nky-iky)*nkx].r; locsrc[(nky-iky)*nkx] = tmp; tmp.r = ez.r*locrec[iky*nkx].r; tmp.r -= ez.i*locrec[iky*nkx].i; tmp.i = ez.r*locrec[iky*nkx].i; tmp.i += ez.i*locrec[iky*nkx].r; locrec[iky*nkx] = tmp; tmp.r = ez.r*locrec[(nky-iky)*nkx].r; tmp.r -= ez.i*locrec[(nky-iky)*nkx].i; tmp.i = ez.r*locrec[(nky-iky)*nkx].i; tmp.i += ez.i*locrec[(nky-iky)*nkx].r; locrec[(nky-iky)*nkx] = tmp; for (ikx = 1; ikx <= (nkx/2); ikx++) { kx = ikx*dkx; kx2 = kx*kx; kz2 = k2 - (kx2 + ky2); if (kz2 >= 0.0) { ez.r = cos(sqrt(kz2)*dz); ez.i = sin(sqrt(kz2)*dz); } else { ez.r = exp(-sqrt(-kz2)*dz); ez.i = 0.0; } tmp.r = ez.r*locsrc[iky*nkx+ikx].r; tmp.r += ez.i*locsrc[iky*nkx+ikx].i; tmp.i = ez.r*locsrc[iky*nkx+ikx].i; tmp.i -= ez.i*locsrc[iky*nkx+ikx].r; locsrc[iky*nkx+ikx] = tmp; tmp.r = ez.r*locsrc[iky*nkx+nkx-ikx].r; tmp.r += ez.i*locsrc[iky*nkx+nkx-ikx].i; tmp.i = ez.r*locsrc[iky*nkx+nkx-ikx].i; tmp.i -= ez.i*locsrc[iky*nkx+nkx-ikx].r; locsrc[iky*nkx+nkx-ikx] = tmp; tmp.r = ez.r*locsrc[(nky-iky)*nkx+ikx].r; tmp.r += ez.i*locsrc[(nky-iky)*nkx+ikx].i; tmp.i = ez.r*locsrc[(nky-iky)*nkx+ikx].i; tmp.i -= ez.i*locsrc[(nky-iky)*nkx+ikx].r; locsrc[(nky-iky)*nkx+ikx] = tmp; tmp.r = ez.r*locsrc[(nky-iky)*nkx+nkx-ikx].r; tmp.r += ez.i*locsrc[(nky-iky)*nkx+nkx-ikx].i; tmp.i = ez.r*locsrc[(nky-iky)*nkx+nkx-ikx].i; tmp.i -= ez.i*locsrc[(nky-iky)*nkx+nkx-ikx].r; locsrc[(nky-iky)*nkx+nkx-ikx] = tmp; tmp.r = ez.r*locrec[iky*nkx+ikx].r; tmp.r -= ez.i*locrec[iky*nkx+ikx].i; tmp.i = ez.r*locrec[iky*nkx+ikx].i; tmp.i += ez.i*locrec[iky*nkx+ikx].r; locrec[iky*nkx+ikx] = tmp; tmp.r = ez.r*locrec[iky*nkx+nkx-ikx].r; tmp.r -= ez.i*locrec[iky*nkx+nkx-ikx].i; tmp.i = ez.r*locrec[iky*nkx+nkx-ikx].i; tmp.i += ez.i*locrec[iky*nkx+nkx-ikx].r; locrec[iky*nkx+nkx-ikx] = tmp; tmp.r = ez.r*locrec[(nky-iky)*nkx+ikx].r; tmp.r -= ez.i*locrec[(nky-iky)*nkx+ikx].i; tmp.i = ez.r*locrec[(nky-iky)*nkx+ikx].i; tmp.i += ez.i*locrec[(nky-iky)*nkx+ikx].r; locrec[(nky-iky)*nkx+ikx] = tmp; tmp.r = ez.r*locrec[(nky-iky)*nkx+nkx-ikx].r; tmp.r -= ez.i*locrec[(nky-iky)*nkx+nkx-ikx].i; tmp.i = ez.r*locrec[(nky-iky)*nkx+nkx-ikx].i; tmp.i += ez.i*locrec[(nky-iky)*nkx+nkx-ikx].r; locrec[(nky-iky)*nkx+nkx-ikx] = tmp; } } cc2dfft(locsrc, nkx, nky, nkx, -1); cc2dfft(locrec, nkx, nky, nkx, -1); /* taper the edges to suppress wrap-around */ for (iy = 0; iy < ny; iy++) { pos = iy*nkx; for (j = 0; j < ntapx; j++) { locsrc[pos+j].r *= taperx[j]; locsrc[pos+j].i *= taperx[j]; locsrc[pos+nkx-j-1].r *= taperx[j]; locsrc[pos+nkx-j-1].i *= taperx[j]; } } for (iy = 0; iy < ntapy; iy++) { pos = iy*nkx; for (j = 0; j < nx; j++) { locsrc[pos+j].r *= tapery[iy]; locsrc[pos+j].i *= tapery[iy]; locsrc[(nky-iy-1)*nkx+j].r *= tapery[iy]; locsrc[(nky-iy-1)*nkx+j].i *= tapery[iy]; } } for (iy = 0; iy < ny; iy++) { pos = iy*nkx; for (j = 0; j < ntapx; j++) { locrec[pos+j].r *= taperx[j]; locrec[pos+j].i *= taperx[j]; locrec[pos+nkx-j-1].r *= taperx[j]; locrec[pos+nkx-j-1].i *= taperx[j]; } } for (iy = 0; iy < ntapy; iy++) { pos = iy*nkx; for (j = 0; j < nx; j++) { locrec[pos+j].r *= tapery[iy]; locrec[pos+j].i *= tapery[iy]; locrec[(nky-iy-1)*nkx+j].r *= tapery[iy]; locrec[(nky-iy-1)*nkx+j].i *= tapery[iy]; } } /* correction term */ scl = sclx*scly; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { pos = (ar->iymin+iy)*ar->nx + ar->ixmin + ix; k = (1.0/velocity[pos] - ic)*dz*om; ez.r = cos(k); ez.i = sin(k); tmp.r = ez.r*locsrc[(iy+ntapy)*nkx+ntapx+ix].r; tmp.r += ez.i*locsrc[(iy+ntapy)*nkx+ntapx+ix].i; tmp.i = ez.r*locsrc[(iy+ntapy)*nkx+ntapx+ix].i; tmp.i -= ez.i*locsrc[(iy+ntapy)*nkx+ntapx+ix].r; src[pos].r = tmp.r*scl; src[pos].i = tmp.i*scl; tmp.r = ez.r*locrec[(iy+ntapy)*nkx+ntapx+ix].r; tmp.r -= ez.i*locrec[(iy+ntapy)*nkx+ntapx+ix].i; tmp.i = ez.r*locrec[(iy+ntapy)*nkx+ntapx+ix].i; tmp.i += ez.i*locrec[(iy+ntapy)*nkx+ntapx+ix].r; rec[pos].r = tmp.r*scl; rec[pos].i = tmp.i*scl; } } free(taperx); free(tapery); free(locsrc); free(locrec); return; }