Skip to content
Snippets Groups Projects
green3D.c 23.14 KiB
#include <genfft.h>
#include "par.h"
#include "segy.h"
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>

#define NINT(x) ((int)((x)>0.0?(x)+0.5:(x)-0.5))
#ifndef MAX
#define	MAX(x,y) ((x) > (y) ? (x) : (y))
#endif
#ifndef MIN
#define	MIN(x,y) ((x) < (y) ? (x) : (y))
#endif
#define SGN(x) ((x) < 0 ? -1.0 : 1.0)


#ifndef COMPLEX
typedef struct _complexStruct { /* complex number */
    float r,i;
} complex;
#endif/* complex */

int disp_fileinfo(char *file, int n1, int n2, float f1, float f2, float d1, float d2, segy *hdrs);
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 *nxm);
int readData(FILE *fp, float *data, segy *hdrs, int n1);

void xwgreen3D(float *data, int nt, int nx, int ny, float dt, float fmin, float fmax, float *xi, float xsrc,
			float dx, float *yi, float ysrc, float dy, float *zi, float zsrc, float c, float cs, float rho,
			float *wavelet, float dipx, float maxdip, int far, int p_vz, int dip, int verbose);


/*********************** self documentation **********************/
char *sdoc[] = {
" 								",
" green - calculation of 2D Greens function in homogenoeus medium based one exact expressions",
" 								",
" green c= zsrc1= [optional parameters]",
" 							        ",
" Required parameters:",
" ",
"   c= ....................... P-wave velocity",
"   cs=0.7*c ................. S-wave velocity",
"   zsrc1= ................... depth of source",
" 							        ",
" Optional parameters:",
" ",
"   file_out= ................ output file (default SU-pipe)",
" RECEIVER POSITIONS ",
"   xrcv=-1500,1500 .......... x-position's of receivers (array)",
"   yrcv=-1500,1500 .......... y-position's of receivers (array)",
"   zrcv=0,0 ................. z-position's of receivers (array)",
"   dxrcv=15 ................. step in receiver x-direction",
"   dyrcv=15 ................. step in receiver y-direction",
"   var=0 .................... variance for irregular sampling (dxrcv +- var)",
"   seed=0 ................... seed for random generator",
"   lint=1 ................... linear interpolate between the rcv points",
"   rrcv= .................... radius for receivers on a circle ",
"   oxrcv=0.0 ................ x-center position of circle",
"   oyrcv=0.0 ................ y-center position of circle",
"   ozrcv=0.0 ................ z-center position of circle",
"   dphi=2 ................... angle between receivers on circle ",
" SOURCE POSITIONS ",
"   xsrc1=0.0 ................ x-position of first source",
"   xsrc2=xsrc1 .............. x-position of last source",
"   dxsrc=0.0 ................ step in source x-direction",
"   ysrc1=0.0 ................ y-position of first source",
"   ysrc2=ysrc1 .............. y-position of last source",
"   dysrc=0.0 ................ step in source y-direction",
"   zsrc2=zsrc1 .............. depth position (z) of last source",
"   dzsrc=0.0 ................ step in source z-direction",
" SAMPLING AND SOURCE DEFINITION ",
"   file_src=spike ........... source wavelet (overrules dt)",
"   nt=256 ................... number of samples",
"   dt=0.004 ................. stepsize in time-direction ",
"   fmin=0 ................... minimum frequency",
"   fmax=70 .................. maximum frequency",
"   dipx=0 ................... local dip of the dipole in x-direction",
"   dipy=0 ................... local dip of the dipole in y-direction",
"   dip=1 .................... 1; dipole 0; monopole source",
"   rho=1000 ................. density",
" FIELD DEFINITION ",
"   far=0 .................... farfield approximation 0=off)",
"   p_vz=0  .................. P or Vz field (0 = P field, 1 = Vz field)",
"   Fz=0  .................... Force source in z with Vz receivers",
"   Fx=0  .................... Force source in x with Vz receivers",
"   maxdip=90 ................ maximum angle (degrees) to be computed ",
"   sum=0 .................... sum all sources",
"   verbose=0 ................ silent option; >0 display info",
"",
"  The P or Vz field of a dipole source at depth z below the receivers",
"  in a homogeneous 2-D medium is calculated.",
"   ",
" author  : Jan Thorbecke : 23-03-1995 (janth@xs4all.nl)",
"                         : revision 2010",
" ",
NULL};
/**************** end self doc ***********************************/

