#define _FILE_OFFSET_BITS 64 #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <math.h> #include <string.h> #include "fdelmodc.h" #include "segy.h" /** * Computes, or read from file, the source signature * * AUTHOR: * Jan Thorbecke (janth@xs4all.nl) * The Netherlands **/ #ifndef COMPLEX typedef struct _complexStruct { /* complex number */ float r,i; } complex; typedef struct _dcomplexStruct { /* complex number */ double r,i; } dcomplex; #endif/* complex */ int optncr(int n); void rc1fft(float *rdata, complex *cdata, int n, int sign); void cr1fft(complex *cdata, float *rdata, int n, int sign); int writesufile(char *filename, float *data, int n1, int n2, float f1, float f2, float d1, float d2); int writesufilesrcnwav(char *filename, float **src_nwav, wavPar wav, int n1, int n2, float f1, float f2, float d1, float d2); float gaussGen(); float normal(double x,double mu,double sigma); int comp (const float *a, const float *b); void spline3(float x1, float x2, float z1, float z2, float dzdx1, float dzdx2, float *a, float *b, float *c, float *d); int randomWavelet(wavPar wav, srcPar src, float *trace, float tbeg, float tend, int verbose); /* random number generators */ double dcmwc4096(); unsigned long CMWC4096(void); unsigned long xorshift(void); void seedCMWC4096(void); /* #define drand48 dcmwc4096 use for different random number generator */ #define MAX(x,y) ((x) > (y) ? (x) : (y)) #define MIN(x,y) ((x) < (y) ? (x) : (y)) #define NINT(x) ((int)((x)>0.0?(x)+0.5:(x)-0.5)) int defineSource(wavPar wav, srcPar src, modPar mod, recPar rec, float **src_nwav, int reverse, int verbose) { FILE *fp; size_t nread; int optn, nfreq, i, j, k, iwmax, tracesToDo; int iw, n1, namp, optnscale, nfreqscale; float scl, d1, df, deltom, om, tshift; float amp1, amp2, amp3; float *trace, maxampl, scale; complex *ctrace, tmp; segy hdr; scale = 1.0; n1 = wav.ns; if (wav.random) { /* initialize random sequence */ srand48(wav.seed+1); seedCMWC4096(); for (i=0; i<8192; i++) { amp1 = dcmwc4096(); } } else { /* read first header and last byte to get file size */ fp = fopen( wav.file_src, "r" ); assert( fp != NULL); nread = fread( &hdr, 1, TRCBYTES, fp ); assert(nread == TRCBYTES); /* read all traces */ tracesToDo = wav.nx; i = 0; while (tracesToDo) { memset(&src_nwav[i][0],0,wav.nt*sizeof(float)); nread = fread(&src_nwav[i][0], sizeof(float), hdr.ns, fp); assert (nread == hdr.ns); nread = fread( &hdr, 1, TRCBYTES, fp ); if (nread==0) break; tracesToDo--; i++; } fclose(fp); } optn = optncr(n1); nfreq = optn/2 + 1; if (wav.nt != wav.ns) { vmess("Sampling in wavelet is %e while for modeling is set to %e", wav.ds, mod.dt); vmess("Wavelet sampling will be FFT-interpolated to sampling of modeling"); vmess("file_src Nt=%d sampling after interpolation=%d", wav.ns, wav.nt); optnscale = wav.nt; nfreqscale = optnscale/2 + 1; } else { optnscale = optn; nfreqscale = optnscale/2 + 1; } // fprintf(stderr,"define S optn=%d ns=%d %e nt=%d %e\n", optn, wav.ns, wav.ds, optnscale, wav.dt); ctrace = (complex *)calloc(nfreqscale,sizeof(complex)); trace = (float *)calloc(optnscale,sizeof(float)); df = 1.0/(optn*wav.ds); deltom = 2.*M_PI*df; scl = 1.0/optn; iwmax = nfreq; for (i=0; i<wav.nx; i++) { if (wav.random) { randomWavelet(wav, src, &src_nwav[i][0], src.tbeg[i], src.tend[i], verbose); } else { memset(&ctrace[0].r,0,nfreqscale*sizeof(complex)); memset(&trace[0],0,optnscale*sizeof(float)); memcpy(&trace[0],&src_nwav[i][0],n1*sizeof(float)); rc1fft(trace,ctrace,optn,-1); /* Scale source from file with -j/w (=1/(jw)) for volume source injections no scaling is applied for volume source injection rates */ if (src.injectionrate==0) { for (iw=1;iw<iwmax;iw++) { om = 1.0/(deltom*iw); tmp.r = om*ctrace[iw].i; tmp.i = -om*ctrace[iw].r; ctrace[iw].r = tmp.r; ctrace[iw].i = tmp.i; } } if (src.type < 6) { // shift wavelet with +1/2 DeltaT due to staggered in time tshift=-(0.5*rec.skipdt+1.5)*wav.dt; for (iw=1;iw<iwmax;iw++) { om = deltom*iw*tshift; tmp.r = ctrace[iw].r*cos(-om) - ctrace[iw].i*sin(-om); tmp.i = ctrace[iw].i*cos(-om) + ctrace[iw].r*sin(-om); ctrace[iw].r = tmp.r; ctrace[iw].i = tmp.i; } } /* zero frequency iw=0 set to 0 if the next sample has amplitude==0*/ amp1 = sqrt(ctrace[1].r*ctrace[1].r+ctrace[1].i*ctrace[1].i); if (amp1 == 0.0) { ctrace[0].r = ctrace[0].i = 0.0; } else { /* stabilization for w=0: extrapolate amplitudes to 0 */ amp2 = sqrt(ctrace[2].r*ctrace[2].r+ctrace[2].i*ctrace[2].i); amp3 = sqrt(ctrace[3].r*ctrace[3].r+ctrace[3].i*ctrace[3].i); ctrace[0].r = amp1+(2.0*(amp1-amp2)-(amp2-amp3)); ctrace[0].i = 0.0; if (ctrace[1].r < 0.0) { ctrace[0].r *= -1.0; } } for (iw=iwmax;iw<nfreqscale;iw++) { ctrace[iw].r = 0.0; ctrace[iw].i = 0.0; } memset(&trace[0],0,optnscale*sizeof(float)); cr1fft(ctrace,trace,optnscale,1); /* avoid a (small) spike in the last sample this is done to avoid diffraction from last wavelet sample which will act as a pulse */ maxampl=0.0; if (reverse) { for (j=0; j<wav.nt; j++) { src_nwav[i][j] = scl*(trace[wav.nt-j-1]-trace[0]); maxampl = MAX(maxampl,fabs(src_nwav[i][j])); } } else { for (j=0; j<wav.nt; j++) { src_nwav[i][j] = scl*(trace[j]-trace[wav.nt-1]); maxampl = MAX(maxampl,fabs(src_nwav[i][j])); } } if (verbose > 3) vmess("Wavelet sampling (FFT-interpolated) done for trace %d", i); } } /* set values smaller than 1e-5 maxampl to zero */ maxampl *= 1e-5; for (i=0; i<wav.nx; i++) { for (j=0; j<wav.nt; j++) { if (fabs(src_nwav[i][j]) < maxampl) src_nwav[i][j] = 0.0; } } free(ctrace); free(trace); /* use random amplitude gain factor for each source */ if (src.amplitude > 0.0) { namp=wav.nx*10; trace = (float *)calloc(2*namp,sizeof(float)); for (i=0; i<wav.nx; i++) { if (src.distribution) { scl = gaussGen()*src.amplitude; k = (int)MAX(MIN(namp*(scl+5*src.amplitude)/(10*src.amplitude),namp-1),0); d1 = 10.0*src.amplitude/(namp-1); } else { scl = (float)(drand48()-0.5)*src.amplitude; k = (int)MAX(MIN(namp*(scl+1*src.amplitude)/(2*src.amplitude),namp-1),0); d1 = 2.0*src.amplitude/(namp-1); } trace[k] += 1.0; /* trace[i] = scl; */ if (wav.random) n1 = wav.nsamp[i]; else n1 = wav.nt; for (j=0; j<n1; j++) { src_nwav[i][j] *= scl; } } if (verbose>2) writesufile("src_ampl.su", trace, namp, 1, -5*src.amplitude, 0.0, d1, 1); /* qsort(trace,wav.nx,sizeof(float), comp); for (i=0; i<wav.nx; i++) { scl = trace[i]; trace[i] = normal(scl, 0.0, src.amplitude); } if (verbose>2) writesufile("src_ampl.su", trace, wav.nx, 1, -5*src.amplitude, 0.0, d1, 1); */ free(trace); } if (verbose>3) writesufilesrcnwav("src_nwav.su", src_nwav, wav, wav.nt, wav.nx, 0.0, 0.0, wav.dt, 1); /* set maximum amplitude in source file to 1.0 */ /* assert(maxampl != 0.0); scl = wav.dt/(maxampl); scl = 1.0/(maxampl); for (i=0; i<wav.nx; i++) { for (j=0; j<n1; j++) { src_nwav[i*n1+j] *= scl; } } */ return 0; } int randomWavelet(wavPar wav, srcPar src, float *trace, float tbeg, float tend, int verbose) { int optn, nfreq, j, iwmax; int iw, n1, itbeg, itmax, nsmth; float df, amp1; float *rtrace; float x1, x2, z1, z2, dzdx1, dzdx2, a, b, c, d, t; complex *ctrace; n1 = wav.nt; /* this is set to the maximum length (tlength/dt) */ optn = optncr(2*n1); nfreq = optn/2 + 1; ctrace = (complex *)calloc(nfreq,sizeof(complex)); rtrace = (float *)calloc(optn,sizeof(float)); df = 1.0/(optn*wav.dt); iwmax = MIN(NINT(wav.fmax/df),nfreq); for (iw=1;iw<iwmax;iw++) { ctrace[iw].r = (float)(drand48()-0.5); ctrace[iw].i = (float)(drand48()-0.5); } for (iw=iwmax;iw<nfreq;iw++) { ctrace[iw].r = 0.0; ctrace[iw].i = 0.0; } cr1fft(ctrace,rtrace,optn,1); /* find first zero crossing in wavelet */ amp1 = rtrace[0]; j = 1; if (amp1 < 0.0) { while (rtrace[j] < 0.0) j++; } else { while (rtrace[j] > 0.0) j++; } itbeg = j; /* find last zero crossing in wavelet */ // itmax = itbeg+MIN(NINT((tend-tbeg)/wav.dt),n1); itmax = MIN(NINT(itbeg+(tend-tbeg)/wav.dt),n1); amp1 = rtrace[itmax-1]; j = itmax; if (amp1 < 0.0) { while (rtrace[j] < 0.0 && j>itbeg) j--; } else { while (rtrace[j] > 0.0 && j>itbeg) j--; } itmax = j; /* make smooth transitions to zero aamplitude */ nsmth=MIN(10,itmax); x1 = 0.0; z1 = 0.0; dzdx1 = 0.0; x2 = nsmth; z2 = rtrace[itbeg+nsmth]; // dzdx2 = (rtrace[itbeg+(nsmth+1)]-rtrace[itbeg+(nsmth-1)])/(2.0); dzdx2 = (rtrace[itbeg+nsmth-2]-8.0*rtrace[itbeg+nsmth-1]+ 8.0*rtrace[itbeg+nsmth+1]-rtrace[itbeg+nsmth+2])/(12.0); spline3(x1, x2, z1, z2, dzdx1, dzdx2, &a, &b, &c, &d); for (j=0; j<nsmth; j++) { t = j; rtrace[itbeg+j] = a*t*t*t+b*t*t+c*t+d; } x1 = 0.0; z1 = rtrace[itmax-nsmth]; // dzdx1 = (rtrace[itmax-(nsmth-1)]-rtrace[itmax-(nsmth+1)])/(2.0); dzdx1 = (rtrace[itmax-nsmth-2]-8.0*rtrace[itmax-nsmth-1]+ 8.0*rtrace[itmax-nsmth+1]-rtrace[itmax-nsmth+2])/(12.0); x2 = nsmth; z2 = 0.0; dzdx2 = 0.0; // fprintf(stderr,"x1=%f z1=%f d=%f x2=%f, z2=%f d=%f\n",x1,z1,dzdx1,x2,z2,dzdx2); spline3(x1, x2, z1, z2, dzdx1, dzdx2, &a, &b, &c, &d); for (j=0; j<nsmth; j++) { t = j; rtrace[itmax-nsmth+j] = a*t*t*t+b*t*t+c*t+d; // fprintf(stderr,"a=%f b=%f c=%f d=%f rtrace%d=%f \n",a,b,c,d,j,rtrace[itmax-nsmth+j]); } for (j=itbeg; j<itmax; j++) trace[j-itbeg] = rtrace[j]; free(ctrace); free(rtrace); return 0; } float normal(double x,double mu,double sigma) { return (float)(1.0/(2.0*M_PI*sigma*sigma))*exp(-1.0*(((x-mu)*(x-mu))/(2.0*sigma*sigma)) ); } int comp (const float *a, const float *b) { if (*a==*b) return 0; else if (*a < *b) return -1; else return 1; }