diff --git a/marchenko/marchenkojan.c b/marchenko/marchenkojan.c new file mode 100644 index 0000000000000000000000000000000000000000..eaf206db686c04c04feaa15c3cc377d0b5c3f969 --- /dev/null +++ b/marchenko/marchenkojan.c @@ -0,0 +1,786 @@ +/* + * Copyright (c) 2017 by the Society of Exploration Geophysicists. + * For more information, go to http://software.seg.org/2017/00XX . + * You must read and accept usage terms at: + * http://software.seg.org/disclaimer.txt before use. + */ + +#include "par.h" +#include "segy.h" +#include <time.h> +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <assert.h> +#include <genfft.h> + +int omp_get_max_threads(void); +int omp_get_num_threads(void); +void omp_set_num_threads(int num_threads); + +#ifndef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif +#ifndef MIN +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#endif +#define NINT(x) ((int)((x)>0.0?(x)+0.5:(x)-0.5)) + +#ifndef COMPLEX +typedef struct _complexStruct { /* complex number */ + float r,i; +} complex; +#endif/* complex */ + +int readShotData(char *filename, float *xrcv, float *xsrc, float *zsrc, int *xnx, complex *cdata, int nw, int nw_low, int nshots, +int nx, int nxs, float fxsb, float dxs, int ntfft, int mode, float scale, float tsq, float Q, float f0, int reci, int *nshots_r, int *isxcount, int *reci_xsrc, int *reci_xrcv, float *ixmask, int verbose); +int readTinvData(char *filename, float *xrcv, float *xsrc, float *zsrc, int *xnx, int Nfoc, int nx, int ntfft, int mode, int *maxval, float *tinv, int hw, int verbose); +int writeDataIter(char *file_iter, float *data, segy *hdrs, int n1, int n2, float d2, float f2, int n2out, int Nfoc, float *xsyn, float *zsyn, int *ixpos, int npos, int t0shift, int iter); + +void name_ext(char *filename, char *extension); + +void applyMute(float *data, int *mute, int smooth, int above, int Nfoc, int nxs, int nt, int *xrcvsyn, int npos, int shift, int *muteW); +void applyMute_tshift( float *data, int *mute, int smooth, int above, int Nfoc, int nxs, int nt, int *ixpos, int npos, int shift, int *tsynW); +void timeShift(float *data, int nsam, int nrec, float dt, float shift, float fmin, float fmax); + + +int getFileInfo(char *filename, int *n1, int *n2, int *ngath, float *d1, float *d2, float *f1, float *f2, float *xmin, float *xmax, float *sclsxgx, int *ntraces); +int readData(FILE *fp, float *data, segy *hdrs, int n1); +int writeData(FILE *fp, float *data, segy *hdrs, int n1, int n2); +int disp_fileinfo(char *file, int n1, int n2, float f1, float f2, float d1, float d2, segy *hdrs); +double wallclock_time(void); + +void synthesis(complex *Refl, complex *Fop, float *Top, float *iRN, int nx, int nt, int nxs, int nts, float dt, float *xsyn, int +Nfoc, float *xrcv, float *xsrc, int *xnx, float fxse, float fxsb, float dxs, float dxsrc, float dx, int ntfft, int +nw, int nw_low, int nw_high, int mode, int reci, int nshots, int *ixpos, int npos, double *tfft, int *isxcount, int +*reci_xsrc, int *reci_xrcv, float *ixmask, int verbose); + +void synthesisPositions(int nx, int nt, int nxs, int nts, float dt, float *xsyn, int Nfoc, float *xrcv, float *xsrc, int *xnx, +float fxse, float fxsb, float dxs, float dxsrc, float dx, int nshots, int *ixpos, int *npos, int *isxcount, int countmin, int reci, int verbose); + +int linearsearch(int *array, size_t N, int value); + +/*********************** self documentation **********************/ +char *sdoc[] = { +" ", +" MARCHENKO - Iterative Green's function and focusing functions retrieval", +" ", +" marchenko file_tinv= file_shot= [optional parameters]", +" ", +" Required parameters: ", +" ", +" file_tinv= ............... direct arrival from focal point: G_d", +" file_shot= ............... Reflection response: R", +" ", +" Optional parameters: ", +" ", +" INTEGRATION ", +" tap=0 .................... lateral taper focusing(1), shot(2) or both(3)", +" ntap=0 ................... number of taper points at boundaries", +" fmin=0 ................... minimum frequency in the Fourier transform", +" fmax=70 .................. maximum frequency in the Fourier transform", +" MARCHENKO ITERATIONS ", +" niter=10 ................. number of iterations", +" MUTE-WINDOW ", +" above=0 .................. mute above(1), around(0) or below(-1) the first travel times of file_tinv", +" shift=12 ................. number of points above(positive) / below(negative) travel time for mute", +" hw=8 ..................... window in time samples to look for maximum in next trace", +" smooth=5 ................. number of points to smooth mute with cosine window", +" plane_wave=0 ............. enable plane-wave illumination function", +" src_angle=0 .............. angle of plane source array", +" src_velo=1500 ............ velocity to use in src_angle definition", +" REFLECTION RESPONSE CORRECTION ", +" tsq=0.0 .................. scale factor n for t^n for true amplitude recovery", +" Q=0.0 .......,............ Q correction factor", +" f0=0.0 ................... ... for Q correction factor", +" scale=2 .................. scale factor of R for summation of Ni with G_d", +" pad=0 .................... amount of samples to pad the reflection series", +" reci=0 ................... 1; add receivers as shots 2; only use receivers as shot positions", +" countmin=0 ............... 0.3*nxrcv; minumum number of reciprocal traces for a contribution", +" OUTPUT DEFINITION ", +" file_green= .............. output file with full Green function(s)", +" file_gplus= .............. output file with G+ ", +" file_gmin= ............... output file with G- ", +" file_f1plus= ............. output file with f1+ ", +" file_f1min= .............. output file with f1- ", +" file_f2= ................. output file with f2 (=p+) ", +" file_pplus= .............. output file with p+ ", +" file_pmin= ............... output file with p- ", +" file_iter= ............... output file with -Ni(-t) for each iteration", +" rotate=1 ................. 1: t=0 at nt/2 (middle) 0: t=0 at sample 0 for f1+,-", +" verbose=0 ................ silent option; >0 displays info", +" ", +" ", +" author : Jan Thorbecke : 2016 (j.w.thorbecke@tudelft.nl)", +" ", +NULL}; +/**************** end self doc ***********************************/ + +int main (int argc, char **argv) +{ + FILE *fp_out, *fp_f1plus, *fp_f1min; + FILE *fp_gmin, *fp_gplus, *fp_f2, *fp_pmin; + int i, j, l, ret, nshots, Nfoc, nt, nx, nts, nxs, ngath; + int size, n1, n2, ntap, tap, di, ntraces, pad, rotate; + int nw, nw_low, nw_high, nfreq, *xnx, *xnxsyn; + int reci, countmin, mode, n2out, verbose, ntfft; + int iter, niter, tracf, *muteW, *tsynW; + int hw, smooth, above, shift, *ixpos, npos, ix, plane_wave; + int nshots_r, *isxcount, *reci_xsrc, *reci_xrcv; + float fmin, fmax, *tapersh, *tapersy, fxf, dxf, *xsrc, *xrcv, *zsyn, *zsrc, *xrcvsyn; + double t0, t1, t2, t3, tsyn, tread, tfft, tcopy, energyNi, *energyN0; + float d1, d2, f1, f2, fxsb, fxse, ft, fx, *xsyn, dxsrc; + float *green, *f2p, *pmin, *G_d, dt, dx, dxs, scl, mem; + float *f1plus, *f1min, *iRN, *Ni, *Nig, *trace, *Gmin, *Gplus; + float xmin, xmax, scale, tsq, Q, f0; + float *ixmask; + float grad2rad, p, src_angle, src_velo, tplmax; + complex *Refl, *Fop; + char *file_tinv, *file_shot, *file_green, *file_iter; + char *file_f1plus, *file_f1min, *file_gmin, *file_gplus, *file_f2, *file_pmin; + segy *hdrs_out; + + initargs(argc, argv); + requestdoc(1); + + tsyn = tread = tfft = tcopy = 0.0; + t0 = wallclock_time(); + + if (!getparstring("file_shot", &file_shot)) file_shot = NULL; + if (!getparstring("file_tinv", &file_tinv)) file_tinv = NULL; + if (!getparstring("file_f1plus", &file_f1plus)) file_f1plus = NULL; + if (!getparstring("file_f1min", &file_f1min)) file_f1min = NULL; + if (!getparstring("file_gplus", &file_gplus)) file_gplus = NULL; + if (!getparstring("file_gmin", &file_gmin)) file_gmin = NULL; + if (!getparstring("file_pplus", &file_f2)) file_f2 = NULL; + if (!getparstring("file_f2", &file_f2)) file_f2 = NULL; + if (!getparstring("file_pmin", &file_pmin)) file_pmin = NULL; + if (!getparstring("file_iter", &file_iter)) file_iter = NULL; + if (!getparint("verbose", &verbose)) verbose = 0; + if (file_tinv == NULL && file_shot == NULL) + verr("file_tinv and file_shot cannot be both input pipe"); + if (!getparstring("file_green", &file_green)) file_green = NULL; + if (!getparfloat("fmin", &fmin)) fmin = 0.0; + if (!getparfloat("fmax", &fmax)) fmax = 70.0; + if (!getparint("reci", &reci)) reci = 0; + if (!getparfloat("scale", &scale)) scale = 2.0; + if (!getparfloat("tsq", &tsq)) tsq = 0.0; + if (!getparfloat("Q", &Q)) Q = 0.0; + if (!getparfloat("f0", &f0)) f0 = 0.0; + if (!getparint("tap", &tap)) tap = 0; + if (!getparint("ntap", &ntap)) ntap = 0; + if (!getparint("pad", &pad)) pad = 0; + if (!getparint("rotate", &rotate)) rotate = 1; + + if(!getparint("niter", &niter)) niter = 10; + if(!getparint("hw", &hw)) hw = 15; + if(!getparint("smooth", &smooth)) smooth = 5; + if(!getparint("above", &above)) above = 0; + if(!getparint("shift", &shift)) shift=12; + + if (!getparint("plane_wave", &plane_wave)) plane_wave = 0; + if (!getparfloat("src_angle",&src_angle)) src_angle=0.; + if (!getparfloat("src_velo",&src_velo)) src_velo=1500.; + + if (reci && ntap) vwarn("tapering influences the reciprocal result"); + +/*================ Reading info about shot and initial operator sizes ================*/ + + ngath = 0; /* setting ngath=0 scans all traces; n2 contains maximum traces/gather */ + ret = getFileInfo(file_tinv, &n1, &n2, &ngath, &d1, &d2, &f1, &f2, &xmin, &xmax, &scl, &ntraces); + Nfoc = ngath; + nxs = n2; + nts = n1; + dxs = d2; + fxsb = f2; + + ngath = 0; /* setting ngath=0 scans all traces; nx contains maximum traces/gather */ + ret = getFileInfo(file_shot, &nt, &nx, &ngath, &d1, &dx, &ft, &fx, &xmin, &xmax, &scl, &ntraces); + nshots = ngath; + assert (nxs >= nshots); + + if (!getparfloat("dt", &dt)) dt = d1; + + ntfft = optncr(MAX(nt+pad, nts+pad)); + nfreq = ntfft/2+1; + nw_low = (int)MIN((fmin*ntfft*dt), nfreq-1); + nw_low = MAX(nw_low, 1); + nw_high = MIN((int)(fmax*ntfft*dt), nfreq-1); + nw = nw_high - nw_low + 1; + scl = 1.0/((float)ntfft); + if (!getparint("countmin", &countmin)) countmin = 0.3*nx; + +/*================ Allocating all data arrays ================*/ + + Fop = (complex *)calloc(nxs*nw*Nfoc,sizeof(complex)); + green = (float *)calloc(Nfoc*nxs*ntfft,sizeof(float)); + f2p = (float *)calloc(Nfoc*nxs*ntfft,sizeof(float)); + pmin = (float *)calloc(Nfoc*nxs*ntfft,sizeof(float)); + f1plus = (float *)calloc(Nfoc*nxs*ntfft,sizeof(float)); + f1min = (float *)calloc(Nfoc*nxs*ntfft,sizeof(float)); + iRN = (float *)calloc(Nfoc*nxs*ntfft,sizeof(float)); + Ni = (float *)calloc(Nfoc*nxs*ntfft,sizeof(float)); + Nig = (float *)calloc(Nfoc*nxs*ntfft,sizeof(float)); + G_d = (float *)calloc(Nfoc*nxs*ntfft,sizeof(float)); + muteW = (int *)calloc(Nfoc*nxs,sizeof(int)); + tsynW = (int *)malloc(Nfoc*nxs*sizeof(int)); // time-shift for Giovanni's plane-wave on non-zero times + energyN0= (double *)malloc(Nfoc*sizeof(double)); + trace = (float *)malloc(ntfft*sizeof(float)); + xrcvsyn = (float *)calloc(Nfoc*nxs,sizeof(float)); // x-rcv postions of focal points + xsyn = (float *)malloc(Nfoc*sizeof(float)); // x-src position of focal points + zsyn = (float *)malloc(Nfoc*sizeof(float)); // z-src position of focal points + xnxsyn = (int *)calloc(Nfoc,sizeof(int)); // number of traces per focal point + ixpos = (int *)calloc(nxs,sizeof(int)); // x-position of source of shot in G_d domain (nxs with dxs) + + Refl = (complex *)malloc(nw*nx*nshots*sizeof(complex)); + xrcv = (float *)calloc(nshots*nx,sizeof(float)); // x-rcv postions of shots + xsrc = (float *)calloc(nshots,sizeof(float)); //x-src position of shots + zsrc = (float *)calloc(nshots,sizeof(float)); // z-src position of shots + xnx = (int *)calloc(nshots,sizeof(int)); // number of traces per shot + + if (reci!=0) { + reci_xsrc = (int *)malloc((nxs*nxs)*sizeof(int)); + reci_xrcv = (int *)malloc((nxs*nxs)*sizeof(int)); + isxcount = (int *)calloc(nxs,sizeof(int)); + ixmask = (float *)calloc(nxs,sizeof(float)); + } + +/*================ Read and define mute window based on focusing operator(s) ================*/ +/* G_d = p_0^+ = G_d (-t) ~ Tinv */ + + mode=-1; /* apply complex conjugate to read in data */ + readTinvData(file_tinv, xrcvsyn, xsyn, zsyn, xnxsyn, Nfoc, nxs, ntfft, + mode, muteW, G_d, hw, verbose); + /* reading data added zero's to the number of time samples to be the same as ntfft */ + nts = ntfft; + + /* compute time shift for tilted plane waves */ + if ( plane_wave==1) { + grad2rad = 17.453292e-3; + p = sin(src_angle*grad2rad)/src_velo; + if (p < 0.0) { + for (i=0; i<nxs; i++) { + tsynW[i] = NINT(fabsf((nxs-1-i)*dxs*p)/dt); + } + } + else { + for (i=0; i<nxs; i++) { + tsynW[i] = NINT(i*dxs*p/dt); + } + } + if (Nfoc!=1) verr("For plane-wave focusing only one function can be computed at the same time"); + } + else { /* just fill with zero's */ + for (i=0; i<nxs*Nfoc; i++) { + tsynW[i] = 0; + } + } + tplmax=0.0; + for (i=0; i<nxs; i++) { + tplmax = MAX(tplmax, fabsf((i)*dxs*p)); + } + //fprintf(stderr,"tplmax=%f\n", tplmax); + + /* define tapers to taper edges of acquisition */ + if (tap == 1 || tap == 3) { + tapersy = (float *)malloc(nxs*sizeof(float)); + for (j = 0; j < ntap; j++) + tapersy[j] = (cos(PI*(j-ntap)/ntap)+1)/2.0; + for (j = ntap; j < nxs-ntap; j++) + tapersy[j] = 1.0; + for (j = nxs-ntap; j < nxs; j++) + tapersy[j] =(cos(PI*(j-(nxs-ntap))/ntap)+1)/2.0; + if (verbose) vmess("Taper for operator applied ntap=%d", ntap); + for (l = 0; l < Nfoc; l++) { + for (i = 0; i < nxs; i++) { + for (j = 0; j < nts; j++) { + G_d[l*nxs*nts+i*nts+j] *= tapersy[i]; + } + } + } + free(tapersy); + } + + /* check consistency of header values */ + if (xrcvsyn[0] != 0 || xrcvsyn[1] != 0 ) fxsb = xrcvsyn[0]; + fxse = fxsb + (float)(nxs-1)*dxs; + dxf = (xrcvsyn[nxs-1] - xrcvsyn[0])/(float)(nxs-1); + if (NINT(dxs*1e3) != NINT(fabs(dxf)*1e3)) { + vmess("dx in hdr.d1 (%.3f) and hdr.gx (%.3f) not equal",d2, dxf); + if (dxf != 0) dxs = fabs(dxf); + vmess("dx in operator => %f", dxs); + } + +/*================ Reading shot records ================*/ + + mode=1; + readShotData(file_shot, xrcv, xsrc, zsrc, xnx, Refl, nw, nw_low, nshots, nx, nxs, fxsb, dxs, ntfft, + mode, scale, tsq, Q, f0, reci, &nshots_r, isxcount, reci_xsrc, reci_xrcv, ixmask, verbose); + + if (tap == 2 || tap == 3) { + tapersh = (float *)malloc(nx*sizeof(float)); + for (j = 0; j < ntap; j++) + tapersh[j] = (cos(PI*(j-ntap)/ntap)+1)/2.0; + for (j = ntap; j < nx-ntap; j++) + tapersh[j] = 1.0; + for (j = nx-ntap; j < nx; j++) + tapersh[j] =(cos(PI*(j-(nx-ntap))/ntap)+1)/2.0; + if (verbose) vmess("Taper for shots applied ntap=%d", ntap); + for (l = 0; l < nshots; l++) { + for (j = 1; j < nw; j++) { + for (i = 0; i < nx; i++) { + Refl[l*nx*nw+j*nx+i].r *= tapersh[i]; + Refl[l*nx*nw+j*nx+i].i *= tapersh[i]; + } + } + } + free(tapersh); + } + + /* check consistency of header values */ + fxf = xsrc[0]; + if (nx > 1) dxf = (xrcv[nx-1] - xrcv[0])/(float)(nx-1); + else dxf = d2; + if (NINT(dx*1e3) != NINT(fabs(dxf)*1e3)) { + vmess("dx in hdr.d1 (%.3f) and hdr.gx (%.3f) not equal",dx, dxf); + if (dxf != 0) dx = fabs(dxf); + else verr("gx hdrs not set"); + vmess("dx used => %f", dx); + } + + dxsrc = (float)xsrc[1] - xsrc[0]; + if (dxsrc == 0) { + vwarn("sx hdrs are not filled in!!"); + dxsrc = dx; + } + +/*================ Check the size of the files ================*/ + + if (NINT(dxsrc/dx)*dx != NINT(dxsrc)) { + vwarn("source (%.2f) and receiver step (%.2f) don't match",dxsrc,dx); + if (reci == 2) vwarn("step used from operator (%.2f) ",dxs); + } + di = NINT(dxf/dxs); + if ((NINT(di*dxs) != NINT(dxf)) && verbose) + vwarn("dx in receiver (%.2f) and operator (%.2f) don't match",dx,dxs); + if (nt != nts) + vmess("Time samples in shot (%d) and focusing operator (%d) are not equal",nt, nts); + if (verbose) { + vmess("Number of focusing operators = %d", Nfoc); + vmess("Number of receivers in focusop = %d", nxs); + vmess("number of shots = %d", nshots); + vmess("number of receiver/shot = %d", nx); + vmess("first model position = %.2f", fxsb); + vmess("last model position = %.2f", fxse); + vmess("first source position fxf = %.2f", fxf); + vmess("source distance dxsrc = %.2f", dxsrc); + vmess("last source position = %.2f", fxf+(nshots-1)*dxsrc); + vmess("receiver distance dxf = %.2f", dxf); + vmess("direction of increasing traces = %d", di); + vmess("number of time samples (nt,nts) = %d (%d,%d)", ntfft, nt, nts); + vmess("time sampling = %e ", dt); + if (file_green != NULL) vmess("Green output file = %s ", file_green); + if (file_gmin != NULL) vmess("Gmin output file = %s ", file_gmin); + if (file_gplus != NULL) vmess("Gplus output file = %s ", file_gplus); + if (file_pmin != NULL) vmess("Pmin output file = %s ", file_pmin); + if (file_f2 != NULL) vmess("f2 (=pplus) output file = %s ", file_f2); + if (file_f1min != NULL) vmess("f1min output file = %s ", file_f1min); + if (file_f1plus != NULL)vmess("f1plus output file = %s ", file_f1plus); + if (file_iter != NULL) vmess("Iterations output file = %s ", file_iter); + } + +/*================ initializations ================*/ + + if (reci) n2out = nxs; + else n2out = nshots; + mem = Nfoc*n2out*ntfft*sizeof(float)/1048576.0; + if (verbose) { + vmess("number of output traces = %d", n2out); + vmess("number of output samples = %d", ntfft); + vmess("Size of output data/file = %.1f MB", mem); + } + + + /* dry-run of synthesis to get all x-positions calcalated by the integration */ + synthesisPositions(nx, nt, nxs, nts, dt, xsyn, Nfoc, xrcv, xsrc, xnx, fxse, fxsb, + dxs, dxsrc, dx, nshots, ixpos, &npos, isxcount, countmin, reci, verbose); + if (verbose) { + vmess("synthesisPositions: nshots=%d npos=%d", nshots, npos); + } + +/*================ set variables for output data ================*/ + + n1 = nts; n2 = n2out; + f1 = ft; f2 = fxsb+dxs*ixpos[0]; + d1 = dt; + if (reci == 0) d2 = dxsrc; // distance between sources in R + else if (reci == 1) d2 = dxs; // distance between traces in G_d + else if (reci == 2) d2 = dx; // distance between receivers in R + + hdrs_out = (segy *) calloc(n2,sizeof(segy)); + if (hdrs_out == NULL) verr("allocation for hdrs_out"); + size = nxs*nts; + + for (i = 0; i < n2; i++) { + hdrs_out[i].ns = n1; + hdrs_out[i].trid = 1; + hdrs_out[i].dt = dt*1000000; + hdrs_out[i].f1 = f1; + hdrs_out[i].f2 = f2; + hdrs_out[i].d1 = d1; + hdrs_out[i].d2 = d2; + hdrs_out[i].trwf = n2out; + hdrs_out[i].scalco = -1000; + hdrs_out[i].gx = NINT(1000*(f2+i*d2)); + hdrs_out[i].scalel = -1000; + hdrs_out[i].tracl = i+1; + } + t1 = wallclock_time(); + tread = t1-t0; + +/*================ initialization ================*/ + + memcpy(Ni, G_d, Nfoc*nxs*ntfft*sizeof(float)); + for (l = 0; l < Nfoc; l++) { + for (i = 0; i < npos; i++) { + j = 0; + ix = ixpos[i]; /* select the traces that have an output trace after integration */ + f2p[l*nxs*nts+i*nts+j] = G_d[l*nxs*nts+ix*nts+j]; + f1plus[l*nxs*nts+i*nts+j] = G_d[l*nxs*nts+ix*nts+j]; + for (j = 1; j < nts; j++) { + f2p[l*nxs*nts+i*nts+j] = G_d[l*nxs*nts+ix*nts+j]; + f1plus[l*nxs*nts+i*nts+j] = G_d[l*nxs*nts+ix*nts+j]; + } + } + } + +/*================ start Marchenko iterations ================*/ + + for (iter=0; iter<niter; iter++) { + + t2 = wallclock_time(); + +/*================ construction of Ni(-t) = - \int R(x,t) Ni(t) ================*/ + + synthesis(Refl, Fop, Ni, iRN, nx, nt, nxs, nts, dt, xsyn, Nfoc, + xrcv, xsrc, xnx, fxse, fxsb, dxs, dxsrc, dx, ntfft, nw, nw_low, nw_high, mode, + reci, nshots, ixpos, npos, &tfft, isxcount, reci_xsrc, reci_xrcv, ixmask, verbose); + + t3 = wallclock_time(); + tsyn += t3 - t2; + + if (file_iter != NULL) { + writeDataIter(file_iter, iRN, hdrs_out, ntfft, nxs, d2, f2, n2out, Nfoc, xsyn, zsyn, ixpos, npos, 0, iter+1); + } + /* N_k(x,t) = -N_(k-1)(x,-t) */ + /* p0^-(x,t) += iRN = (R * T_d^inv)(t) */ + for (l = 0; l < Nfoc; l++) { + energyNi = 0.0; + for (i = 0; i < npos; i++) { + j = 0; + ix = ixpos[i]; + Ni[l*nxs*nts+i*nts+j] = -iRN[l*nxs*nts+ix*nts+j]; + pmin[l*nxs*nts+i*nts+j] += iRN[l*nxs*nts+ix*nts+j]; + energyNi += iRN[l*nxs*nts+ix*nts+j]*iRN[l*nxs*nts+ix*nts+j]; + for (j = 1; j < nts; j++) { + Ni[l*nxs*nts+i*nts+j] = -iRN[l*nxs*nts+ix*nts+nts-j]; + pmin[l*nxs*nts+i*nts+j] += iRN[l*nxs*nts+ix*nts+j]; + energyNi += iRN[l*nxs*nts+ix*nts+j]*iRN[l*nxs*nts+ix*nts+j]; + } + if ( plane_wave==1 ) { /* don't reverse in time */ + Nig[l*nxs*nts+i*nts+j] = -iRN[l*nxs*nts+ix*nts+j]; + for (j = 1; j < nts; j++) { + Nig[l*nxs*nts+i*nts+j] = -iRN[l*nxs*nts+ix*nts+j]; + } + } + } + if (iter==0) energyN0[Nfoc] = energyNi; + if (verbose >=2) vmess(" - iSyn %d: Ni at iteration %d has energy %e; relative to N0 %e", l, iter, sqrt(energyNi), +sqrt(energyNi/energyN0[Nfoc])); + } + + /* apply mute window based on times of direct arrival (in muteW) */ + if ( plane_wave==1 ) { /* use a-symmetric shift for plane waves with non-zero angles */ + applyMute_tshift(Ni, muteW, smooth, above, Nfoc, nxs, nts, ixpos, npos, shift, tsynW); + applyMute_tshift(Nig, muteW, smooth, above, Nfoc, nxs, nts, ixpos, npos, shift, tsynW); + } + else { + applyMute(Ni, muteW, smooth, above, Nfoc, nxs, nts, ixpos, npos, shift, tsynW); + } + + if (iter % 2 == 0) { /* even iterations update: => f_1^-(t) */ + if (plane_wave==0) { /* follow the standard focal point scheme */ + for (l = 0; l < Nfoc; l++) { + for (i = 0; i < npos; i++) { + j = 0; + f1min[l*nxs*nts+i*nts+j] -= Ni[l*nxs*nts+i*nts+j]; + for (j = 1; j < nts; j++) { + f1min[l*nxs*nts+i*nts+j] -= Ni[l*nxs*nts+i*nts+nts-j]; + } + } + } + if (above==-2) applyMute(f1min, muteW, smooth, 0, Nfoc, nxs, nts, ixpos, npos, shift, tsynW); + } + else { /* plane wave scheme */ + for (l = 0; l < Nfoc; l++) { + for (i = 0; i < npos; i++) { + j = 0; + f1min[l*nxs*nts+i*nts+j] -= Nig[l*nxs*nts+i*nts+j]; + Ni[l*nxs*nts+i*nts+j] = Nig[l*nxs*nts+i*nts+j]; + for (j = 1; j < nts; j++) { + f1min[l*nxs*nts+i*nts+j] -= Nig[l*nxs*nts+i*nts+j]; + Ni[l*nxs*nts+i*nts+j] = Nig[l*nxs*nts+i*nts+nts-j]; + } + } + } + if (above==-2) applyMute(f1min, muteW, smooth, 0, Nfoc, nxs, nts, ixpos, npos, shift, tsynW); + } + } + else {/* odd iterations update: => f_1^+(t) */ + for (l = 0; l < Nfoc; l++) { + for (i = 0; i < npos; i++) { + j = 0; + f1plus[l*nxs*nts+i*nts+j] += Ni[l*nxs*nts+i*nts+j]; + for (j = 1; j < nts; j++) { + f1plus[l*nxs*nts+i*nts+j] += Ni[l*nxs*nts+i*nts+j]; + } + } + } + } + //writeDataIter("Ni.su", Ni, hdrs_out, ntfft, nxs, d2, f2, n2out, Nfoc, xsyn, zsyn, ixpos, npos, 0, iter+1); + + /* update f2 */ + for (l = 0; l < Nfoc; l++) { + for (i = 0; i < npos; i++) { + j = 0; + f2p[l*nxs*nts+i*nts+j] += Ni[l*nxs*nts+i*nts+j]; + for (j = 1; j < nts; j++) { + f2p[l*nxs*nts+i*nts+j] += Ni[l*nxs*nts+i*nts+j]; + } + } + } + + t2 = wallclock_time(); + tcopy += t2 - t3; + + if (verbose) vmess("*** Iteration %d finished ***", iter); + + } /* end of iterations */ + + free(Ni); + free(Nig); + free(G_d); + + /* compute full Green's function G = int R * f2(t) + f2(-t) = Pplus + Pmin */ + for (l = 0; l < Nfoc; l++) { + for (i = 0; i < npos; i++) { + j = 0; + /* set green to zero if mute-window exceeds nt/2 */ + if (muteW[l*nxs+ixpos[i]] >= nts/2) { + memset(&green[l*nxs*nts+i*nts],0, sizeof(float)*nt); + continue; + } + green[l*nxs*nts+i*nts+j] = f2p[l*nxs*nts+i*nts+j] + pmin[l*nxs*nts+i*nts+j]; + for (j = 1; j < nts; j++) { + green[l*nxs*nts+i*nts+j] = f2p[l*nxs*nts+i*nts+nts-j] + pmin[l*nxs*nts+i*nts+j]; + } + } + } + applyMute(green, muteW, smooth, 4, Nfoc, nxs, nts, ixpos, npos, shift, tsynW); + + /* compute upgoing Green's function G^+,- */ + if (file_gmin != NULL) { + Gmin = (float *)calloc(Nfoc*nxs*ntfft,sizeof(float)); + + /* use f1+ as operator on R in frequency domain */ + mode=1; + synthesis(Refl, Fop, f1plus, iRN, nx, nt, nxs, nts, dt, xsyn, Nfoc, + xrcv, xsrc, xnx, fxse, fxsb, dxs, dxsrc, dx, ntfft, nw, nw_low, nw_high, mode, + reci, nshots, ixpos, npos, &tfft, isxcount, reci_xsrc, reci_xrcv, ixmask, verbose); + + /* compute upgoing Green's G^-,+ */ + for (l = 0; l < Nfoc; l++) { + for (i = 0; i < npos; i++) { + j=0; + ix = ixpos[i]; + Gmin[l*nxs*nts+i*nts+j] = iRN[l*nxs*nts+ix*nts+j] - f1min[l*nxs*nts+i*nts+j]; + for (j = 1; j < nts; j++) { + Gmin[l*nxs*nts+i*nts+j] = iRN[l*nxs*nts+ix*nts+j] - f1min[l*nxs*nts+i*nts+j]; + } + } + } + /* Apply mute with window for Gmin */ + if ( plane_wave==1 ) { + applyMute_tshift(Gmin, muteW, smooth, 1, Nfoc, nxs, nts, ixpos, npos, shift, tsynW); + timeShift(Gmin, nts, npos, dt, tplmax, fmin, fmax); + } + else { + applyMute(Gmin, muteW, smooth, 4, Nfoc, nxs, nts, ixpos, npos, shift, tsynW); + } + } /* end if Gmin */ + + /* compute downgoing Green's function G^+,+ */ + if (file_gplus != NULL) { + Gplus = (float *)calloc(Nfoc*nxs*ntfft,sizeof(float)); + + /* use f1-(*) as operator on R in frequency domain */ + mode=-1; + synthesis(Refl, Fop, f1min, iRN, nx, nt, nxs, nts, dt, xsyn, Nfoc, + xrcv, xsrc, xnx, fxse, fxsb, dxs, dxsrc, dx, ntfft, nw, nw_low, nw_high, mode, + reci, nshots, ixpos, npos, &tfft, isxcount, reci_xsrc, reci_xrcv, ixmask, verbose); + + /* compute downgoing Green's G^+,+ */ + for (l = 0; l < Nfoc; l++) { + for (i = 0; i < npos; i++) { + j=0; + ix = ixpos[i]; + Gplus[l*nxs*nts+i*nts+j] = -iRN[l*nxs*nts+ix*nts+j] + f1plus[l*nxs*nts+i*nts+j]; + for (j = 1; j < nts; j++) { + Gplus[l*nxs*nts+i*nts+j] = -iRN[l*nxs*nts+ix*nts+j] + f1plus[l*nxs*nts+i*nts+nts-j]; + } + } + } + /* Apply mute with window for Gplus */ + applyMute(Gplus, muteW, smooth, 4, Nfoc, nxs, nts, ixpos, npos, shift, tsynW); + } /* end if Gplus */ + + free(muteW); + free(tsynW); + free(energyN0); + + t2 = wallclock_time(); + if (verbose) { + vmess("Total CPU-time marchenko = %.3f", t2-t0); + vmess("with CPU-time synthesis = %.3f", tsyn); + vmess("with CPU-time copy array = %.3f", tcopy); + vmess(" CPU-time fft data = %.3f", tfft); + vmess("and CPU-time read data = %.3f", tread); + } + +/*================ write output files ================*/ + + + if (file_green != NULL) { + fp_out = fopen(file_green, "w+"); + if (fp_out==NULL) verr("error on creating output file %s", file_green); + } + if (file_gmin != NULL) { + fp_gmin = fopen(file_gmin, "w+"); + if (fp_gmin==NULL) verr("error on creating output file %s", file_gmin); + } + if (file_gplus != NULL) { + fp_gplus = fopen(file_gplus, "w+"); + if (fp_gplus==NULL) verr("error on creating output file %s", file_gplus); + } + if (file_f2 != NULL) { + fp_f2 = fopen(file_f2, "w+"); + if (fp_f2==NULL) verr("error on creating output file %s", file_f2); + } + if (file_pmin != NULL) { + fp_pmin = fopen(file_pmin, "w+"); + if (fp_pmin==NULL) verr("error on creating output file %s", file_pmin); + } + if (file_f1plus != NULL) { + fp_f1plus = fopen(file_f1plus, "w+"); + if (fp_f1plus==NULL) verr("error on creating output file %s", file_f1plus); + } + if (file_f1min != NULL) { + fp_f1min = fopen(file_f1min, "w+"); + if (fp_f1min==NULL) verr("error on creating output file %s", file_f1min); + } + + + tracf = 1; + for (l = 0; l < Nfoc; l++) { + if (reci) f2 = fxsb; + else f2 = fxf; + + for (i = 0; i < n2; i++) { + hdrs_out[i].fldr = l+1; + hdrs_out[i].sx = NINT(xsyn[l]*1000); + hdrs_out[i].offset = (long)NINT((f2+i*d2) - xsyn[l]); + hdrs_out[i].tracf = tracf++; + hdrs_out[i].selev = NINT(zsyn[l]*1000); + hdrs_out[i].sdepth = NINT(-zsyn[l]*1000); + hdrs_out[i].f1 = f1; + } + + if (file_green != NULL) { + ret = writeData(fp_out, (float *)&green[l*size], hdrs_out, n1, n2); + if (ret < 0 ) verr("error on writing output file."); + } + + if (file_gmin != NULL) { + ret = writeData(fp_gmin, (float *)&Gmin[l*size], hdrs_out, n1, n2); + if (ret < 0 ) verr("error on writing output file."); + } + if (file_gplus != NULL) { + ret = writeData(fp_gplus, (float *)&Gplus[l*size], hdrs_out, n1, n2); + if (ret < 0 ) verr("error on writing output file."); + } + if (file_f2 != NULL) { + ret = writeData(fp_f2, (float *)&f2p[l*size], hdrs_out, n1, n2); + if (ret < 0 ) verr("error on writing output file."); + } + if (file_pmin != NULL) { + ret = writeData(fp_pmin, (float *)&pmin[l*size], hdrs_out, n1, n2); + if (ret < 0 ) verr("error on writing output file."); + } + if (file_f1plus != NULL) { + /* rotate to get t=0 in the middle */ + if (rotate==1) { + for (i = 0; i < n2; i++) { + hdrs_out[i].f1 = -n1*0.5*dt; + memcpy(&trace[0],&f1plus[l*size+i*nts],nts*sizeof(float)); + for (j = 0; j < n1/2; j++) { + f1plus[l*size+i*nts+n1/2+j] = trace[j]; + } + for (j = n1/2; j < n1; j++) { + f1plus[l*size+i*nts+j-n1/2] = trace[j]; + } + } + } + ret = writeData(fp_f1plus, (float *)&f1plus[l*size], hdrs_out, n1, n2); + if (ret < 0 ) verr("error on writing output file."); + } + if (file_f1min != NULL) { + /* rotate to get t=0 in the middle */ + if (rotate==1) { + for (i = 0; i < n2; i++) { + hdrs_out[i].f1 = -n1*0.5*dt; + memcpy(&trace[0],&f1min[l*size+i*nts],nts*sizeof(float)); + for (j = 0; j < n1/2; j++) { + f1min[l*size+i*nts+n1/2+j] = trace[j]; + } + for (j = n1/2; j < n1; j++) { + f1min[l*size+i*nts+j-n1/2] = trace[j]; + } + } + } + ret = writeData(fp_f1min, (float *)&f1min[l*size], hdrs_out, n1, n2); + if (ret < 0 ) verr("error on writing output file."); + } + } + ret=0; + if (file_green != NULL) {ret += fclose(fp_out);} + if (file_gplus != NULL) {ret += fclose(fp_gplus);} + if (file_gmin != NULL) {ret += fclose(fp_gmin);} + if (file_f2 != NULL) {ret += fclose(fp_f2);} + if (file_pmin != NULL) {ret += fclose(fp_pmin);} + if (file_f1plus != NULL) {ret += fclose(fp_f1plus);} + if (file_f1min != NULL) {ret += fclose(fp_f1min);} + if (ret < 0) verr("err %d on closing output file",ret); + + if (verbose) { + t1 = wallclock_time(); + vmess("and CPU-time write data = %.3f", t1-t2); + } + +/*================ free memory ================*/ + + free(hdrs_out); + + exit(0); +} + + diff --git a/marchenko3D/applyMute3D_tshift.c b/marchenko3D/applyMute3D_tshift.c new file mode 100644 index 0000000000000000000000000000000000000000..1111c29b164a7958b516dead018a258c6fcf4a51 --- /dev/null +++ b/marchenko3D/applyMute3D_tshift.c @@ -0,0 +1,203 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <assert.h> + +#ifndef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif +#ifndef MIN +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#endif +#define NINT(x) ((int)((x)>0.0?(x)+0.5:(x)-0.5)) +#ifndef COMPLEX +typedef struct _complexStruct { /* complex number */ + float r,i; +} complex; +#endif/* complex */ + + +void applyMute3D_tshift( float *data, long *mute, long smooth, long above, long Nfoc, long nxs, long nys, long nt, + long *ixpos, long *iypos, long npos, long shift, long iter, long *tsynW) +{ + long i, j, l, isyn, nxys; + float *costaper, scl, *Nig; + long imute, tmute, ts; + + nxys = nxs*nys; + Nig = (float *)malloc(nt*sizeof(float)); + + if (smooth) { + costaper = (float *)malloc(smooth*sizeof(float)); + scl = M_PI/((float)smooth); + for (i=0; i<smooth; i++) { + costaper[i] = 0.5*(1.0+cos((i+1)*scl)); + } + } + + for (isyn = 0; isyn < Nfoc; isyn++) { + for (i = 0; i < npos; i++) { + if (iter % 2 == 0) { + for (j = 0; j < nt; j++) { + Nig[j] = data[isyn*nxys*nt+i*nt+j]; + } + } + else { // reverse back in time + j=0; + Nig[j] = data[isyn*nxys*nt+i*nt+j]; + for (j = 1; j < nt; j++) { + Nig[j] = data[isyn*nxys*nt+i*nt+nt-j]; + } + } + if (above==1) { + imute = iypos[i]*nxs+ixpos[i]; + tmute = mute[isyn*nxys+imute]; + ts = tsynW[isyn*nxys+imute]; + for (j = 0; j < MAX(0,tmute-shift-smooth); j++) { + Nig[j] = 0.0; + } + for (j = MAX(0,tmute-shift-smooth),l=0; j < MAX(0,tmute-shift); j++,l++) { + Nig[j] *= costaper[smooth-l-1]; + } + } + else if (above==0){ + imute = iypos[i]*nxs+ixpos[i]; + tmute = mute[isyn*nxys+imute]; + ts = tsynW[isyn*nxys+imute]; + if (tmute >= nt/2) { + memset(&Nig[0],0, sizeof(float)*nt); + continue; + } + for (j = MAX(0,tmute-shift),l=0; j < MAX(0,tmute-shift+smooth); j++,l++) { + Nig[j] *= costaper[l]; + } + for (j = MAX(0,tmute-shift+smooth+1); j < MIN(nt,nt+1-tmute+2*ts+shift-smooth); j++) { + Nig[j] = 0.0; + } + for (j = MIN(nt-1,nt-tmute+2*ts+shift-smooth),l=0; j < MIN(nt,nt-tmute+shift); j++,l++) { + Nig[j] *= costaper[smooth-l-1]; + } + } + else if (above==-1) { + imute = iypos[i]*nxs+ixpos[i]; + tmute = mute[isyn*nxys+imute]; + ts = tsynW[isyn*nxys+imute]; + for (j = ts+tmute-shift,l=0; j < ts+tmute-shift+smooth; j++,l++) { + Nig[j] *= costaper[l]; + } + for (j = ts+tmute-shift+smooth; j < nt; j++) { + Nig[j] = 0.0; + } + } + else if (above==4) { //Psi gate which is the inverse of the Theta gate (above=0) + imute = iypos[i]*nxs+ixpos[i]; + tmute = mute[isyn*nxys+imute]; + ts = tsynW[isyn*nxys+imute]; + for (j = -2*ts+tmute-shift-smooth,l=0; j < -2*ts+tmute-shift; j++,l++) { + Nig[j] *= costaper[smooth-l-1]; + } + for (j = 0; j < -2*ts+tmute-shift-smooth-1; j++) { + Nig[j] = 0.0; + } + for (j = nt+1-tmute+shift+smooth; j < nt; j++) { + Nig[j] = 0.0; + } + for (j = nt-tmute+shift,l=0; j < nt-tmute+shift+smooth; j++,l++) { + Nig[j] *= costaper[l]; + } + } +/* To Do above==2 is not yet adapated for plane-waves */ + else if (above==2){//Separates the direct part of the wavefield from the coda + imute = iypos[i]*nxs+ixpos[i]; + tmute = mute[isyn*nxys+imute]; + for (j = 0; j < tmute-shift-smooth; j++) { + data[isyn*nxys*nt+i*nt+j] = 0.0; + } + for (j = tmute-shift-smooth,l=0; j < tmute-shift; j++,l++) { + data[isyn*nxys*nt+i*nt+j] *= costaper[smooth-l-1]; + } + for (j = tmute+shift,l=0; j < tmute+shift+smooth; j++,l++) { + data[isyn*nxys*nt+i*nt+j] *= costaper[l]; + } + for (j = tmute+shift+smooth; j < nt; j++) { + data[isyn*nxys*nt+i*nt+j] = 0.0; + } + } + + if (iter % 2 == 0) { + for (j = 0; j < nt; j++) { + data[isyn*nxys*nt+i*nt+j] = Nig[j]; + } + } + else { // reverse back in time + j=0; + data[isyn*nxys*nt+i*nt+j] = Nig[j]; + for (j = 1; j < nt; j++) { + data[isyn*nxys*nt+i*nt+j] = Nig[nt-j]; + } + } + } /* end if ipos */ + } + + if (smooth) free(costaper); + free(Nig); + + return; +} + +void timeShift(float *data, int nsam, int nrec, float dt, float shift, float fmin, float fmax) +{ + int optn, iom, iomin, iomax, nfreq, ix, it; + float omin, omax, deltom, om, tom, df, *trace, scl; + complex *ctrace, ctmp; + + optn = optncr(nsam); + nfreq = optn/2+1; + df = 1.0/(optn*dt); + + ctrace = (complex *)malloc(nfreq*sizeof(complex)); + if (ctrace == NULL) verr("memory allocation error for ctrace"); + + trace = (float *)malloc(optn*sizeof(float)); + if (trace == NULL) verr("memory allocation error for rdata"); + + deltom = 2.*M_PI*df; + omin = 2.*M_PI*fmin; + omax = 2.*M_PI*fmax; + iomin = (int)MIN((omin/deltom), (nfreq)); + iomax = MIN((int)(omax/deltom), (nfreq)); + scl = 1.0/(float)optn; + + for (ix = 0; ix < nrec; ix++) { + for (it=0;it<nsam;it++) trace[it]=data[ix*nsam+it]; + for (it=nsam;it<optn;it++) trace[it]=0.0; + /* Forward time-frequency FFT */ + rc1fft(&trace[0], &ctrace[0], optn, -1); + + for (iom = 0; iom < iomin; iom++) { + ctrace[iom].r = 0.0; + ctrace[iom].i = 0.0; + } + for (iom = iomax; iom < nfreq; iom++) { + ctrace[iom].r = 0.0; + ctrace[iom].i = 0.0; + } + for (iom = iomin ; iom < iomax ; iom++) { + om = deltom*iom; + tom = om*shift; + ctmp = ctrace[iom]; + ctrace[iom].r = ctmp.r*cos(-tom) - ctmp.i*sin(-tom); + ctrace[iom].i = ctmp.i*cos(-tom) + ctmp.r*sin(-tom); + } + /* Inverse frequency-time FFT and scale result */ + cr1fft(ctrace, trace, optn, 1); + for (it=0;it<nsam;it++) data[ix*nsam+it]=trace[it]*scl; + } + + + free(ctrace); + free(trace); + + return; +} diff --git a/raytime3d/writeData3D.c b/raytime3d/writeData3D.c new file mode 100644 index 0000000000000000000000000000000000000000..d8c3e4775ecdf7ca462abfaa7b303681da102d20 --- /dev/null +++ b/raytime3d/writeData3D.c @@ -0,0 +1,28 @@ +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include "segy.h" + +/** +* writes an 2D array to a SU file +* +* AUTHOR: +* Jan Thorbecke (janth@xs4all.nl) +* The Netherlands +**/ + +int writeData3D(FILE *fp, float *data, segy *hdrs, long n1, long n2) +{ + size_t nwrite; + long i; + + for (i=0; i<n2; i++) { + nwrite = fwrite(&hdrs[i], 1, TRCBYTES, fp); + assert(nwrite == TRCBYTES); + nwrite = fwrite(&data[i*n1], sizeof(float), n1, fp); + assert (nwrite == n1); + } + + return 0; +} + diff --git a/utils/convhomg.c b/utils/convhomg.c new file mode 100644 index 0000000000000000000000000000000000000000..2bd57624d4b95dd4f68053bbaca5d862dfeb2cc7 --- /dev/null +++ b/utils/convhomg.c @@ -0,0 +1,222 @@ +#include "par.h" +#include "segy.h" +#include <time.h> +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <assert.h> +#include <genfft.h> +#include "zfpmar.h" +#include <zfp.h> + +#ifndef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif +#ifndef MIN +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#endif +#define NINT(x) ((long)((x)>0.0?(x)+0.5:(x)-0.5)) + +#ifndef COMPLEX +typedef struct _complexStruct { /* complex number */ + float r,i; +} complex; +#endif/* complex */ + +long getFileInfo3D(char *filename, long *n1, long *n2, long *n3, long *ngath, float *d1, float *d2, float *d3, + float *f1, float *f2, float *f3, float *sclsxgxsygy, long *nxm); +double wallclock_time(void); +long writeData3D(FILE *fp, float *data, segy *hdrs, long n1, long n2); +long readSnapData3D(char *filename, float *data, segy *hdrs, long nsnaps, long nx, long ny, long nz, + long sx, long ex, long sy, long ey, long sz, long ez); +void scl_data(float *data, long nsam, long nrec, float scl, float *datout, long nsamout); +void convol(float *data1, float *data2, float *con, long ntfft); + +char *sdoc[] = { +" ", +" convhomg - Convolve a wavelet with a homogeneous Green's function ", +" ", +" authors : Joeri Brackenhoff (J.A.Brackenhoff@tudelft.nl)", +" : Jan Thorbecke (janth@xs4all.nl)", +" ", +" Required parameters: ", +"", +" file_hom= ................. First file of the array of virtual receivers", +" file_wav= ................. File containing the virtual source", +" ", +" Optional parameters: ", +" ", +" file_out= ................ Filename of the output", +NULL}; + +int main (int argc, char **argv) +{ + FILE *fp_hom, *fp_wav, *fp_out; + char *file_hom, *file_wav, *file_out; + long nt, nx, ny, nz, ntwav, ntfft, ntr, verbose; + long nt_wav, it, ipos; + float dt, dx, dy, dz, x0, y0, z0, scl, *Ghom, *wav, *wavelet, dt_wav; + float *trace, *conv; + segy *hdr_hom, hdr_wav; + size_t nread; + + initargs(argc, argv); + requestdoc(1); + + /*----------------------------------------------------------------------------* + * Get the parameters passed to the function + *----------------------------------------------------------------------------*/ + if (!getparstring("file_hom", &file_hom)) file_hom = NULL; + if (!getparstring("file_wav", &file_wav)) file_wav = NULL; + if (!getparstring("file_out", &file_out)) file_out = "out.su"; + if (!getparlong("verbose", &verbose)) verbose = 1; + + if (file_hom==NULL) verr("Error file_hom is not given"); + if (file_wav==NULL) verr("Error file_wav is not given"); + + /*----------------------------------------------------------------------------* + * Get the file info of the data and determine the indez of the truncation + *----------------------------------------------------------------------------*/ + + getFileInfo3D(file_hom, &nz, &nx, &ny, &nt, &dz, &dx, &dy, &z0, &x0, &y0, &scl, &ntr); + + if (verbose) { + vmess("******************** HOMG DATA ********************"); + vmess("Number of samples: %li, x: %li, y: %li, z: %li, t:%li",nx*ny*nz*nt,nx,ny,nz,nt); + vmess("Sampling distance for x: %.3f, y: %.3f, z: %.3f",dx,dy,dz); + vmess("Starting distance for x: %.3f, y: %.3f, z: %.3f",x0,y0,z0); + } + + /*----------------------------------------------------------------------------* + * Allocate and read in the data + *----------------------------------------------------------------------------*/ + + fp_wav = fopen( file_wav, "r" ); + if (fp_wav == NULL) verr("File %s does not exist or cannot be opened", file_wav); + nread = fread( &hdr_wav, 1, TRCBYTES, fp_wav ); + assert(nread == TRCBYTES); + nt_wav = hdr_wav.ns; + dt_wav = (float)(hdr_wav.dt/1E6); + wav = (float *)calloc(nt_wav,sizeof(float)); + nread = fread(&wav[0], sizeof(float), nt_wav, fp_wav); + assert(nread==nt_wav); + fclose(fp_wav); + + ntfft = loptncr(MAX(nt_wav,nt)); + + Ghom = (float *)calloc(nx*ny*nz*nt,sizeof(float)); + hdr_hom = (segy *)calloc(nx*ny*nt,sizeof(segy)); + readSnapData3D(file_hom, Ghom, hdr_hom, nt, nx, ny, nz, 0, nx, 0, ny, 0, nz); + dt = (float)(hdr_hom[0].dt/1E6); + + if (verbose) { + vmess("******************** TIME DATA ********************"); + vmess("Number of time samples wavelet: %li",nt_wav); + vmess("Number of time samples HomG : %li",nt); + vmess("Number of time samples FFT : %li",ntfft); + vmess("Time sampling HomG : %.3f",dt); + vmess("Time sampling wavelet : %.3f",dt_wav); + } + if (dt_wav!=dt) vmess("WARNING! dt of HomG (%f) and wavelet (%f) do not match.",dt,dt_wav); + + wavelet = (float *)calloc(ntfft,sizeof(float)); + trace = (float *)calloc(ntfft,sizeof(float)); + conv = (float *)calloc(ntfft,sizeof(float)); + + for (it = 0; it < nt_wav/2; it++) { + wavelet[it] = wav[it]; + wavelet[ntfft-1-it] = wav[nt_wav-1-it]; + } + free(wav); + for (ipos = 0; ipos<nx*ny*nz; ipos++) { + for (it = 0; it < nt; it++) { + trace[it] = Ghom[it*nx*ny*nz+ipos]; + } + convol(trace,wavelet,conv,ntfft); + for (it = 0; it < nt; it++) { + Ghom[it*nx*ny*nz+ipos] = conv[it]; + } + for (it = 0; it < ntfft; it++) { + trace[it] = 0.0; + conv[it] = 0.0; + } + } + + free(wavelet); free(trace); free(conv); + + fp_out = fopen(file_out, "w+"); + + nread = writeData3D(fp_out, &Ghom[0], hdr_hom, nz, nx*ny*nt); + if (nread < 0 ) verr("error on writing output file."); + + fclose(fp_out); + free(Ghom); free(hdr_hom); + + return 0; + +} + +void convol(float *data1, float *data2, float *con, long ntfft) +{ + long i, j, n, nfreq, sign; + float scl; + float *qr, *qi, *p1r, *p1i, *p2r, *p2i, *rdata1; + complex *cdata1, *cdata2, *ccon; + + nfreq = ntfft/2+1; + + cdata1 = (complex *)malloc(nfreq*sizeof(complex)); + if (cdata1 == NULL) verr("memory allocation error for cdata1"); + cdata2 = (complex *)malloc(nfreq*sizeof(complex)); + if (cdata2 == NULL) verr("memory allocation error for cdata2"); + ccon = (complex *)malloc(nfreq*sizeof(complex)); + if (ccon == NULL) verr("memory allocation error for ccov"); + + rdata1 = (float *)malloc(ntfft*sizeof(float)); + if (rdata1 == NULL) verr("memory allocation error for rdata1"); + + /* forward time-frequency FFT */ + sign = -1; + rcmfft(&data1[0], &cdata1[0], (int)ntfft, 1, (int)ntfft, (int)nfreq, (int)sign); + rcmfft(&data2[0], &cdata2[0], (int)ntfft, 1, (int)ntfft, (int)nfreq, (int)sign); + + /* apply convolution */ + p1r = (float *) &cdata1[0]; + p2r = (float *) &cdata2[0]; + qr = (float *) &ccon[0].r; + p1i = p1r + 1; + p2i = p2r + 1; + qi = qr + 1; + n = nfreq; + for (j = 0; j < n; j++) { + *qr = (*p2r**p1r-*p2i**p1i); + *qi = (*p2r**p1i+*p2i**p1r); + qr += 2; + qi += 2; + p1r += 2; + p1i += 2; + p2r += 2; + p2i += 2; + } + free(cdata1); + free(cdata2); + + /* inverse frequency-time FFT and scale result */ + sign = 1; + scl = 1.0/((float)(ntfft)); + crmfft(&ccon[0], &rdata1[0], (int)ntfft, 1, (int)nfreq, (int)ntfft, (int)sign); + scl_data(rdata1,ntfft,1,scl,con,ntfft); + + free(ccon); + free(rdata1); + return; +} + +void scl_data(float *data, long nsam, long nrec, float scl, float *datout, long nsamout) +{ + long it,ix; + for (ix = 0; ix < nrec; ix++) { + for (it = 0 ; it < nsamout ; it++) + datout[ix*nsamout+it] = scl*data[ix*nsam+it]; + } +} \ No newline at end of file