int main(int argc, char **argv)
{
	FILE	*fp_in, *fp_out;
	int     n1, n2, n3, i, j, l, nrx, nry, nrz, dip;
	int     far, p_vz, nt, nx, ny, Nsx, Nsy, is, isy, sum, lint, verbose;
	int     size, ntraces, ngath, Fz, Fx;
	float   scl, xmin, xmax, ymin, ymax;
	float   dx, dy, dt, d1, d2, d3, fmin, fmax, f1, f2, f3, c, cs, rho;
	float 	*data, *wavelet, *tmpdata, dipx, dipy, xsrc1, xsrc2, ysrc1, ysrc2;
	float 	*xrcv, *yrcv, *zrcv, *xi, *yi, *zi, x0, y0, maxdip;
    float   rrcv, dphi, oxrcv, ozrcv;
	float	zsrc1, zsrc2, dxsrc, dysrc, dzsrc, xsrc, ysrc, zsrc, dxrcv, dyrcv;
	char    *file_src, *file_out;
	size_t  nwrite;
	segy	*hdrs;

/* ========================= Reading parameters ====================== */

	initargs(argc, argv);
	requestdoc(1);

	if(!getparint("verbose", &verbose)) verbose = 0;
	if(!getparstring("file_out", &file_out)){
		if (verbose) vwarn("parameter file_out not found, assume pipe");
		file_out = NULL;
	}
	if(!getparstring("file_src", &file_src)) file_src = NULL;
	if(!getparfloat("c", &c)) verr("velocity must be specified.");
    if(!getparfloat("cs", &cs)) cs=0.7*c;
	if(!getparfloat("zsrc1", &zsrc1)) verr("zsrc1(depth) must be specified.");
	if(!getparint("lint", &lint)) lint=1;
	if(!getparfloat("maxdip", &maxdip)) maxdip=90.0;

	nrx  = countparval("xrcv");
    nry  = countparval("yrcv");
	// nrz  = countparval("zrcv");
	nrz = 0;
	if(!getparfloat("dxrcv",&dxrcv)) dxrcv = 15;
    if(!getparfloat("dyrcv",&dyrcv)) dyrcv = 15;

	if (nrx != 0 && nry != 0 && nrz == 0) {
		if (nrx != 2) verr("xrcv should have only two values");
        if (nry != 2) verr("yrcv should have only two values");
		xrcv = (float *)malloc(nrx*sizeof(float));
        yrcv = (float *)malloc(nry*sizeof(float));
		getparfloat("xrcv",xrcv);
        getparfloat("yrcv",yrcv);
		nx = NINT((xrcv[1] - xrcv[0])/dxrcv) + 1;
        ny = NINT((yrcv[1] - yrcv[0])/dyrcv) + 1;
		xi = (float *)malloc(nx*ny*sizeof(float));
        yi = (float *)malloc(nx*ny*sizeof(float));
		zi = (float *)malloc(nx*ny*sizeof(float));
		x0 = xrcv[0];
        y0 = yrcv[0];
		for (i = 0; i < ny; i++) {
            for (j = 0; j < nx; j++) {
                xi[i*nx+j] = x0 + j*dxrcv;
                yi[i*nx+j] = y0 + i*dyrcv;
			    zi[i*nx+j] = 0;
            }
		}
	}
	else if (nrx == 0 && nry == 0 && nrz == 0) {
		nx = NINT((3000)/dxrcv) + 1;
		ny = NINT((3000)/dyrcv) + 1;
		xi = (float *)malloc(nx*ny*sizeof(float));
		yi = (float *)malloc(nx*ny*sizeof(float));
		zi = (float *)malloc(nx*ny*sizeof(float));
		x0 = -1500;
		y0 = -1500;
		for (i = 0; i < ny; i++) {
            for (j = 0; j < nx; j++) {
                xi[i*nx+j] = x0 + j*dxrcv;
                yi[i*nx+j] = y0 + i*dyrcv;
			    zi[i*nx+j] = 0;
            }
		}
	}
	else verr("Number of xrcv and yrcv values are not equal");

	if (verbose) vmess("number of receivers nx = %d, ny = %d total = %d", nx, ny, nx*ny);
	if (verbose == 13) {
		for (j = 0; j < ny; j++) {
			for (i = 0; i < nx; i++) {
				vmess("xi = %d yi = %d x = %f y=%f z = %f", i, j, xi[j*nx+i], yi[j*nx+i], zi[j*nx+i]);
			}
		}
	}

	if(!getparfloat("xsrc1", &xsrc1)) xsrc1=0;
	if(!getparfloat("xsrc2", &xsrc2)) xsrc2=xsrc1;
	if(!getparfloat("dxsrc", &dxsrc)) dxsrc=0.0;
    if(!getparfloat("ysrc1", &ysrc1)) ysrc1=0;
	if(!getparfloat("ysrc2", &ysrc2)) ysrc2=ysrc1;
	if(!getparfloat("dysrc", &dysrc)) dysrc=0.0;
	if(!getparfloat("zsrc2", &zsrc2)) zsrc2=zsrc1;
	if(!getparfloat("dzsrc", &dzsrc)) dzsrc=0;
	if(!getparint("nt", &nt)) nt = 256;
	if(!getparfloat("fmin", &fmin)) fmin = 0.0;
	if(!getparfloat("fmax", &fmax)) fmax = 70.0;
	if(!getparfloat("dipx", &dipx)) dipx = 0.0;
    if(!getparfloat("dipy", &dipy)) dipy = 0.0;
	if(!getparfloat("rho", &rho)) rho = 1000.0;
	if(!getparint("far", &far)) far = 0;
	if(!getparint("p_vz", &p_vz)) p_vz = 0;
    if(!getparint("Fz", &Fz)) Fz = 0;
    if(!getparint("Fx", &Fx)) Fx = 0;
	if(!getparint("dip", &dip)) dip = 1;
	if(!getparint("sum", &sum)) sum = 0;
    if(Fz) p_vz=2;
    if(Fx) p_vz=3;

/* ========================= Opening wavelet file ====================== */

	if (file_src == NULL){
		if(!getparfloat("dt", &dt)) dt = 0.004;
		wavelet = (float *)calloc(nt,sizeof(float));
		wavelet[0] = 1.0;
	}
	else {
		if (verbose) vmess("Reading wavelet from file %s.", file_src);
		ngath = 1;
		getFileInfo(file_src, &n1, &n2, &ngath, &d1, &d2, &f1, &f2, &xmin, &xmax, &scl, &ntraces);
		
		fp_in = fopen(file_src, "r");
		if (fp_in == NULL) verr("error on opening input file_src=%s", file_src);
		
		tmpdata = (float *)calloc(n1*n2,sizeof(float));
		hdrs = (segy *) calloc(n2,sizeof(segy));
		
		n2 = readData(fp_in, tmpdata, hdrs, n1);
		fclose(fp_in);
		if (verbose) {
			disp_fileinfo(file_src, n1, n2, f1,  f2,  d1,  d2, hdrs);
		}
		dt = d1;
		wavelet = (float *)calloc(nt,sizeof(float));

		if (n1 <= nt) {
			for (i = 0; i < n1; i++) wavelet[i] = tmpdata[i];
			for (i = n1; i < nt; i++) wavelet[i] = 0.0;
		}
		else {
			vwarn("file_src has more samples than output");
			for (i = 0; i < nt; i++) wavelet[i] = tmpdata[i];
		}
		if( tmpdata ) free(tmpdata);
		if( hdrs ) free( (void *) hdrs);
	}

/* ============ INITIALIZE AND CHECK PARAMETERS =============== */

	if (xsrc2==xsrc1) Nsx = 1;
	else Nsx = NINT((xsrc2 - xsrc1)/dxsrc) + 1;
	if (ysrc2==ysrc1) Nsy = 1;
	else Nsy = NINT((ysrc2 - ysrc1)/dysrc) + 1;

	if (verbose) vmess("Number of shot records to generate x = %d y = %d", Nsx, Nsy);
	if (Nsx > 1 && Nsy > 1) {
		dxsrc = (xsrc2-xsrc1)/(Nsx-1);
		dysrc = (ysrc2-ysrc1)/(Nsy-1);
		dzsrc = (zsrc2-zsrc1)/(Nsx-1);
		if (verbose) {
			vmess("dxsrc = %f", dxsrc);
			vmess("dysrc = %f", dysrc);
			vmess("dzsrc = %f", dzsrc);
		}
	}

	size = nt * nx *ny;
	dx   = dxrcv;
	dy   = dyrcv;
	tmpdata = (float *)calloc(size,sizeof(float));
	data = (float *)calloc(size,sizeof(float));
	hdrs = (segy *) calloc(nx*ny,sizeof(segy));
	for (i = 0; i < ny; i++) {
		for(j = 0; j < nx; j++) {
			hdrs[i*nx+j].f1= 0.0;
			hdrs[i*nx+j].f2= x0;
			hdrs[i*nx+j].d1= dt;
			hdrs[i*nx+j].d2= dx;
			hdrs[i*nx+j].ns= nt;
			hdrs[i*nx+j].dt= (int)1000000*dt;
			hdrs[i*nx+j].trwf= nx*ny;
			hdrs[i*nx+j].tracl= i*nx+j+1;
			hdrs[i*nx+j].tracf= i*nx+j+1;
			hdrs[i*nx+j].gx = (x0 + j*dx)*1000;
			hdrs[i*nx+j].gy = (y0 + i*dy)*1000;
			hdrs[i*nx+j].scalco = -1000;
			hdrs[i*nx+j].trid = TREAL;
		}
	}
	if (file_out==NULL) fp_out=stdout;
	else fp_out = fopen(file_out,"w");
	if (fp_out == NULL) verr("error in creating output file");

	for (isy = 0; isy < Nsy; isy++) {
		for (is = 0; is < Nsx; is++) {
			xsrc = xsrc1 + is*dxsrc;
			ysrc = ysrc1 + isy*dysrc;
			zsrc = zsrc1 + is*dzsrc;
			if (verbose) vmess("xsrc = %f ysrc=%f zsrc = %f", xsrc, ysrc, zsrc);

			xwgreen3D(data,nt,nx,ny,dt,fmin,fmax,xi,xsrc,dx,yi,ysrc,dy,zi,zsrc,c,cs,rho,wavelet,
				dipx, maxdip, far, p_vz, dip, verbose);

			for (l = 0; l < ny; l++) {
				for (i = 0; i < nx; i++) {
					for (j = 0; j < nt; j++) tmpdata[l*nx*nt+i*nt+j] = data[l*nx*nt+i*nt+j];
					hdrs[l*nx+i].sx = NINT(xsrc*1000);
					hdrs[l*nx+i].sy = NINT(ysrc*1000);
					hdrs[l*nx+i].scalco = -1000;
					hdrs[l*nx+i].offset = xi[l*nx+i]-xsrc;
					hdrs[l*nx+i].gx = NINT(xi[l*nx+i]*1000);
					hdrs[l*nx+i].gy = NINT(yi[l*nx+i]*1000);
					hdrs[l*nx+i].fldr = isy*Nsx+is+1;
					hdrs[l*nx+i].trwf = nx*ny;
					nwrite = fwrite( &hdrs[l*nx+i], 1, TRCBYTES, fp_out);
					assert(nwrite == TRCBYTES);
					nwrite = fwrite( &tmpdata[l*nx*nt+i*nt], sizeof(float), nt, fp_out);
					assert(nwrite == nt);
				}
			}
		}
	}

	if( xi ) free(xi);
	if( yi ) free(yi);
	if( zi ) free(zi);
	if( wavelet ) free( wavelet );

    fclose(fp_out);

	if( data ) free(data);
	if( tmpdata ) free(tmpdata);
	if( hdrs ) free( hdrs);

	exit ( 0 );
}

