void maketrace(float *trace,int nt,float ft,float dt, float xs,float xg,float **mig,float **migi,float aperx, int nx,float fx,float dx,int nz,float fz,float dz, int mzmax,int ls,float angmax,float v0,float fmax,Wavelet *w, float **tb,float **pb,float **sigb,float **cosb,int nr,float **tsum, int nxt,float fxt,float dxt,int nzt,float fzt,float dzt) /***************************************************************************** Make one synthetic seismogram ****************************************************************************** Input: **mig migration section **migi integrated migration section nt number of time samples in seismic trace ft first time sample of seismic trace dt time sampleing interval in seismic trace xs,xg lateral coordinates of source and geophone aperx lateral aperature in migration nx,fx,dx,nz,fz,dz dimension parameters of migration region mzmax number of depth samples in triangle filter ls =1 for line source; =0 for point source w wavelet to convolve with trace angmax migration angle aperature from vertical tb,pb,sigb,cosb reference traveltime, lateral slowness, sigma and cosine of emergent angle nr number of lateral samples in reference quantities tsum sum of residual traveltimes from shot and receiver nxt,fxt,dxt,nzt,fzt,dzt dimension parameters of traveltime table Output: trace array[nt] containing synthetic seismogram *****************************************************************************/ { int nxf,nxe,nxtf,nxte,ix,iz,iz0,izt0,nzp,jrs,jrg,jz,jt,jx,mz,iz1; float xm,x,dis,rxz,ar,srs,srg,srs0,srg0,sigp,z0,rdz,ampd, sigs,sigg,coss,cosg,ax,ax0,pmin, odt=1.0/dt,pd,az,sz,sz0,at,td,res,temp; float *zpt,**ampt,**ampti,**zmt,*amp,*ampi,*zm,*tzt,*work1; int lhd=LHD,nhd=NHD; static float hd[NHD]; static int madehd=0; /* if half-derivative filter not yet made, make it */ if (!madehd) { mkhdiff(dt,lhd,hd); madehd = 1; } /* zero trace */ for (jt=0; jt<nt; ++jt) trace[jt] = 0.0; zmt = ealloc2float(nzt,nxt); ampt = ealloc2float(nzt,nxt); ampti = ealloc2float(nzt,nxt); amp = ealloc1float(nzt); ampi = ealloc1float(nzt); zm = ealloc1float(nzt); tzt = ealloc1float(nzt); zpt = ealloc1float(nxt); work1 = ealloc1float(nt); z0 = (fz-fzt)/dzt; pmin = 1.0/(2.0*dx*fmax); rdz = dz/dzt; xm = 0.5*(xs+xg); rxz = (angmax==90)?0.0:1.0/tan(angmax*PI/180.); nxtf = (xm-aperx-fxt)/dxt; if(nxtf<0) nxtf = 0; nxte = (xm+aperx-fxt)/dxt+1.0; if(nxte>=nxt) nxte = nxt-1; /* compute amplitudes */ for(ix=nxtf; ix<=nxte; ++ix){ x = fxt+ix*dxt; dis = (xm>=x)?xm-x:x-xm; izt0 = ((dis-dxt)*rxz-fzt)/dzt-1; if(izt0<0) izt0 = 0; if(izt0>=nzt) izt0 = nzt-1; ar = (xs>=x)?(xs-x)/dx:(x-xs)/dx; jrs = (int)ar; if(jrs>nr-2) jrs = nr-2; srs = ar-jrs; srs0 = 1.0-srs; ar = (xg>=x)?(xg-x)/dx:(x-xg)/dx; jrg = (int)ar; if(jrg>nr-2) jrg = nr-2; srg = ar-jrg; srg0 = 1.0-srg; sigp = ((xs-x)*(xg-x)>0)?1.0:-1.0; zpt[ix] = fzt+(nzt-1)*dzt; for(iz=izt0; iz<nzt; ++iz){ sigs = srs0*sigb[jrs][iz]+srs*sigb[jrs+1][iz]; sigg = srg0*sigb[jrg][iz]+srg*sigb[jrg+1][iz]; coss = srs0*cosb[jrs][iz]+srs*cosb[jrs+1][iz]; cosg = srg0*cosb[jrg][iz]+srg*cosb[jrg+1][iz]; ampd = v0*dx*(coss+cosg)*dz; if(ampd<0.0) ampd = -ampd; if(ls) ampt[ix][iz] = ampd/sqrt(v0*sigs*sigg); else ampt[ix][iz] = ampd/sqrt(sigs*sigg*(sigs+sigg)); pd = srs0*pb[jrs][iz]+srs*pb[jrs+1][iz]+sigp *(srg0*pb[jrg][iz]+srg*pb[jrg+1][iz]); if(pd<0.0) pd = -pd; if(pd<0.0) pd = -pd; temp = 0.5*pd*v0*dx/dz; if(temp<1) temp = 1.0; if(temp>mzmax) temp = mzmax; ampti[ix][iz] = ampt[ix][iz]/(temp*temp); zmt[ix][iz] = temp; if(pd<pmin && zpt[ix]>fzt+(nzt-1.1)*dzt) zpt[ix] = fzt+iz*dzt; } } nxf = (xm-aperx-fx)/dx+0.5; if(nxf<0) nxf = 0; nxe = (xm+aperx-fx)/dx+0.5; if(nxe>=nx) nxe = nx-1; /* interpolate amplitudes */ for(ix=nxf; ix<=nxe; ++ix){ x = fx+ix*dx; dis = (xm>=x)?xm-x:x-xm; izt0 = (dis*rxz-fzt)/dzt-1; if(izt0<0) izt0 = 0; if(izt0>=nzt) izt0 = nzt-1; iz0 = (dis*rxz-fz)/dz; if(iz0<0) iz0 = 0; if(iz0>=nz) iz0 = nz-1; ax = (x-fxt)/dxt; jx = (int)ax; ax = ax-jx; if(ax<=0.01) ax = 0.; if(ax>=0.99) ax = 1.0; ax0 = 1.0-ax; if(jx>nxte-1) jx = nxte-1; if(jx<nxtf) jx = nxtf; ar = (xs>=x)?(xs-x)/dx:(x-xs)/dx; jrs = (int)ar; if(jrs>=nr-1) jrs = nr-2; srs = ar-jrs; srs0 = 1.0-srs; ar = (xg>=x)?(xg-x)/dx:(x-xg)/dx; jrg = (int)ar; if(jrg>=nr-1) jrg = nr-2; srg = ar-jrg; srg0 = 1.0-srg; for(iz=izt0; iz<nzt; ++iz){ tzt[iz] = ax0*tsum[jx][iz]+ax*tsum[jx+1][iz] +srs0*tb[jrs][iz]+srs*tb[jrs+1][iz] +srg0*tb[jrg][iz]+srg*tb[jrg+1][iz]; amp[iz] = ax0*ampt[jx][iz]+ax*ampt[jx+1][iz]; ampi[iz] = ax0*ampti[jx][iz]+ax*ampti[jx+1][iz]; zm[iz] = ax0*zmt[jx][iz]+ax*zmt[jx+1][iz]; } nzp = (ax0*zpt[jx]+ax*zpt[jx+1]-fz)/dz+1.5; if(nzp<iz0) nzp = iz0; if(nzp>nz) nzp = nz; /* interpolate along depth if operater aliasing */ for(iz=iz0; iz<nzp; ++iz) { az = z0+iz*rdz; jz = (int)az; if(jz>=nzt-1) jz = nzt-2; sz = az-jz; sz0 = 1.0-sz; td = sz0*tzt[jz]+sz*tzt[jz+1]; at = (td-ft)*odt; jt = (int)at; if(jt > 0 && jt < nt-1){ ampd = sz0*ampi[jz]+sz*ampi[jz+1]; mz = (int)(0.5+sz0*zm[jz]+sz*zm[jz+1]); res = at-jt; iz1 = iz+mzmax; temp = (-migi[ix][iz1-mz]+2.0*migi[ix][iz1] -migi[ix][iz1+mz])*ampd; trace[jt] += (1.0-res)*temp; trace[jt+1] += res*temp; } } /* interpolate along depth if not operater aliasing */ for(iz=nzp; iz<nz; ++iz) { az = z0+iz*rdz; jz = (int)az; if(jz>=nzt-1) jz = nzt-2; sz = az-jz; sz0 = 1.0-sz; td = sz0*tzt[jz]+sz*tzt[jz+1]; at = (td-ft)*odt; jt = (int)at; if(jt > 0 && jt < nt-1){ ampd = sz0*amp[jz]+sz*amp[jz+1]; res = at-jt; temp = mig[ix][iz]*ampd; trace[jt] += (1.0-res)*temp; trace[jt+1] += res*temp; } } } /* apply half-derivative filter to trace */ convolve_cwp(nhd,-lhd,hd,nt,0,trace,nt,0,work1); /* convolve wavelet with trace */ convolve_cwp(w->lw,w->iw,w->wv,nt,0,work1,nt,0,trace); /* free workspace */ free2float(ampt); free2float(ampti); free1float(tzt); free1float(work1); free1float(amp); free1float(ampi); free2float(zmt); free1float(zpt); free1float(zm); }
static void makeone (float **ts, float **as, float **sgs, float **tg, float **ag, float **sgg, float ex, float ez, float dx, float dz, float fx, float vs0, float vg0, int ls, Wavelet *w, int nr, Reflector *r, int nt, float dt, float ft, float *trace) /***************************************************************************** Make one synthetic seismogram ****************************************************************************** Input: **v array[nx][nz] containing velocities nz number of z samples dz z sampling interval nx number of x samples dx x sampling interval fx first x sample ls =1 for line source amplitudes; =0 for point source w wavelet to convolve with trace xs x coordinate of source xg x coordinate of receiver group nr number of reflectors r array[nr] of reflectors nt number of time samples dt time sampling interval ft first time sample Output: trace array[nt] containing synthetic seismogram *****************************************************************************/ { int it,ir,is,ns,ix,iz; float ar,ds,xd,zd,cd,sd,xi,zi,ci,cr,time,amp,sx,sz, tsd,asd,sgsd,tgd,agd,sggd, *temp; ReflectorSegment *rs; int lhd=LHD,nhd=NHD; static float hd[NHD]; static int madehd=0; /* if half-derivative filter not yet made, make it */ if (!madehd) { mkhdiff(dt,lhd,hd); madehd = 1; } /* zero trace */ for (it=0; it<nt; ++it) trace[it] = 0.0; /* loop over reflectors */ for (ir=0; ir<nr; ++ir) { /* amplitude, number of segments, segment length */ ar = r[ir].a; ns = r[ir].ns; ds = r[ir].ds; rs = r[ir].rs; /* loop over diffracting segments */ for (is=0; is<ns; ++is) { /* diffractor midpoint, unit-normal, and length */ xd = rs[is].x; zd = rs[is].z; cd = rs[is].c; sd = rs[is].s; /* check range of reflector */ if(xd<fx || xd>=ex || zd>=ez) continue; /* determine sample indices */ xi = (xd-fx)/dx; ix = xi; zi = zd/dz; iz = zi; /* bilinear interpolation */ sx = xi-ix; sz = zi-iz; tsd = (1.0-sz)*((1.0-sx)*ts[ix][iz] + sx*ts[ix+1][iz]) + sz*((1.0-sx)*ts[ix][iz+1] + sx*ts[ix+1][iz+1]); asd = (1.0-sz)*((1.0-sx)*as[ix][iz] + sx*as[ix+1][iz]) + sz*((1.0-sx)*as[ix][iz+1] + sx*as[ix+1][iz+1]); sgsd = (1.0-sz)*((1.0-sx)*sgs[ix][iz] + sx*sgs[ix+1][iz]) + sz*((1.0-sx)*sgs[ix][iz+1] + sx*sgs[ix+1][iz+1]); tgd = (1.0-sz)*((1.0-sx)*tg[ix][iz] + sx*tg[ix+1][iz]) + sz*((1.0-sx)*tg[ix][iz+1] + sx*tg[ix+1][iz+1]); agd = (1.0-sz)*((1.0-sx)*ag[ix][iz] + sx*ag[ix+1][iz]) + sz*((1.0-sx)*ag[ix][iz+1] + sx*ag[ix+1][iz+1]); sggd = (1.0-sz)*((1.0-sx)*sgg[ix][iz] + sx*sgg[ix+1][iz]) + sz*((1.0-sx)*sgg[ix][iz+1] + sx*sgg[ix+1][iz+1]); /* cosines of incidence and reflection angles */ ci = cd*cos(asd)+sd*sin(asd); cr = cd*cos(agd)+sd*sin(agd); /* two-way time and amplitude */ time = tsd+tgd; if (ls) amp = sqrt(vs0*vg0/(sgsd*sggd)); else amp = sqrt(vs0*vg0/(sgsd*sggd*(sgsd+sggd))); amp *= ABS(ci+cr)*ar*ds; /* add sinc wavelet to trace */ addsinc(time,amp,nt,dt,ft,trace); } } /* allocate workspace */ temp = ealloc1float(nt); /* apply half-derivative filter to trace */ conv(nhd,-lhd,hd,nt,0,trace,nt,0,temp); /* convolve wavelet with trace */ conv(w->lw,w->iw,w->wv,nt,0,temp,nt,0,trace); /* free workspace */ free1float(temp); }
static void makeone (float v00, float dvdx, float dvdz, int ls, int er, int ob, int sp, Wavelet *w, float gamma, float xs, float zs, float xg, float zg, int nr, Reflector *r, int nt, float dt, float ft, float *trace) /***************************************************************************** Make one synthetic seismogram for linear velocity v(x,z) = v00+dvdx*x+dvdz*z ****************************************************************************** Input: v00 velocity v at (x=0,z=0) dvdx derivative dv/dx of velocity v with respect to x dvdz derivative dv/dz of velocity v with respect to z ls =1 for line source amplitudes; =0 for point source er =1 for exploding, =0 for normal reflector amplitudes ob =1 to include cos obliquity factors; =0 to omit sp =1 to account for amplitude spreading w wavelet to convolve with trace xs x coordinate of source zs z coordinate of source xg x coordinate of receiver group zg z coordinate of receiver group nr number of reflectors r array[nr] of reflectors nt number of time samples dt time sampling interval ft first time sample Output: trace array[nt] containing synthetic seismogram *****************************************************************************/ { int it,ir,is,ns; float ar,ds,xd,zd,cd,sd,vs,vg,vd,cs,ss,ts,qs,cg,sg,tg,qg, ci,cr,time,amp,*temp,tos; ReflectorSegment *rs; int lhd=LHD,nhd=NHD; static float hd[NHD]; static int madehd=0; /* constant depending on gamma and v00*/ tos = 2.0/(1.0+1.0/gamma); /* if half-derivative filter not yet made, make it */ if (!madehd) { mkhdiff(dt,lhd,hd); madehd = 1; } /* zero trace */ for (it=0; it<nt; ++it) trace[it] = 0.0; /* velocities at source and receiver */ vs = v00+dvdx*xs+dvdz*zs; vg = (v00+dvdx*xg+dvdz*zg)*gamma; /* loop over reflectors */ for (ir=0; ir<nr; ++ir) { /* amplitude, number of segments, segment length */ ar = r[ir].a; ns = r[ir].ns; ds = r[ir].ds; rs = r[ir].rs; /* loop over diffracting segments */ for (is=0; is<ns; ++is) { /* diffractor midpoint, unit-normal, and length */ xd = rs[is].x; zd = rs[is].z; cd = rs[is].c; sd = rs[is].s; /* velocity at diffractor */ vd = (v00+dvdx*xd+dvdz*zd)*tos; /* ray from shot to diffractor */ raylv2(v00,dvdx,dvdz,xs,zs,xd,zd,&cs,&ss,&ts,&qs); /* ray from receiver to diffractor */ raylv2(gamma*v00,gamma*dvdx,gamma*dvdz,xg,zg,xd,zd, &cg,&sg,&tg,&qg); /* cosines of incidence and reflection angles */ if (ob) { ci = cd*cs+sd*ss; cr = cd*cg+sd*sg; } else { ci = 1.0; cr = 1.0; } /* if either cosine is negative, skip diffractor */ if (ci<0.0 || cr<0.0) continue; /* two-way time and amplitude */ time = ts+tg; if (sp) { if (er) { amp = sqrt(vg*vd/qg); } else { if (ls) amp = sqrt((vs*vd*vd*vg)/ (qs*qg)); else amp = sqrt((vs*vd*vd*vg)/ (qs*qg*(qs+qg))); } amp *= (ci+cr)*ar*ds; } else amp = 1.0/sqrt(time); /* add sinc wavelet to trace */ addsinc(time,amp,nt,dt,ft,trace); } } /* allocate workspace */ temp = ealloc1float(nt); /* apply half-derivative filter to trace */ conv(nhd,-lhd,hd,nt,0,trace,nt,0,temp); /* convolve wavelet with trace */ conv(w->lw,w->iw,w->wv,nt,0,temp,nt,0,trace); /* free workspace */ free1float(temp); }