Skip to content
Snippets Groups Projects
defineSource.c 11.42 KiB
#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;
}