/***************************************************************************
*  
*   Calculation of pulse response in homogeneous medium
*
*
***************************************************************************/

void xwgreen3D(float *data, int nt, int nx, int ny, float dt, float fmin, float fmax, float *xi, float xsrc, float dx, float *yi, float ysrc, float dy, float *zi, float zsrc, float c, float cs, float rho, float *wavelet, float dipx, float maxdip, int far, int p_vz, int dip, int verbose)
{
	int    	iomin, iomax, iom, ix, iy, nfreq, i, sign, optn;
	float  	df, deltom, om, k, r, x, y, invr, phi, phi2, cosphi;
	float	*rwave, *rdata, cos2, scl, z, kp, ks, sclr;
	complex	*cwave, *cdata, tmp, tmp2, ekr, sum;
    complex H02p, H12p, H02s, H12s, Gp, Gs;

	optn	= optncr(nt);
	nfreq	= 1+(optn/2);
	df		= 1.0/(dt*optn);
	deltom	= 2.*M_PI*df;
	iomin	= (int)MIN((fmin*dt*optn), (nfreq-1));
	iomin	= MAX(iomin, 1);
	iomax	= MIN((int)(fmax*dt*optn), (nfreq-1));

	rdata = (float *)calloc(optn*nx*ny,sizeof(float));
	cdata = (complex *)calloc(nfreq*nx*ny,sizeof(complex));
	rwave = (float *)calloc(optn,sizeof(float));
	cwave = (complex *)calloc(nfreq,sizeof(complex));

	for (i = 0; i < nt; i++) rwave[i] = wavelet[i]*dt;
	for (i = nt; i < optn; i++) rwave[i] = 0.0;
	
	sign = -1;
	rc1fft(rwave, cwave, optn, sign);

	for (iy = 0; iy < ny; iy++) {
		for (ix = 0; ix < nx; ix++) {
			for (iom = 0; iom < iomin; iom++) {
				cdata[iy*nx*nfreq+ix*nfreq+iom].r = 0.0;
				cdata[iy*nx*nfreq+ix*nfreq+iom].i = 0.0;
			}
		}
	}
	for (iy = 0; iy < ny; iy++) {
		for (ix = 0; ix < nx; ix++) {
			for (iom = iomax; iom < nfreq; iom++) {
				cdata[iy*nx*nfreq+ix*nfreq+iom].r = 0.0;
				cdata[iy*nx*nfreq+ix*nfreq+iom].i = 0.0;
			}
		}
	}

	if (p_vz == 0) {
		if (dip == 1) {
			if (verbose) vmess("P field of dipole");
			for (iy = 0; iy < ny; iy++) {
				for (ix = 0; ix < nx; ix++) {
					x      = xi[iy*nx+ix] - xsrc;
					y      = yi[iy*nx+ix] - ysrc;
					z      = fabs(zi[iy*nx+ix] - zsrc);
					r      = sqrt(x*x + y*y + z*z);
					if (r != 0) phi = acos(z/r);
					else phi = M_PI/2;
					phi2   = SGN(x)*phi - (dipx*M_PI/180.0);
					cosphi = 0.25*cos(phi2)*rho;
					if (fabs(phi) < maxdip*M_PI/180.0) {
						/* exp(-jkr) = cos(kr) - j*sin(kr) */
						for (iom = iomin; iom <= iomax; iom++) {
							om = iom*deltom;
							k = om/c;
							ekr.r = cos(k*r)/(r*r);
							ekr.i = sin(-k*r)/(r*r);
							tmp.r = cosphi*(ekr.r - k*r*ekr.i);
							tmp.i = cosphi*(ekr.i + k*r*ekr.r);
							cdata[iy*nx*nfreq+ix*nfreq+iom].r = tmp.r*cwave[iom].r - 
											tmp.i*cwave[iom].i;
							cdata[iy*nx*nfreq+ix*nfreq+iom].i = tmp.r*cwave[iom].i +
											tmp.i*cwave[iom].r;
						}
					}
					else {
						for (iom = iomin; iom <= iomax; iom++) {
							cdata[iy*nx*nfreq+ix*nfreq+iom].r = 0.0;
							cdata[iy*nx*nfreq+ix*nfreq+iom].i = 0.0;
						}
					}
				}
			}
		}
/* There is no far-field definition 'needed' in 3D 
		else if (far == 1 && dip == 1){
			if (verbose) vmess("far P field of dipole");
			for (iy = 0; iy < ny; iy++) {
				for (ix = 0; ix < nx; ix++) {
					x = xi[ix] - xsrc;
					y = yi[iy*nx+ix] - ysrc;
					z = fabs(zi[iy*nx+ix] - zsrc);
					r = sqrt(x*x + y*y + z*z);
					if (r != 0) phi = acos(z/r);
					else phi = M_PI/2;
					phi2   = SGN(x)*phi - (dipx*M_PI/180.0);
					cosphi = 0.5*cos(phi2)*rho/sqrt(r);
					if (fabs(phi) < maxdip*M_PI/180.0) {
						for (iom = iomin; iom <= iomax; iom++) {
							om = iom*deltom;
							k = om/c;
							tmp.r = sqrt(k/(2.0*M_PI))*cosphi*cos(k*r-M_PI/4.0);
							tmp.i = -sqrt(k/(2.0*M_PI))*cosphi*sin(k*r-M_PI/4.0);

							cdata[iy*nx*nfreq+ix*nfreq+iom].r = tmp.r*cwave[iom].r -
											tmp.i*cwave[iom].i;
							cdata[iy*nx*nfreq+ix*nfreq+iom].i = tmp.r*cwave[iom].i +
											tmp.i*cwave[iom].r;
						}
					}
					else {
						for (iom = iomin; iom <= iomax; iom++) {
							cdata[iy*nx*nfreq+ix*nfreq+iom].r = 0.0;
							cdata[iy*nx*nfreq+ix*nfreq+iom].i = 0.0;
						}
					}
				}
			}
		}
*/
		else if (dip == 0){
			if (verbose) vmess("P field of monopole");
			for (iy = 0; iy < ny; iy++) {
				for (ix = 0; ix < nx; ix++) {
					x = xi[iy*nx+ix] - xsrc;
					y = yi[iy*nx+ix] - ysrc;
					z = fabs(zi[iy*nx+ix] - zsrc);
					r = sqrt(x*x + y*y + z*z);
					if (r != 0) phi = acos(z/r);
					else phi = M_PI/2;
					scl = 0.25*rho;
					if (fabs(phi) < maxdip*M_PI/180.0) {
						for (iom = iomin; iom <= iomax; iom++) {
							om = iom*deltom;
							k  = om/c;
							tmp.r = scl*cos(k*r)/(r);
							tmp.i = scl*sin(-k*r)/(r);

							cdata[iy*nx*nfreq+ix*nfreq+iom].r = tmp.r*cwave[iom].r - 
											tmp.i*cwave[iom].i;
							cdata[iy*nx*nfreq+ix*nfreq+iom].i = tmp.r*cwave[iom].i +
											tmp.i*cwave[iom].r;
						}
					}
					else {
						for (iom = iomin; iom <= iomax; iom++) {
							cdata[iy*nx*nfreq+ix*nfreq+iom].r = 0.0;
							cdata[iy*nx*nfreq+ix*nfreq+iom].i = 0.0;
						}
					}
				}
			}
		}
/* There is no far-field definition 'needed' in 3D 
		else if (far == 1 && dip == 0){
			if (verbose) vmess("far P field of monopole");
			for (iy = 0; iy < ny; iy++) {
				for (ix = 0; ix < nx; ix++) {
					x = xi[iy*nx+ix] - xsrc;
					y = yi[iy*nx+ix] - ysrc;
					z = fabs(zi[iy*nx+ix] - zsrc);
					r = sqrt(x*x + y*y + z*z);
					if (r != 0) phi = acos(z/r);
					else phi = M_PI*0.5;
					scl = 0.5*rho/sqrt(r);
					if (fabs(phi) <= M_PI*(maxdip/180.0)) {
						for (iom = iomin; iom <= iomax; iom++) {
							om = iom*deltom;
							k = om/c;
							tmp.r = -sqrt(1.0/(2.0*M_PI*k))*scl*sin(k*r-M_PI/4.0);
							tmp.i = -sqrt(1.0/(2.0*M_PI*k))*scl*cos(k*r-M_PI/4.0);

							cdata[iy*nx*nfreq+ix*nfreq+iom].r = tmp.r*cwave[iom].r -
											tmp.i*cwave[iom].i;
							cdata[iy*nx*nfreq+ix*nfreq+iom].i = tmp.r*cwave[iom].i +
											tmp.i*cwave[iom].r;
						}
					}
					else {
						for (iom = iomin; iom <= iomax; iom++) {
							cdata[iy*nx*nfreq+ix*nfreq+iom].r = 0.0;
							cdata[iy*nx*nfreq+ix*nfreq+iom].i = 0.0;
						}
					}
				}
			}
		}
*/
	}
	else if (p_vz == 1) {
		if (dip == 1) {
	    		if (verbose) vmess("Vz field of dipole, this is not yet implemented");
				for (iy = 0; iy < ny; iy++) {
					for (ix = 0; ix < nx; ix++) {
						x = xi[iy*nx+ix] - xsrc;
						y = yi[iy*nx+ix] - ysrc;
						z = fabs(zi[iy*nx+ix] - zsrc);
						r = sqrt(x*x + y*y + z*z);
						invr   = -0.25/(c);
						if (r != 0) phi = acos(z/r);
						else phi = M_PI/2;
						phi2   = SGN(x)*phi - (dipx*M_PI/180.0);
						cosphi = cos(phi2);
						cos2 = cosphi*cosphi;
						if (fabs(phi) < maxdip*M_PI/180.0) {
							for (iom = iomin; iom <= iomax; iom++) {
								om = iom*deltom;
								k = om/c;
								tmp.r = k*cos2*invr*j0(k*r);
								tmp.i = -k*cos2*invr*y0(k*r);
								tmp2.r = k*(1-2*cos2)*invr*j1(k*r)/(k*r);
								tmp2.i = -k*(1-2*cos2)*invr*y1(k*r)/(k*r);
								sum.r = tmp.r + tmp2.r;
								sum.i = tmp.i + tmp2.i;
								cdata[iy*nx*nfreq+ix*nfreq+iom].r = sum.r*cwave[iom].r -
												sum.i*cwave[iom].i;
								cdata[iy*nx*nfreq+ix*nfreq+iom].i = sum.r*cwave[iom].i +
												sum.i*cwave[iom].r;
							}
						}
						else {
							for (iom = iomin; iom <= iomax; iom++) {
								cdata[iy*nx*nfreq+ix*nfreq+iom].r = 0.0;
								cdata[iy*nx*nfreq+ix*nfreq+iom].i = 0.0;
							}
						}
					}
				}
		}
		else {
	    	if (verbose) vmess("Vz field of monopole");

			for (iy = 0; iy < ny; iy++) {
				for (ix = 0; ix < nx; ix++) {
					x      = xi[iy*nx+ix] - xsrc;
					y      = yi[iy*nx+ix] - ysrc;
					z      = fabs(zi[iy*nx+ix] - zsrc);
					r      = sqrt(x*x + y*y + z*z);
					if (r != 0) phi = acos(z/r);
					else phi = M_PI/2;
					phi2   = SGN(x)*phi - (dipx*M_PI/180.0);
					cosphi = 0.25*cos(phi2)/c;
					if (fabs(phi) < maxdip*M_PI/180.0) {
						/* exp(-jkr) = cos(kr) - j*sin(kr) */
						for (iom = iomin; iom <= iomax; iom++) {
							om = iom*deltom;
							k = om/c;
							ekr.r = cos(k*r)/(r*r);
							ekr.i = sin(-k*r)/(r*r);
							tmp.r = cosphi*(ekr.r - k*r*ekr.i);
							tmp.i = cosphi*(ekr.i + k*r*ekr.r);
							cdata[iy*nx*nfreq+ix*nfreq+iom].r = tmp.r*cwave[iom].r - 
											tmp.i*cwave[iom].i;
							cdata[iy*nx*nfreq+ix*nfreq+iom].i = tmp.r*cwave[iom].i +
											tmp.i*cwave[iom].r;
						}
					}
					else {
						for (iom = iomin; iom <= iomax; iom++) {
							cdata[iy*nx*nfreq+ix*nfreq+iom].r = 0.0;
							cdata[iy*nx*nfreq+ix*nfreq+iom].i = 0.0;
						}
					}
				}
			}
		}
	}
    else if (p_vz == 2) { /* Fz source with Vz receivers Fz=1 == p_vz=2 */
        for (iy = 0; iy < ny; iy++) {
			for (ix = 0; ix < nx; ix++) {
				x = xi[iy*nx+ix] - xsrc;
				y = yi[iy*nx+ix] - ysrc;
				z = fabs(zi[iy*nx+ix] - zsrc);
				r = sqrt(x*x + y*y + z*z);

				if (r != 0) phi = acos(z/r);
				else phi = M_PI/2;
				phi2   = SGN(x)*phi - (dipx*M_PI/180.0);
				cosphi = cos(phi2);
				sclr = (z*z-x*x-y*y)/(r);
				if (fabs(phi) < maxdip*M_PI/180.0) {
					for (iom = iomin; iom <= iomax; iom++) {
						om = iom*deltom;
						kp = om/c;
						ks = om/cs;
						H02p.r = j0(kp*r);
						H02p.i = -y0(kp*r);
						H12p.r = j1(kp*r);
						H12p.i = -y1(kp*r);
						
						H02s.r = j0(ks*r);
						H02s.i = -y0(ks*r);
						H12s.r = j1(ks*r);
						H12s.i = -y1(ks*r);

						Gp.r = kp/(4*om*rho*r*r)*(-z*z*kp*H02p.r + sclr*H12p.r);
						Gp.i = kp/(4*om*rho*r*r)*(-z*z*kp*H02p.i + sclr*H12p.i);

						Gs.r = ks/(4*om*rho*r*r)*(-z*z*ks*H02s.r + sclr*H12s.r);
						Gs.i = ks/(4*om*rho*r*r)*(-z*z*ks*H02s.i + sclr*H12s.i);

						tmp.i = (-1.0/om)*((om/(4*rho*cs*cs))*(H02s.r) - Gp.r + Gs.r);
						tmp.r = ( 1.0/om)*((om/(4*rho*cs*cs))*(H02s.i) - Gp.i + Gs.i);

						cdata[iy*nx*nfreq+ix*nfreq+iom].r = tmp.r*cwave[iom].r - 
						tmp.i*cwave[iom].i;
						cdata[iy*nx*nfreq+ix*nfreq+iom].i = tmp.r*cwave[iom].i +
						tmp.i*cwave[iom].r;
					}
				}
				else {
					for (iom = iomin; iom <= iomax; iom++) {
						cdata[iy*nx*nfreq+ix*nfreq+iom].r = 0.0;
						cdata[iy*nx*nfreq+ix*nfreq+iom].i = 0.0;
					}
				}
			}
        }

    }
    else if (p_vz == 3) { /* Fx source with Vz receivers Fx=1 == p_vz=3 */
        for (iy = 0; iy < ny; iy++) {
			for (ix = 0; ix < nx; ix++) {
				x = xi[iy*nx+ix] - xsrc;
				y = yi[iy*nx+ix] - ysrc;
				z = fabs(zi[iy*nx+ix] - zsrc);
				r = sqrt(x*x + y*y + z*z);

				if (r != 0) phi = acos(z/r);
				else phi = M_PI/2;
				phi2   = SGN(x)*phi - (dipx*M_PI/180.0);
				cosphi = cos(phi2);
				scl = (z*x*y)/(4.0*r*r*rho);
				if (fabs(phi) < maxdip*M_PI/180.0) {
					for (iom = iomin; iom <= iomax; iom++) {
						om = iom*deltom;
						kp = om/c;
						ks = om/cs;
						H02p.r = kp*kp*j0(kp*r);
						H02p.i = -kp*kp*y0(kp*r);
						H12p.r = 2.0*kp*j1(kp*r)/r;
						H12p.i = -2.0*kp*y1(kp*r)/r;
						
						H02s.r = ks*ks*j0(ks*r);
						H02s.i = -ks*ks*y0(ks*r);
						H12s.r = 2.0*ks*j1(ks*r)/r;
						H12s.i = -2.0*ks*y1(ks*r)/r;
						
						tmp.i = (scl/(om*om))*((H02p.r-H12p.r) - (H02s.r-H12s.r));
						tmp.r = -(scl/(om*om))*((H02p.i-H12p.i) - (H02s.i-H12s.i));
						
						cdata[iy*nx*nfreq+ix*nfreq+iom].r = tmp.r*cwave[iom].r - 
						tmp.i*cwave[iom].i;
						cdata[iy*nx*nfreq+ix*nfreq+iom].i = tmp.r*cwave[iom].i +
						tmp.i*cwave[iom].r;
					}
				}
				else {
					for (iom = iomin; iom <= iomax; iom++) {
						cdata[iy*nx*nfreq+ix*nfreq+iom].r = 0.0;
						cdata[iy*nx*nfreq+ix*nfreq+iom].i = 0.0;
					}
				}
			}
        }

    }


	scl  = df;
	sign = 1;
	crmfft(&cdata[0], &rdata[0], optn, nx*ny, nfreq, optn, sign);
	for (iy = 0; iy < ny; iy++) {
		for (ix = 0; ix < nx; ix++) {
			for (i = 0; i < nt; i++) {
				data[iy*nx*nt+ix*nt+i] = scl*rdata[iy*nx*optn+ix*optn+i];
			}
		}
	}

	free(cdata);
	free(cwave);
	free(rdata);
	free(rwave);

	return;
}