Skip to content
Snippets Groups Projects
getParameters3D.c 52.15 KiB
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<assert.h>
#include"par.h"
#include"fdelmodc3D.h"

#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define NINT(x) ((long)((x)>0.0?(x)+0.5:(x)-0.5))

/**
*
*  The routine getParameters reads in all parameters to set up a FD modeling.
*  Model and source parameters are used to calculate stability and dispersion relations
*  Source and receiver positions are calculated and checked if they fit into the model.
*
*   AUTHOR:
*           Jan Thorbecke (janth@xs4all.nl)
*           The Netherlands
**/

float gaussGen();

long loptncr(long n);

long getModelInfo3D(char *file_name, long *n1, long *n2, long *n3, 
	float *d1, float *d2, float *d3, float *f1, float *f2, float *f3,
	float *min, float *max, long *axis, long zeroch, long verbose);

long getWaveletInfo3D(char *file_src, long *n1, long *n2, float *d1, float *d2,
	float *f1, float *f2, float *fmax, long *nxm, long verbose);
 
long getWaveletHeaders3D(char *file_src, long n1, long n2, float *gx, float *sx,
	float *gy, float *sy, float *gelev, float *selev, long verbose);

long recvPar3D(recPar *rec, float sub_x0, float sub_y0, float sub_z0,
	float dx, float dy, float dz, long nx, long ny, long nz);

long getParameters3D(modPar *mod, recPar *rec, snaPar *sna, wavPar *wav, srcPar *src,
	shotPar *shot, bndPar *bnd, long verbose)
{
	long isnapmax1, isnapmax2, isnapmax, sna_nrsna;
	long n1, n2, n3, nx, ny, nz, nsrc, ix, axis, ioPz, is0, optn;
	long npxsrc, npysrc, isx0, isy0, isx, isy;
	long idzshot, idxshot, idyshot, nsrctext;
	long src_ix0, src_iy0, src_iz0, src_ix1, src_iy1, src_iz1;
	long disable_check;
	float cp_min, cp_max, cs_min, cs_max, ro_min, ro_max;
	float stabfactor,dispfactor, cmin, dt, fmax, scl, wfct, tapfact;
	float zstart, xstart, ystart, d1, d2, d3, f1, f2, f3, sub_x0, sub_y0, sub_z0;
	float srcendx, srcendy, srcendz, dx, dy, dz;
	float xsrc, ysrc, zsrc, dxshot, dyshot, dzshot, dtshot;
	float dxrcv, dyrcv, dzrcv, dxspread, dyspread, dzspread;
	float tsnap1, tsnap2, dtsnap, dxsnap, dysnap, dzsnap, dtrcv;
	float xsnap1, xsnap2, ysnap1, ysnap2, zsnap1, zsnap2, xmax, ymax, zmax;
	float xsrc1, xsrc2, ysrc1, ysrc2, zsrc1, zsrc2, tsrc1, tsrc2, tlength, tactive;
	float src_anglex, src_angley, src_velox, src_veloy, px, py, grad2rad, rdelay, scaledt;
	float *xsrca, *ysrca, *zsrca, rrcv;
	float Mxx, Myy, Mzz, Mxy, Myz, Mxz;
	float rsrc, oxsrc, oysrc, ozsrc, dphisrc, ncsrc;
	size_t nsamp;
	long i, j, l;
	long cfree;
	long tapleft,tapright,taptop,tapbottom,tapfront, tapback;
	long nxsrc, nysrc, nzsrc;
	long largeSUfile;
	long is,ntraces,length_random;
	float rand;
	char *src_positions, tmpname[1024];
	char* src_txt;
	FILE *fp;

	if (!getparlong("verbose",&verbose)) verbose=0;
	if (!getparlong("disable_check",&disable_check)) disable_check=0;
	if (!getparlong("iorder",&mod->iorder)) mod->iorder=4;
	if (!getparlong("ischeme",&mod->ischeme)) mod->ischeme=1;
    if (!getparlong("sh",&mod->sh)) mod->sh=0;

	if (!getparstring("file_cp",&mod->file_cp)) {
		verr("parameter file_cp required!");
	}
	if (!getparstring("file_den",&mod->file_ro)) {
		verr("parameter file_den required!");
	}
	if (mod->ischeme>2 && mod->ischeme!=5) {
		if (!getparstring("file_cs",&mod->file_cs)) {
			verr("parameter file_cs required!");
		}
	}
	if (!getparstring("file_src",&wav->file_src)) wav->file_src=NULL;
	if (!getparstring("file_snap",&sna->file_snap)) sna->file_snap="snap.su";
	if (!getparstring("file_beam",&sna->file_beam)) sna->file_beam="beam.su";
	if (!getparstring("file_rcv",&rec->file_rcv)) rec->file_rcv="recv.su";
	if (!getparlong("grid_dir",&mod->grid_dir)) mod->grid_dir=0;
	if (!getparlong("src_at_rcv",&src->src_at_rcv)) src->src_at_rcv=1;
	
	/* read model parameters, which are used to set up source and receivers and check stability */
	
	getModelInfo3D(mod->file_cp, &nz, &nx, &ny, &dz, &dx, &dy, &sub_z0, &sub_x0, &sub_y0, &cp_min, &cp_max, &axis, 1, verbose);
	getModelInfo3D(mod->file_ro, &n1, &n2, &n3, &d1, &d2, &d3, &zstart, &xstart, &ystart, &ro_min, &ro_max, &axis, 0, verbose);

	mod->cp_max = cp_max;
	mod->cp_min = cp_min;
	mod->ro_max = ro_max;
	mod->ro_min = ro_min;
	assert( (ro_min != 0.0) );
	if (NINT(100*(dx/d2)) != 100) 
		vwarn("dx differs for file_cp and file_den!");
    if (NINT(100*(dy/d3)) != 100) 
		vwarn("dy differs for file_cp and file_den!");
	if (NINT(100*(dz/d1)) != 100) 
		vwarn("dz differs for file_cp and file_den!");
	if (nx != n2) 
		vwarn("nx differs for file_cp and file_den!");
    if (ny != n3) 
		vwarn("nx differs for file_cp and file_den!");
	if (nz != n1) 
		vwarn("nz differs for file_cp and file_den!");

	if (mod->ischeme>2 && mod->ischeme!=5) {
		getModelInfo3D(mod->file_cs, &n1, &n2, &n3, &d1, &d2, &d3, &zstart, &xstart, &ystart, &cs_min, &cs_max, &axis, 1, verbose);
		mod->cs_max = cs_max;
		mod->cs_min = cs_min;
		if (NINT(100*(dx/d2)) != 100) 
			vwarn("dx differs for file_cp and file_cs!");
        if (NINT(100*(dy/d3)) != 100) 
			vwarn("dy differs for file_cp and file_cs!");
		if (NINT(100*(dz/d1)) != 100) 
			vwarn("dz differs for file_cp and file_cs!");
		if (nx != n2) 
			vwarn("nx differs for file_cp and file_cs!");
        if (ny != n3) 
			vwarn("ny differs for file_cp and file_cs!");
		if (nz != n1) 
			vwarn("nz differs for file_cp and file_cs!");
	}
	if (mod->ischeme==5) {
		cs_max=0.0; cs_min=0.0;
		mod->cs_max = cs_max;
		mod->cs_min = cs_min;
	}
		
	mod->nfz = nz;
	mod->nfx = nx;
	mod->nfy = ny;
    /* check if 1D, 2D or full 3D gridded model is given as input model */
	if (nx==1 && ny==1 ) { // 1D model 
        if (!getparlong("nx",&nx)) nx=nz;
        if (!getparlong("ny",&ny)) ny=nx;
		dx=dz;
		dy=dx;
    	sub_x0=-0.5*(nx-1)*(dx);
    	sub_y0=-0.5*(ny-1)*(dy);
	}
	else if (ny==1) { // 2D model
        if (!getparlong("ny",&ny)) ny=nx;
		dy=dx;
    	sub_y0=-0.5*(ny-1)*(dy);
		fprintf(stderr,"get param ny=%ld dy=%f y0=%f\n", ny, dy, sub_y0);
	}
	mod->dz = dz;
	mod->dx = dx;
	mod->dy = dy;
	mod->nz = nz;
	mod->nx = nx;
	mod->ny = ny;

// end of part1 ################################################################################################

	/* define wavelet(s), modeling time and wavelet maximum frequency */ 
	if (wav->file_src!=NULL) {
		getWaveletInfo3D(wav->file_src, &wav->ns, &wav->nx, &wav->ds, &d2, &f1, &f2, &fmax, &ntraces, verbose);

		if (wav->ds <= 0.0) {
			vwarn("dt in wavelet (file_src) equal to 0.0 or negative.");
			vwarn("Use parameter dt= to overule dt from file_src.");
		}
        wav->nt = wav->ns;
		wav->dt = wav->ds;
		if(!getparfloat("tmod",&mod->tmod)) mod->tmod = (wav->nt-1)*wav->dt;
		if(!getparfloat("dt",&mod->dt)) mod->dt=wav->dt;

        if (NINT(wav->ds*1000000) != NINT(mod->dt*1000000)) {
			if (wav->dt > mod->dt) {
				scaledt = wav->dt/mod->dt;
				scaledt = floorf(wav->dt/mod->dt);
    			optn = loptncr(wav->ns);
				wav->nt  = floorf(scaledt*optn);
				vmess("file_src dt-scalefactor=%f : wav.dt=%e ==interpolated==> mod.dt=%e", scaledt, wav->dt, mod->dt);
				wav->dt = mod->dt;
			}
			else {
				wav->dt = mod->dt; /* in case if wav.dt is smaller than 1e-7 and can not be read by SU-getpar */
			}
		}
		if(!getparfloat("fmax",&wav->fmax)) wav->fmax=fmax;
	}
	else {
		fmax = 50;
		if(!getparfloat("dt",&mod->dt)) verr("dt must be given or use file_src=");
		if(!getparfloat("tmod",&mod->tmod)) verr("tmod must be given");
		if(!getparfloat("fmax",&wav->fmax)) wav->fmax=fmax;
		fmax = wav->fmax;
		wav->dt=mod->dt;
	}
	assert(mod->dt!=0.0);
	/* check if receiver delays is defined; option inactive: add delay time to total modeling time */
	if (!getparfloat("rec_delay",&rdelay)) rdelay=0.0;
	rec->delay=NINT(rdelay/mod->dt);
	mod->nt = NINT(mod->tmod/mod->dt);
	dt = mod->dt;

	if (!getparlong("src_type",&src->type)) src->type=1;
	if (!getparfloat("src_Mxx",&src->Mxx)) src->Mxx=0.0;
	if (!getparlong("src_orient",&src->orient)) {
		src->orient=1;
		if (getparlong("dipsrc",&src->orient)) src->orient=2; // for compatability with DELPHI's fdacmod
	}
	if (mod->ischeme<=2) {
		if (src->type>1 && src->type<6)
			verr("Invalid src_type for acoustic scheme!");
	}
	if (mod->ischeme==2 || mod->ischeme==4) {
		if (!getparstring("file_qp",&mod->file_qp)) mod->file_qp=NULL;
		if (!getparstring("file_qs",&mod->file_qs)) mod->file_qs=NULL;
		if (!getparfloat("Qp",&mod->Qp)) mod->Qp=1;
		if (!getparfloat("Qs",&mod->Qs)) mod->Qs=mod->Qp;
		if (!getparfloat("fw",&mod->fw)) mod->fw=0.5*wav->fmax;
	}

	/* dissipative medium option for Evert */
	if (mod->ischeme==-1) {
		if (!getparfloat("qr",&mod->qr)) mod->qr=0.1;
	}
	assert(src->type > 0);

/* dispersion factor to 10 points per wavelength (2nd order)
   or 5 points per wavelength (4th order) */

	if (mod->iorder == 2) {
		dispfactor=10;
		stabfactor = 1.0/sqrt(2.0);
	}
	else {
		dispfactor = 6;
		//stabfactor = 0.606; /* courant number */
		stabfactor = 0.495; //Joeri check: number changes in 3D case. Sei&Simes, 1995.
		/*However as we will see in the sequel, the stability condition
has only an indicative role. We will have to choose p = c. A t/Ax much less
than the maximum allowed by the stability condition to fulfill the precision
criteria we have imposed.*/
	}
    
// end of part2 ################################################################################################

    /* origin of model in real (non-grid) coordinates */
	mod->x0 = sub_x0;
    mod->y0 = sub_y0;
	mod->z0 = sub_z0;
	xmax = sub_x0+(nx-1)*dx;
	ymax = sub_y0+(ny-1)*dy;
	zmax = sub_z0+(nz-1)*dz;

	if (verbose) {
		vmess("*******************************************");
		vmess("************** general info ***************");
		vmess("*******************************************");
		vmess("tmod    = %f",mod->tmod);
		vmess("ntsam   = %li   dt      = %f(%e)",mod->nt, mod->dt, mod->dt);
		if (mod->ischeme == 1) vmess("Acoustic staggered grid, pressure/velocity");
		if (mod->ischeme == 2) vmess("Visco-Acoustic staggered grid, pressure/velocity");
		if (mod->ischeme == 3) vmess("Elastic staggered grid, stress/velocity");
		if (mod->ischeme == 4) vmess("Visco-Elastic staggered grid, stress/velocity");
		if (mod->ischeme == 5) vmess("Acoustic staggered grid, Txx/Tzz/velocity");
		if (mod->grid_dir) vmess("Time reversed modelling");
		else vmess("Forward modelling");
		vmess("*******************************************");
		vmess("*************** model info ****************");
		vmess("*******************************************");
		if (mod->nfx == 1) {
			vmess(" 1-dimensional model is read from file");
		}
		else if (mod->nfy == 1) {
			vmess(" 2-dimensional model is read from file");
		}
		else {
			vmess(" 3-dimensional model is read from file");
		}
		vmess("nz      = %li    ny      = %li nx      = %li", nz, ny, nx);
		vmess("dz      = %8.4f  dy      = %8.4f dx      = %8.4f", dz, dy, dx);
		vmess("zmin    = %8.4f  zmax    = %8.4f", sub_z0, zmax);
		vmess("ymin    = %8.4f  ymax    = %8.4f", sub_y0, ymax);
		vmess("xmin    = %8.4f  xmax    = %8.4f", sub_x0, xmax);
		vmess("min(cp) = %9.3f  max(cp) = %9.3f", cp_min, cp_max);
		if (mod->ischeme>2 && mod->ischeme!=5) vmess("min(cs) = %9.3f  max(cs) = %9.3f", cs_min, cs_max);
		vmess("min(ro) = %9.3f  max(ro) = %9.3f", ro_min, ro_max);
		if (mod->ischeme==2 || mod->ischeme==4) {
			if (mod->file_qp!=NULL) vmess("Qp from file %s   ", mod->file_qp);
			else vmess("Qp      = %9.3f   ", mod->Qp);
			vmess("at freq = %5.3f", mod->fw);
		}
		if (mod->ischeme==4) {
			if (mod->file_qs!=NULL) vmess("Qs from file %s   ", mod->file_qs);
			else vmess("Qs      = %9.3f ", mod->Qs);
			vmess("at freq = %5.3f", mod->fw);
		}
	}

	if (mod->ischeme <= 2) {
		cmin = cp_min;
	}
	else {
		cmin = cs_min; 
		if ( (cmin<1e-20) || (cp_min<cs_min) ) cmin=cp_min;
	}

	if (verbose) {
		vmess("*******************************************");
		vmess("******** dispersion and stability *********");
		vmess("*******************************************");
		vmess("Dispersion criterion is %3d points per wavelength: ", NINT(dispfactor));
		vmess(" ====> wavelength > %f m [dx*disp]", dx*dispfactor);
		vmess("The maximum frequency in source wavelet must be:");
		vmess(" ====> frequency < %f Hz. [Cmin/dx*disp]", cmin/(dx*dispfactor));
		vmess("Stability criterion for current settings: ");
		vmess(" ====> Cp < %f m/s [dx*disp/dt]", dx*stabfactor/dt);
		if (wav->file_src != NULL) vmess(" For wavelet(s) in file_src fmax = %f", fmax);
		vmess("Optimal discretisation for current model:");
		vmess(" With maximum velocity  = %f dt <= %e", cp_max,dx*stabfactor/cp_max);
		vmess(" With maximum frequency = %f dx <= %e", wav->fmax, cmin/(wav->fmax*dispfactor));
	}

	/* Check stability and dispersion setting */

	if (cp_max > dx*stabfactor/dt) {
		vwarn("************ ! Stability ! ****************");
		vwarn("From the input file maximum P-wave velocity");
		vwarn("in the current model is %f !!", cp_max);
		vwarn("Hence, adjust dx >= %.4f,",cp_max*dt/stabfactor);
		vwarn("    or adjust dt <= %f,",dx*stabfactor/cp_max);
		vwarn("    or lower the maximum velocity below %.3f m/s.",dx*stabfactor/dt);
		vwarn("***************** !!! *********************");
		if (!disable_check) verr("********* leaving program *********");
	}
	if (wav->fmax > cmin/(dx*dispfactor)) {
		vwarn("*********** ! Dispersion ! ****************");
		vwarn("The maximum frequency in the source wavelet is");
		vwarn("%.3f for stable modeling fmax < %.3f ", wav->fmax, cmin/(dx*dispfactor));
		vwarn("Hence, adjust dx <= %.4f",cmin/(wav->fmax*dispfactor));
		vwarn("  or adjust fmax <= %f (overruled with parameter fmax=),",cmin/(dx*dispfactor));
		vwarn("  or increase the minimum velocity above %.3f m/s.",dx*dispfactor*wav->fmax);
		vwarn("***************** !!! *********************");
		if (!disable_check) verr("********* leaving program *********");
	}

	/* to support old parameter interface */
	if (!getparlong("cfree",&cfree)) taptop=1;
	if (!getparlong("tapleft",&tapleft)) tapleft=0;
	if (!getparlong("tapright",&tapright)) tapright=0;
	if (!getparlong("taptop",&taptop)) taptop=0;
	if (!getparlong("tapbottom",&tapbottom)) tapbottom=0;
	if (!getparlong("tapfront",&tapfront)) tapfront=0;
	if (!getparlong("tapback",&tapback)) tapback=0;

	if (tapleft) bnd->lef=4;
    else bnd->lef=1;
	if (tapright) bnd->rig=4;
    else bnd->rig=1;
	if (taptop) bnd->top=4;
    else bnd->top=1;
	if (tapbottom) bnd->bot=4;
    else bnd->bot=1;
	if (tapfront) bnd->fro=4;
    else bnd->fro=1;
	if (tapback) bnd->bac=4;
    else bnd->bac=1;

	/* define the type of boundaries */
	/* 1=free 2=pml 3=rigid 4=taper */
	if (!getparlong("left",&bnd->lef) && !tapleft) bnd->lef=4;
	if (!getparlong("right",&bnd->rig)&& !tapright) bnd->rig=4;
	if (!getparlong("top",&bnd->top) && !taptop) bnd->top=1;
	if (!getparlong("bottom",&bnd->bot) && !tapbottom) bnd->bot=4;
	if (!getparlong("front",&bnd->fro) && !tapfront) bnd->fro=4;
	if (!getparlong("back",&bnd->bac) && !tapback) bnd->bac=4;

    /* calculate default taper length to be three wavelenghts */
	if (!getparlong("ntaper",&bnd->ntap)) bnd->ntap=0; // bnd->ntap=3*NINT((cp_max/wav->fmax)/dx);
	if (!bnd->ntap) if (!getparlong("npml",&bnd->ntap)) bnd->ntap=3*NINT((cp_max/wav->fmax)/dx);
	if (!getparfloat("R",&bnd->R)) bnd->R=1e-5;
	if (!getparfloat("m",&bnd->m)) bnd->m=2.0;
	bnd->npml=bnd->ntap;


	if (bnd->ntap) {
		bnd->tapx   = (float *)malloc(bnd->ntap*sizeof(float));
        bnd->tapy   = (float *)malloc(bnd->ntap*sizeof(float));
		bnd->tapz   = (float *)malloc(bnd->ntap*sizeof(float));
		bnd->tapxz  = (float *)malloc(bnd->ntap*bnd->ntap*sizeof(float));
		bnd->tapxyz = (float *)malloc(bnd->ntap*bnd->ntap*bnd->ntap*sizeof(float));
        if(!getparfloat("tapfact",&tapfact)) tapfact=0.30;
		scl = tapfact/((float)bnd->ntap);
		for (i=0; i<bnd->ntap; i++) {
			wfct = (scl*i);
			bnd->tapx[i] = exp(-(wfct*wfct));

            bnd->tapy[i] = exp(-(wfct*wfct));

			wfct = (scl*(i+0.5));
			bnd->tapz[i] = exp(-(wfct*wfct));
		}
		//corner
		for (j=0; j<bnd->ntap; j++) {
			for (i=0; i<bnd->ntap; i++) {
				wfct = (scl*sqrt(i*i+j*j));
				bnd->tapxz[j*bnd->ntap+i] = exp(-(wfct*wfct));
			}
		}
		//double corner
		for (j=0; j<bnd->ntap; j++) {
			for (i=0; i<bnd->ntap; i++) {
				for (l=0; l<bnd->ntap; l++) {
					wfct = (scl*sqrt(i*i+j*j+l*l));
					bnd->tapxyz[l*(bnd->ntap)*(bnd->ntap)+j*(bnd->ntap)+i] = exp(-(wfct*wfct));
				}
			}
		}
	}

    /* Vx: rox */
	mod->ioXx=mod->iorder/2;
    mod->ioXy=mod->iorder/2-1;
	mod->ioXz=mod->iorder/2-1;
    /* Vy: roy */
	mod->ioYx=mod->iorder/2-1;
    mod->ioYy=mod->iorder/2;
	mod->ioYz=mod->iorder/2-1;
	/* Vz: roz */
    mod->ioZx=mod->iorder/2-1;
    mod->ioZy=mod->iorder/2-1;
	mod->ioZz=mod->iorder/2;
	/* P, Txx, Tzz: lam, l2m */
	mod->ioPx=mod->iorder/2-1;
    mod->ioPy=mod->ioPx;
	mod->ioPz=mod->ioPx;
	/* Txz: mul */
	mod->ioTx=mod->iorder/2;
    mod->ioTy=mod->ioTx;
	mod->ioTz=mod->ioTx;

    /* end loop iteration in FD kernels */
    /* Vx: rox */
	mod->ieXx=nx+mod->ioXx;
	mod->ieXy=ny+mod->ioXy;
	mod->ieXz=nz+mod->ioXz;
    /* Vy: roy */
	mod->ieYx=nx+mod->ioYx;
	mod->ieYy=ny+mod->ioYy;
	mod->ieYz=nz+mod->ioYz;
	/* Vz: roz */
	mod->ieZx=nx+mod->ioZx;
    mod->ieZy=ny+mod->ioZy;
    mod->ieZz=nz+mod->ioZz;
	/* P, Txx, Tzz: lam, l2m */
	mod->iePx=nx+mod->ioPx;
	mod->iePy=ny+mod->ioPy;
	mod->iePz=nz+mod->ioPz;
	/* Txz: muu */
	mod->ieTx=nx+mod->ioTx;
	mod->ieTy=ny+mod->ioTy;
	mod->ieTz=nz+mod->ioTz;
    
    mod->naz = mod->nz+mod->iorder;
    mod->nay = mod->ny+mod->iorder;
    mod->nax = mod->nx+mod->iorder;

    /* for tapered and PML extra points are needed at the boundaries of the model */    
    if (bnd->top==4 || bnd->top==2) {
        mod->naz  += bnd->ntap; 
        mod->ioXz += bnd->ntap; 
        mod->ioYz += bnd->ntap;
        mod->ioZz += bnd->ntap;
        mod->ieXz += bnd->ntap;
        mod->ieYz += bnd->ntap;
        mod->ieZz += bnd->ntap;
        /* For P/Tzz, Txx and Txz fields the tapered boundaries are calculated in the main kernels */
        mod->iePz += bnd->ntap;
        mod->ieTz += bnd->ntap;
    }
    if (bnd->bot==4 || bnd->bot==2) {
        mod->naz += bnd->ntap;
        /* For P/Tzz, Txx and Txz fields the tapered boundaries are calculated in the main kernels */
        mod->iePz += bnd->ntap;
        mod->ieTz += bnd->ntap;
    }
    if (bnd->lef==4 || bnd->lef==2) {
        mod->nax += bnd->ntap;
        mod->ioXx += bnd->ntap;
        mod->ioYx += bnd->ntap;
        mod->ioZx += bnd->ntap;
        mod->ieXx += bnd->ntap;
        mod->ieYx += bnd->ntap;
        mod->ieZx += bnd->ntap;
        /* For Tzz, Txx and Txz fields the tapered boundaries are calculated in the main kernels */
        mod->iePx += bnd->ntap;
        mod->ieTx += bnd->ntap;
    }
    if (bnd->rig==4 || bnd->rig==2) {
        mod->nax += bnd->ntap;
        /* For P/Tzz, Txx and Txz fields the tapered boundaries are calculated in the main kernels */
        mod->iePx += bnd->ntap;
        mod->ieTx += bnd->ntap;
    }
	if (bnd->fro==4 || bnd->fro==2) {
        mod->nay += bnd->ntap;
        mod->ioXy += bnd->ntap;
        mod->ioYy += bnd->ntap;
        mod->ioZy += bnd->ntap;
        mod->ieXy += bnd->ntap;
        mod->ieYy += bnd->ntap;
        mod->ieZy += bnd->ntap;
        /* For Tzz, Txx and Txz fields the tapered boundaries are calculated in the main kernels */
        mod->iePy += bnd->ntap;
        mod->ieTy += bnd->ntap;
    }
    if (bnd->bac==4 || bnd->bac==2) {
        mod->nay += bnd->ntap;
        /* For P/Tzz, Txx and Txz fields the tapered boundaries are calculated in the main kernels */
        mod->iePy += bnd->ntap;
        mod->ieTy += bnd->ntap;
    } 

	/* Intialize the array which contains the topography surface */
    if (bnd->top==4 || bnd->top==2) ioPz=mod->ioPz - bnd->ntap;
	else ioPz=mod->ioPz;
	ioPz=mod->ioPz;
	bnd->surface = (long *)malloc((mod->nax*mod->nay+mod->naz)*sizeof(long));
	for (ix=0; ix<mod->nax*mod->nay+mod->naz; ix++) {
		bnd->surface[ix] = ioPz;
	}

	if (verbose) {
		vmess("*******************************************");
		vmess("************* boundary info ***************");
		vmess("*******************************************");
		vmess("***  1=free 2=pml 3=rigid 4=tapered     ***");
		vmess("Top boundary    : %li",bnd->top);
		vmess("Left boundary   : %li",bnd->lef);
		vmess("Right boundary  : %li",bnd->rig);
		vmess("Bottom boundary : %li",bnd->bot);
		vmess("Front boundary  : %li",bnd->fro);
		vmess("Back boundary   : %li",bnd->bac);
        vmess("taper length = %li points",bnd->ntap);
	}

	/* define the number and type of shots to model */
	/* each shot can have multiple sources arranged in different ways */
    
	if (!getparfloat("xsrc",&xsrc)) xsrc=sub_x0+((nx-1)*dx)/2.0;
	if (!getparfloat("ysrc",&ysrc)) ysrc=sub_y0+((ny-1)*dy)/2.0;
	if (!getparfloat("zsrc",&zsrc)) zsrc=sub_z0;

	if (!getparlong("nshot",&shot->n)) shot->n=1;
	if (!getparfloat("dxshot",&dxshot)) dxshot=dx;
	if (!getparfloat("dyshot",&dyshot)) dyshot=dy;
	if (!getparfloat("dzshot",&dzshot)) dzshot=0.0;
	if (!getparfloat("dip",&src->dip)) src->dip=0.0;
	if (!getparfloat("strike",&src->strike)) src->strike=0.0;
	if (!getparfloat("rake",&src->rake)) src->rake=0.0;
	src->dip = M_PI*(src->dip/180.0);
	src->strike = M_PI*(src->strike/180.0);
	src->rake = M_PI*(src->rake/180.0);

	if (shot->n>1) {
		idxshot=MAX(0,NINT(dxshot/dx));
		idyshot=MAX(0,NINT(dyshot/dy));
		idzshot=MAX(0,NINT(dzshot/dz));
	}
	else {
		idxshot=0.0;
		idyshot=0.0;
		idzshot=0.0;
	}
	
	/* calculate the shot positions */	
	src_ix0=MAX(0,NINT((xsrc-sub_x0)/dx));
	src_ix0=MIN(src_ix0,nx);
	src_iy0=MAX(0,NINT((ysrc-sub_y0)/dy));
	src_iy0=MIN(src_iy0,ny);
	src_iz0=MAX(0,NINT((zsrc-sub_z0)/dz));
	src_iz0=MIN(src_iz0,nz);
	srcendx=(shot->n-1)*dxshot+xsrc;
	srcendy=(shot->n-1)*dyshot+ysrc;
	srcendz=(shot->n-1)*dzshot+zsrc;
	src_ix1=MAX(0,NINT((srcendx-sub_x0)/dx));
	src_ix1=MIN(src_ix1,nx);
	src_iy1=MAX(0,NINT((srcendy-sub_y0)/dy));
	src_iy1=MIN(src_iy1,ny);
	src_iz1=MAX(0,NINT((srcendz-sub_z0)/dz));
	src_iz1=MIN(src_iz1,nz);

	shot->x = (long *)calloc(shot->n,sizeof(long));
	shot->y = (long *)calloc(shot->n,sizeof(long));
	shot->z = (long *)calloc(shot->n,sizeof(long));
	for (is=0; is<shot->n; is++) {
		shot->x[is] = src_ix0+is*idxshot;
		shot->y[is] = src_iy0+is*idyshot;
		shot->z[is] = src_iz0+is*idzshot;
		if (shot->x[is] > nx-1) shot->n = is-1;
		if (shot->y[is] > ny-1) shot->n = is-1;
		if (shot->z[is] > nz-1) shot->n = is-1;
	}

	/* check if source array is defined */
	nxsrc = countparval("xsrca");
	nysrc = countparval("ysrca");
	nzsrc = countparval("zsrca");
	if (nxsrc != nzsrc) {
		verr("Number of sources in array xsrca (%li), ysrca (%li), zsrca (%li) are not equal",nxsrc, nysrc, nzsrc);
	}

	/* source positions defined through txt file */
   	if (!getparstring("src_txt",&src_txt)) src_txt=NULL;

	/* check if sources on a circle are defined */
	if (getparfloat("rsrc", &rsrc)) {
		if (!getparfloat("dphisrc",&dphisrc)) dphisrc=2.0;
		if (!getparfloat("oxsrc",&oxsrc)) oxsrc=0.0;
		if (!getparfloat("oysrc",&oysrc)) oysrc=0.0;
		if (!getparfloat("ozsrc",&ozsrc)) ozsrc=0.0;
		ncsrc = NINT(360.0/dphisrc);
        src->n = nsrc;
		
		src->x = (long *)malloc(ncsrc*sizeof(long));
		src->y = (long *)malloc(ncsrc*sizeof(long));
		src->z = (long *)malloc(ncsrc*sizeof(long));

		for (ix=0; ix<ncsrc; ix++) {
			src->x[ix] = NINT((oxsrc-sub_x0+rsrc*cos(((ix*dphisrc)/360.0)*(2.0*M_PI)))/dx);
			src->y[ix] = NINT((oysrc-sub_y0+rsrc*sin(((ix*dphisrc)/360.0)*(2.0*M_PI)))/dy);
			src->z[ix] = NINT((ozsrc-sub_z0+rsrc*sin(((ix*dphisrc)/360.0)*(2.0*M_PI)))/dz);
			if (verbose>4) fprintf(stderr,"Source on Circle: xsrc[%li]=%li ysrc=%li zsrc=%li\n", ix, src->x[ix], src->y[ix], src->z[ix]);
		}	
	}
    
    
    /* TO DO propagate src_positions parameter and structure through code */
	if (!getparstring("src_positions",&src_positions)) src_positions="single";
	wav->random=0;
	src->random=0;
	src->plane=0;
	src->array=0;
	src->single=0;
	if (strstr(src_positions, "single")) src->single=1;
	else if (strstr(src_positions, "array")) src->array=1;
	else if (strstr(src_positions, "random")) src->random=1;
	else if (strstr(src_positions, "plane")) src->plane=1;
	else src->single=1;
    
	/* to maintain functionality of older parameters usage */
	if (!getparlong("src_random",&src->random)) src->random=0;
	if (!getparlong("plane_wave",&src->plane)) src->plane=0;
	
	if (src->random) {
		if (!getparlong("wav_random",&wav->random)) wav->random=1;
		src->plane=0;
		src->array=0;
		src->single=0;
	}
	else {
		if (!getparlong("wav_random",&wav->random)) wav->random=0;
	}
	if (src->plane) {
		src->random=0;
		src->array=0;
		src->single=0;
	}

	if (!wav->random) assert (wav->file_src != NULL);
	if (wav->random) {
		wav->nt=mod->nt;
		wav->dt=mod->dt;
		wav->nx=1;
	}

		
	/* number of sources per shot modeling */
	if (!getparlong("src_nxwindow",&src->nxwindow)) src->nxwindow=0;
	if (!getparlong("src_nywindow",&src->nywindow)) src->nywindow=0;
	src->window = 0;
	if (!getparfloat("src_anglex",&src_anglex)) src_anglex=0.;
	if (!getparfloat("src_angley",&src_angley)) src_angley=0.;
	if (!getparfloat("src_velox",&src_velox)) src_velox=1500.;
	if (!getparfloat("src_veloy",&src_veloy)) src_veloy=1500.;
	if (!getparlong("distribution",&src->distribution)) src->distribution=0;
	if (!getparlong("src_multiwav",&src->multiwav)) src->multiwav=0;
	if (!getparfloat("amplitude", &src->amplitude)) src->amplitude=0.0;
	if (!getparfloat("tlength", &tlength)) tlength=mod->dt*(mod->nt-1);
    if (!getparlong("src_injectionrate", &src->injectionrate)) src->injectionrate=0;
	if (src->random && nxsrc==0) {
		if (!getparlong("nsrc",&nsrc)) nsrc=1;
		if (!getparlong("seed",&wav->seed)) wav->seed=10;
		if (!getparfloat("xsrc1", &xsrc1)) xsrc1=sub_x0;
		if (!getparfloat("xsrc2", &xsrc2)) xsrc2=xmax;
		if (!getparfloat("ysrc1", &ysrc1)) ysrc1=sub_y0;
		if (!getparfloat("ysrc2", &ysrc2)) ysrc2=ymax;
		if (!getparfloat("zsrc1", &zsrc1)) zsrc1=sub_z0;
		if (!getparfloat("zsrc2", &zsrc2)) zsrc2=zmax;
		if (!getparfloat("tsrc1", &tsrc1)) tsrc1=0.0;
		if (!getparfloat("tsrc2", &tsrc2)) tsrc2=mod->tmod;
		if (!getparfloat("tactive", &tactive)) tactive=tsrc2;
		tsrc2  = MIN(tsrc2, mod->tmod);
		if (!getparfloat("tlength", &tlength)) tlength=tsrc2-tsrc1;
		if (!getparlong("length_random", &length_random)) length_random=1;
		dxshot = xsrc2-xsrc1;
		dyshot = ysrc2-ysrc1;
		dzshot = zsrc2-zsrc1;
		dtshot = tsrc2-tsrc1;
		if (wav->random) {
			if (!getparlong("src_multiwav",&src->multiwav)) src->multiwav=1;
			if (src->multiwav) wav->nx = nsrc;
			else wav->nx = 1;
		}
		if (wav->random) wav->nt = NINT(tlength/mod->dt)+1;
		src->tbeg = (float *)malloc(nsrc*sizeof(float));
		src->tend = (float *)malloc(nsrc*sizeof(float));
		wav->nsamp = (size_t *)malloc((nsrc+1)*sizeof(size_t));
		src->x = (long *)malloc(nsrc*sizeof(long));
		src->y = (long *)malloc(nsrc*sizeof(long));
		src->z = (long *)malloc(nsrc*sizeof(long));
		nsamp = 0;
		srand48(wav->seed);
		for (is=0; is<nsrc; is++) {
			rand = (float)drand48();
			src->x[is] = NINT((xsrc1+rand*dxshot-sub_x0)/dx);
			rand = (float)drand48();
			src->y[is] = NINT((ysrc1+rand*dyshot-sub_y0)/dy);
			rand = (float)drand48();
			src->z[is] = NINT((zsrc1+rand*dzshot-sub_z0)/dz);
			if (length_random) rand = (float)drand48();
			else rand = 0.0;
			src->tbeg[is] = tsrc1+rand*(dtshot);
			if (wav->random) {
				if (src->distribution) rand = fabsf(tlength+gaussGen()*tlength);
				else rand = (float)drand48()*tlength;
				if (length_random!=1) rand = tlength;
				src->tend[is] = MIN(src->tbeg[is]+rand, tactive);
				wav->nsamp[is] = (size_t)(NINT((src->tend[is]-src->tbeg[is])/mod->dt)+1);
			}
			else {
				src->tend[is] = MIN(src->tbeg[is]+(wav->nt-1)*wav->dt,mod->tmod);
				wav->nsamp[is] = wav->nt;
			}
			nsamp += wav->nsamp[is];
			if (verbose>3) {
				vmess("Random xsrc=%f ysrc=%f zsrc=%f src_tbeg=%f src_tend=%f nsamp=%ld",src->x[is]*dx, src->y[is]*dy, src->z[is]*dz, src->tbeg[is], src->tend[is], wav->nsamp[is]);
			}
		}
		wav->nsamp[nsrc] = nsamp; /* put total number of samples in last position */
		wav->nst = nsamp; /* put total number of samples in nst part */

/* write time and length of source signals */
		if (verbose>3) {
			float *dum;
			dum = (float *)calloc(mod->nt, sizeof(float));
			for (is=0; is<nsrc; is++) {
				dum[(long)floor(src->tbeg[is]/mod->dt)] = src->tend[is]-src->tbeg[is];
			}
			FILE *fp;
			sprintf(tmpname,"srcTimeLengthN=%li.bin",mod->nt);
			fp = fopen(tmpname, "w+");
			fwrite(dum, sizeof(float), mod->nt, fp);
			fclose(fp);
			free(dum);
		}

	}
	else if ( (nxsrc != 0) || (src_txt != NULL) ) {
		/* source array is defined */
	    if (src_txt!=NULL) {
    	    /* Sources from a Text File */
            /* Open text file */
		    nsrctext=0;
            fp=fopen(src_txt,"r");
            assert(fp!=NULL);
            /* Get number of lines */
            while (!feof(fp)) if (fgetc(fp)=='\n') nsrctext++;
            fseek(fp,-1,SEEK_CUR);
            if (fgetc(fp)!='\n') nsrctext++; /* Checks if last line terminated by /n */
            if (verbose) vmess("Number of sources in src_txt file: %li",nsrctext);
            rewind(fp);
		    nsrc=nsrctext;
        }
        else {
		    nsrc=nxsrc;
        }
		/* Allocate arrays */
		src->x = (long *)malloc(nsrc*sizeof(long));
		src->y = (long *)malloc(nsrc*sizeof(long));
		src->z = (long *)malloc(nsrc*sizeof(long));
		src->tbeg = (float *)malloc(nsrc*sizeof(float));
		src->tend = (float *)malloc(nsrc*sizeof(float));
		xsrca = (float *)malloc(nsrc*sizeof(float));
		ysrca = (float *)malloc(nsrc*sizeof(float));
		zsrca = (float *)malloc(nsrc*sizeof(float));
	    if (src_txt!=NULL) {
			/* Read in source coordinates */
			for (i=0;i<nsrc;i++) {
				if (fscanf(fp,"%e %e %e\n",&xsrca[i],&ysrca[i],&zsrca[i])!=3) vmess("Source Text File: Can not parse coordinates on line %li.",i);
			}
			/* Close file */
			fclose(fp);
        }
		else {
			getparfloat("xsrca", xsrca);
			getparfloat("ysrca", ysrca);
			getparfloat("zsrca", zsrca);
        }
		/* Process coordinates */
		for (is=0; is<nsrc; is++) {
			src->x[is] = NINT((xsrca[is]-sub_x0)/dx);
			src->y[is] = NINT((ysrca[is]-sub_y0)/dy);
			src->z[is] = NINT((zsrca[is]-sub_z0)/dz);
			src->tbeg[is] = 0.0;
			src->tend[is] = (wav->nt-1)*wav->dt;
			if (verbose>3) fprintf(stderr,"Source Array: xsrc[%li]=%f ysrc=%f zsrc=%f\n", is, xsrca[is], ysrca[is], zsrca[is]);
		}

		src->random = 1;
		wav->nsamp = (size_t *)malloc((nsrc+1)*sizeof(size_t));
		if (wav->random) {
			if (!getparlong("src_multiwav",&src->multiwav)) src->multiwav=1;
			if (src->multiwav) wav->nx = nsrc;
			else wav->nx = 1;
			wav->nt = NINT(tlength/mod->dt)+1;
			nsamp=0;
			for (is=0; is<nsrc; is++) {
				rand = (float)drand48()*tlength;
				src->tend[is] = MIN(src->tbeg[is]+rand, mod->tmod);
				wav->nsamp[is] = (size_t)(NINT((src->tend[is]-src->tbeg[is])/mod->dt)+1);
				nsamp += wav->nsamp[is];
			}
			wav->nsamp[nsrc] = nsamp; /* put total number of samples in last position */
			wav->nst = nsamp; /* put total number of samples in nst part */
		}
		else {
			nsamp=0;
			for (is=0; is<nsrc; is++) {
				wav->nsamp[is] = wav->nt;
				nsamp += wav->nsamp[is];
			}
			wav->nsamp[nsrc] = nsamp; /* put total number of samples in last position */
			wav->nst = nsamp; /* put total number of samples in nst part */
		}
		free(xsrca);
		free(ysrca);
		free(zsrca);
	}
	else if (wav->nx > 1) {
		/* read file_src for number of sources and receiver positions */
		if (!getparlong("src_multiwav",&src->multiwav)) src->multiwav=1;
		float *gx, *sx, *gy, *sy, *gelev, *selev;
		gx = (float *)malloc(wav->nx*sizeof(float));
		sx = (float *)malloc(wav->nx*sizeof(float));
		gy = (float *)malloc(wav->nx*sizeof(float));
		sy = (float *)malloc(wav->nx*sizeof(float));
		gelev = (float *)malloc(wav->nx*sizeof(float));
		selev = (float *)malloc(wav->nx*sizeof(float));
		getWaveletHeaders3D(wav->file_src, wav->ns, wav->nx, gx, sx, gy, sy, gelev, selev, verbose);
		nsrc = wav->nx;
		src->x = (long *)malloc(nsrc*sizeof(long));
		src->y = (long *)malloc(nsrc*sizeof(long));
		src->z = (long *)malloc(nsrc*sizeof(long));
		src->tbeg = (float *)malloc(nsrc*sizeof(float));
		src->tend = (float *)malloc(nsrc*sizeof(float));
		wav->nsamp = (size_t *)malloc((nsrc+1)*sizeof(size_t));
		nsamp=0;
		for (is=0; is<nsrc; is++) {
			if (src->src_at_rcv>0){
				src->x[is] = NINT((gx[is]-sub_x0)/dx);
				src->y[is] = NINT((gy[is]-sub_y0)/dy);
				src->z[is] = NINT((gelev[is]-sub_z0)/dz);
				if (verbose>3) fprintf(stderr,"Source Array: xsrc[%li]=%f %li ysrc=%f %li zsrc=%f %li\n", is, gx[is], src->x[is], gy[is], src->y[is], gelev[is], src->z[is]);
			}
			else {
                src->x[is]=NINT((sx[is]-sub_x0)/dx);
                src->y[is]=NINT((sy[is]-sub_y0)/dy);
                src->z[is]=NINT((selev[is]-sub_z0)/dz);
				if (verbose>3) fprintf(stderr,"Source Array: xsrc[%li]=%f %li ysrc=%f %li zsrc=%f %li\n", is, sx[is], src->x[is], sy[is], src->y[is], selev[is], src->z[is]);
			}
			src->tbeg[is] = 0.0;
			src->tend[is] = (wav->nt-1)*wav->dt;
			wav->nsamp[is] = (size_t)(NINT((src->tend[is]-src->tbeg[is])/mod->dt)+1);
			nsamp += wav->nsamp[is];
		}
		wav->nsamp[nsrc] = nsamp; /* put total number of samples in last position */
		free(gx);
		free(sx);
		free(gy);
		free(sy);
		free(gelev);
		free(selev);
	}
	else {
		if (src->plane) { 
			if (!getparlong("npxsrc",&npxsrc)) npxsrc=1;
			if (!getparlong("npysrc",&npysrc)) npysrc=1;
		}
		else {
			npxsrc=1;
			npysrc=1;
		}

		if (npxsrc > nx) {
			vwarn("Number of sources used in plane wave (%li) is larger than ",npxsrc);
			vwarn("number of gridpoints in X (%li). Plane wave will be clipped to the edges of the model",nx);
			npxsrc = mod->nx;
		}
		if (npysrc > ny) {
			vwarn("Number of sources used in plane wave (%li) is larger than ",npysrc);
			vwarn("number of gridpoints in Y (%li). Plane wave will be clipped to the edges of the model",ny);
			npysrc = mod->ny;
		}
		nsrc = npxsrc*npysrc;

	/* for a source defined on mutliple gridpoint calculate p delay factor */

		src->x = (long *)malloc(nsrc*sizeof(long));
		src->y = (long *)malloc(nsrc*sizeof(long));
		src->z = (long *)malloc(nsrc*sizeof(long));
		src->tbeg = (float *)malloc(nsrc*sizeof(float));
		src->tend = (float *)malloc(nsrc*sizeof(float));
		grad2rad = 17.453292e-3;
		px = sin(src_anglex*grad2rad)/src_velox;
		py = sin(src_angley*grad2rad)/src_veloy;
		if (py < 0.0) {
			for (isy=0; isy<npysrc; isy++) {
				if (px < 0.0) {
					for (isx=0; isx<npxsrc; isx++) {
						src->tbeg[isy*npxsrc+isx] = fabsf((npysrc-isy-1)*dy*py) + fabsf((npxsrc-isx-1)*dx*px);
					}
				}
				else {
					for (isx=0; isx<npxsrc; isx++) {
						src->tbeg[isy*npxsrc+isx] = fabsf((npysrc-isy-1)*dy*py) + isx*dx*px;
					}
				}
			}
		}
		else {
			for (isy=0; isy<npysrc; isy++) {
				if (px < 0.0) {
					for (isx=0; isx<npxsrc; isx++) {
						src->tbeg[isy*npxsrc+isx] = isy*dy*py + fabsf((npxsrc-isx-1)*dx*px);
					}
				}
				else {
					for (isx=0; isx<npxsrc; isx++) {
						src->tbeg[isy*npxsrc+isx] = isy*dy*py + isx*dx*px;
					}
				}
			}
		}
		for (is=0; is<nsrc; is++) {
			src->tend[is] = src->tbeg[is] + (wav->nt-1)*wav->dt;
		}		
		isx0 = -1*floor((npxsrc-1)/2);
		isy0 = -1*floor((npysrc-1)/2);
		for (isy=0; isy<npysrc; isy++) {
			for (isx=0; isx<npxsrc; isx++) {
				src->x[isy*npxsrc+isx] = isx0 + isx;
				src->y[isy*npxsrc+isx] = isy0 + isy;
				src->z[isy*npxsrc+isx] = 0;
			}
		}
		
		if (wav->random) {
			if (!getparlong("src_multiwav",&src->multiwav)) src->multiwav=1;
			if (src->multiwav) wav->nx = nsrc;
			else wav->nx = 1;
			wav->nt = NINT(tlength/mod->dt)+1;
			wav->nsamp = (size_t *)malloc((wav->nx+1)*sizeof(size_t));
			nsamp=0;
			for (is=0; is<wav->nx; is++) {
				rand = (float)drand48()*tlength;
				src->tend[is] = MIN(src->tbeg[is]+rand, mod->tmod);
				wav->nsamp[is] = (size_t)(NINT((src->tend[is]-src->tbeg[is])/mod->dt)+1);
				nsamp += wav->nsamp[is];
			}
			wav->nsamp[nsrc] = nsamp; /* put total number of samples in last position */
			wav->nst = nsamp; /* put total number of samples in nst part */
		}
		else {
			wav->nsamp = (size_t *)malloc((nsrc+1)*sizeof(size_t));
			nsamp=0;
			for (is=0; is<nsrc; is++) {
				wav->nsamp[is] = wav->nt;
				nsamp += wav->nsamp[is];
			}
			wav->nsamp[nsrc] = nsamp; /* put total number of samples in last position */
			wav->nst = nsamp; /* put total number of samples in nst part */
		}
		src->nx = npxsrc;
		src->ny = npysrc;
	}

	if (src->multiwav) {
		if (wav->nx != nsrc) {
			vwarn("src_multiwav has been defined but number of traces in");
			vwarn("file_src = %li is not equal to nsrc = %li", wav->nx, nsrc);
			vwarn("last trace in file_src will be repeated.");
		}
		else {
			if (wav->file_src != NULL) vmess("Using all traces in file_src for a real shot");
		}
	}
	src->n=nsrc;


	if (verbose) {
		vmess("*******************************************");
		vmess("************* wavelet info ****************");
		vmess("*******************************************");
		vmess("wav_nt   = %6li   wav_nx      = %li", wav->ns, wav->nx);
		vmess("src_type = %6li   src_orient  = %li", src->type, src->orient);
		vmess("number of sources              = %li", shot->n);
		vmess("fmax     = %8.2f", fmax);
		fprintf(stderr,"    %s: Source type         : ",xargv[0]);
		switch ( src->type ) {
			case 1 : fprintf(stderr,"P "); break;
			case 2 : fprintf(stderr,"Txz "); break;
			case 3 : fprintf(stderr,"Tzz "); break;
			case 4 : fprintf(stderr,"Txx "); break;
			case 5 : fprintf(stderr,"S-potential"); break;
			case 6 : fprintf(stderr,"Fx "); break;
			case 7 : fprintf(stderr,"Fz "); break;
			case 8 : fprintf(stderr,"P-potential"); break;
			case 9 : fprintf(stderr,"Double-couple"); break;
			case 10 : fprintf(stderr,"Moment tensor"); break;
		}
		fprintf(stderr,"\n");
		if (src->type==9) {
			Mxx = -1.0*(sin(src->dip)*cos(src->rake)*sin(2.0*src->strike)+sin(src->dip*2.0)*sin(src->rake)*sin(src->strike)*sin(src->strike));
			Myy = sin(src->dip)*cos(src->rake)*sin(2.0*src->strike)-sin(src->dip*2.0)*sin(src->rake)*cos(src->strike)*cos(src->strike);
			Mzz = sin(src->dip*2.0)*sin(src->rake);
			Mxz = -1.0*(cos(src->dip)*cos(src->rake)*cos(src->strike)+cos(src->dip*2.0)*sin(src->rake)*sin(src->strike));
			Mxy = sin(src->dip)*cos(src->rake)*cos(src->strike*2.0)+0.5*(sin(src->dip*2.0)*sin(src->rake)*sin(src->strike*2.0));
			Myz = -1.0*(cos(src->dip)*cos(src->rake)*sin(src->strike)-cos(src->dip*2.0)*sin(src->rake)*cos(src->strike));
			vmess("Strike %.3f (%.2f degrees) Rake %.3f (%.2f degrees) Dip %.3f (%.2f degrees)",src->strike,180.0*src->strike/M_PI,src->rake,180.0*src->rake/M_PI,src->dip,180.0*src->dip/M_PI);
			vmess("Mxx %.2f Myy %.2f Mzz %.2f",Mxx,Myy,Mzz);
			vmess("Mxy %.2f Mxz %.2f Myz %.2f",Mxy,Mxz,Myz);
		}
		if (wav->random) vmess("Wavelet has a random signature with fmax=%.2f", wav->fmax);
		if (src->n>1) {
			vmess("*******************************************");
			vmess("*********** source array info *************");
			vmess("*******************************************");
			vmess("Areal source array is defined with %li sources (x=%li, y=%li).",nsrc,npxsrc,npysrc);
			vmess("Memory requirement for sources = %.2f MB.",sizeof(float)*(nsamp/(1024.0*1024.0)));
			if (src->plane) vmess("Computed px-value = %f. and py-value = %f",px,py);
		}
		if (src->random) {
		vmess("Sources are placed at random locations in domain: ");
		vmess(" x[%.2f : %.2f]  y[%.2f : %.2f]  z[%.2f : %.2f] ", xsrc1, xsrc2, ysrc1, ysrc2, zsrc1, zsrc2);
		vmess(" and all start in time window  t[%.3f : %.3f].", tsrc1, tsrc2);
		vmess(" after time %.3f the sources will not be active anymore.", tactive);
		}
	}

	/* define snapshots and beams */

	if (!getparfloat("tsnap1", &tsnap1)) tsnap1=0.1;
	if (!getparfloat("tsnap2", &tsnap2)) tsnap2=0.0;
	if (!getparfloat("dtsnap", &dtsnap)) dtsnap=0.1;
	if (!getparfloat("dxsnap", &dxsnap)) dxsnap=dx;
	if (!getparfloat("dysnap", &dysnap)) dysnap=dy;
	if (!getparfloat("dzsnap", &dzsnap)) dzsnap=dz;
	if (!getparfloat("xsnap1", &xsnap1)) xsnap1=sub_x0;
	if (!getparfloat("xsnap2", &xsnap2)) xsnap2=xmax;
	if (!getparfloat("ysnap1", &ysnap1)) ysnap1=sub_y0;
	if (!getparfloat("ysnap2", &ysnap2)) ysnap2=ymax;
	if (!getparfloat("zsnap1", &zsnap1)) zsnap1=sub_z0;
	if (!getparfloat("zsnap2", &zsnap2)) zsnap2=zmax;
	if (!getparlong("sna_vxvztime", &sna->vxvztime)) sna->vxvztime=0;
	if (!getparlong("beam", &sna->beam)) sna->beam=0;
	if (!getparlong("snapwithbnd", &sna->withbnd)) sna->withbnd=0;

	if (!getparlong("sna_type_vz", &sna->type.vz)) sna->type.vz=1;
	if (!getparlong("sna_type_vy", &sna->type.vy)) sna->type.vy=0;
	if (!getparlong("sna_type_vx", &sna->type.vx)) sna->type.vx=0;
	if (mod->ischeme>2) {
		sna->type.p=0;
		if (!getparlong("sna_type_txx", &sna->type.txx)) sna->type.txx=0;
		if (!getparlong("sna_type_tyy", &sna->type.tyy)) sna->type.tyy=0;
		if (!getparlong("sna_type_tzz", &sna->type.tzz)) sna->type.tzz=0;
		if (!getparlong("sna_type_txz", &sna->type.txz)) sna->type.txz=0;
		if (!getparlong("sna_type_txy", &sna->type.txy)) sna->type.txy=0;
		if (!getparlong("sna_type_tyz", &sna->type.tyz)) sna->type.tyz=0;
		if (!getparlong("sna_type_pp", &sna->type.pp)) sna->type.pp=0;
		if (!getparlong("sna_type_ss", &sna->type.ss)) sna->type.ss=0;
	}
	else {
		if (!getparlong("sna_type_p", &sna->type.p)) sna->type.p=1;
		sna->type.txx=0;
		sna->type.tyy=0;
		sna->type.tzz=0;
		sna->type.txz=0;
		sna->type.txy=0;
		sna->type.tyz=0;
		sna->type.pp=0;
		sna->type.ss=0;
	}

	sna->nsnap = 0;
	if (tsnap2 >= tsnap1) {
		sna_nrsna   = 1+NINT((tsnap2-tsnap1)/dtsnap);
		sna->skipdt = MAX(1,NINT(dtsnap/dt));
		sna->skipdx = MAX(1,NINT(dxsnap/dx));
		sna->skipdy = MAX(1,NINT(dysnap/dy));
		sna->skipdz = MAX(1,NINT(dzsnap/dz));
		sna->delay  = NINT(tsnap1/dt);
		isnapmax1   = (sna_nrsna-1)*sna->skipdt;
		isnapmax2   = floor( (mod->nt-(sna->delay + 1))/sna->skipdt) * sna->skipdt;
		isnapmax    = (sna->delay + 1) + MIN(isnapmax1,isnapmax2);
		sna->nsnap  = floor((isnapmax-(sna->delay + 1))/sna->skipdt) + 1;

		sna->x1=NINT((MIN(MAX(sub_x0,xsnap1),xmax)-sub_x0)/dx);
		sna->x2=NINT((MIN(MAX(sub_x0,xsnap2),xmax)-sub_x0)/dx);
		sna->y1=NINT((MIN(MAX(sub_y0,ysnap1),ymax)-sub_y0)/dy);
		sna->y2=NINT((MIN(MAX(sub_y0,ysnap2),ymax)-sub_y0)/dy);
		sna->z1=NINT((MIN(MAX(sub_z0,zsnap1),zmax)-sub_z0)/dz);
		sna->z2=NINT((MIN(MAX(sub_z0,zsnap2),zmax)-sub_z0)/dz);
		dxsnap=dx*sna->skipdx;
		dysnap=dy*sna->skipdy;
		dzsnap=dz*sna->skipdz;
		sna->nx=1+(((sna->x2-sna->x1))/sna->skipdx);
		sna->ny=1+(((sna->y2-sna->y1))/sna->skipdy);
		sna->nz=1+(((sna->z2-sna->z1))/sna->skipdz);

		if (verbose) {
			vmess("*******************************************");
			vmess("************* snap shot info **************");
			vmess("*******************************************");
			vmess("tsnap1  = %f tsnap2  = %f ", tsnap1, tsnap2);
			vmess("dtsnap  = %f Nsnap   = %li ", dtsnap, sna->nsnap);
			vmess("nzsnap  = %li nysnap  = %li nxsnap  = %li ", sna->nz, sna->ny, sna->nx);
			vmess("dzsnap  = %f dysnap  = %f dxsnap  = %f ", dzsnap, dysnap, dxsnap);
			vmess("zmin    = %f zmax    = %f ", sub_z0+dz*sna->z1, sub_z0+dz*sna->z2);
			vmess("ymin    = %f ymax    = %f ", sub_y0+dy*sna->y1, sub_y0+dy*sna->y2);
			vmess("xmin    = %f xmax    = %f ", sub_x0+dx*sna->x1, sub_x0+dx*sna->x2);
			if (sna->vxvztime) vmess("vx/vy/vz snapshot time  : t+0.5*dt ");
			else vmess("vx/vy/vz snapshot time  : t-0.5*dt ");
			fprintf(stderr,"    %s: Snapshot types        : ",xargv[0]);
			if (sna->type.vz) fprintf(stderr,"Vz ");
			if (sna->type.vy) fprintf(stderr,"Vy ");
			if (sna->type.vx) fprintf(stderr,"Vx ");
			if (sna->type.p) fprintf(stderr,"p ");
			if (mod->ischeme>2) {
				if (sna->type.txx) fprintf(stderr,"Txx ");
				if (sna->type.tyy) fprintf(stderr,"Tyy ");
				if (sna->type.tzz) fprintf(stderr,"Tzz ");
				if (sna->type.txz) fprintf(stderr,"Txz ");
				if (sna->type.txy) fprintf(stderr,"Txy ");
				if (sna->type.tyz) fprintf(stderr,"Tyz ");
				if (sna->type.pp) fprintf(stderr,"P ");
				if (sna->type.ss) fprintf(stderr,"S ");
			}
			fprintf(stderr,"\n");
		}
	}
	else {
		sna->nsnap = 0;
		if (verbose) vmess("*************** no snapshots **************");
	}
	if (sna->beam) {
		sna->skipdx = MAX(1,NINT(dxsnap/dx));
		sna->skipdy = MAX(1,NINT(dysnap/dy));
		sna->skipdz = MAX(1,NINT(dzsnap/dz));
		sna->x1=NINT((MIN(MAX(sub_x0,xsnap1),xmax)-sub_x0)/dx);
		sna->x2=NINT((MIN(MAX(sub_x0,xsnap2),xmax)-sub_x0)/dx);
		sna->y1=NINT((MIN(MAX(sub_y0,ysnap1),ymax)-sub_y0)/dy);
		sna->y2=NINT((MIN(MAX(sub_y0,ysnap2),ymax)-sub_y0)/dy);
		sna->z1=NINT((MIN(MAX(sub_z0,zsnap1),zmax)-sub_z0)/dz);
		sna->z2=NINT((MIN(MAX(sub_z0,zsnap2),zmax)-sub_z0)/dz);
		dxsnap=dx*sna->skipdx;
		dysnap=dy*sna->skipdy;
		dzsnap=dz*sna->skipdz;
		sna->nx=1+(((sna->x2-sna->x1))/sna->skipdx);
		sna->ny=1+(((sna->y2-sna->y1))/sna->skipdy);
		sna->nz=1+(((sna->z2-sna->z1))/sna->skipdz);

		if (verbose) {
			vmess("*******************************************");
			vmess("**************** beam info ****************");
			vmess("*******************************************");
			vmess("nzsnap  = %li nysnap  =%li nxsnap  = %li ", sna->nz, sna->ny, sna->nx);
			vmess("dzsnap  = %f dysnap  = %f dxsnap  = %f ", dzsnap, dysnap, dxsnap);
			vmess("zmin    = %f zmax    = %f ", sub_z0+dz*sna->z1, sub_z0+dz*sna->z2);
			vmess("ymin    = %f ymax    = %f ", sub_y0+dy*sna->y1, sub_y0+dy*sna->y2);
			vmess("xmin    = %f xmax    = %f ", sub_x0+dx*sna->x1, sub_x0+dx*sna->x2);
			fprintf(stderr,"    %s: Beam types            : ",xargv[0]);
			if (sna->type.vz) fprintf(stderr,"Vz ");
			if (sna->type.vy) fprintf(stderr,"Vy ");
			if (sna->type.vx) fprintf(stderr,"Vx ");
			if (sna->type.p) fprintf(stderr,"p ");
			if (mod->ischeme>2) {
				if (sna->type.txx) fprintf(stderr,"Txx ");
				if (sna->type.tyy) fprintf(stderr,"Tyy ");
				if (sna->type.tzz) fprintf(stderr,"Tzz ");
				if (sna->type.txz) fprintf(stderr,"Txz ");
				if (sna->type.txy) fprintf(stderr,"Txy ");
				if (sna->type.tyz) fprintf(stderr,"Tyz ");
				if (sna->type.pp) fprintf(stderr,"P ");
				if (sna->type.ss) fprintf(stderr,"S ");
			}
			fprintf(stderr,"\n");
		}
	}
	else {
		if (verbose) vmess("**************** no beams *****************");
	}

	/* define receivers */

	if (!getparlong("largeSUfile",&largeSUfile)) largeSUfile=0;
	if (!getparlong("sinkdepth",&rec->sinkdepth)) rec->sinkdepth=0;
	if (!getparlong("sinkdepth_src",&src->sinkdepth)) src->sinkdepth=0;
	if (!getparlong("sinkvel",&rec->sinkvel)) rec->sinkvel=0;
	if (!getparfloat("dtrcv",&dtrcv)) dtrcv=0.004;
	/* TODO check if dtrcv is integer multiple of dt */
	rec->skipdt=NINT(dtrcv/dt);
	dtrcv = mod->dt*rec->skipdt;
	if (!getparfloat("rec_delay",&rdelay)) rdelay=0.0;
	if (!getparlong("rec_ntsam",&rec->nt)) rec->nt=NINT((mod->tmod-rdelay)/dtrcv)+1;
	if (!getparlong("rec_int_p",&rec->int_p)) rec->int_p=0;
	if (!getparlong("rec_int_vx",&rec->int_vx)) rec->int_vx=0;
	if (!getparlong("rec_int_vy",&rec->int_vy)) rec->int_vy=0;
	if (!getparlong("rec_int_vz",&rec->int_vz)) rec->int_vz=0;
	if (!getparlong("max_nrec",&rec->max_nrec)) rec->max_nrec=15000;
	if (!getparlong("scale",&rec->scale)) rec->scale=0;
	if (!getparfloat("dxspread",&dxspread)) dxspread=0;
	if (!getparfloat("dyspread",&dyspread)) dyspread=0;
	if (!getparfloat("dzspread",&dzspread)) dzspread=0;
	rec->nt=MIN(rec->nt, NINT((mod->tmod-rdelay)/dtrcv)+1);

/* allocation of receiver arrays is done in recvPar */
	
	/* calculates the receiver coordinates */
	

	recvPar3D(rec, sub_x0, sub_y0, sub_z0, dx, dy, dz, nx, ny, nz);

	 

	if (!getparlong("rec_type_vz", &rec->type.vz)) rec->type.vz=1;
	if (!getparlong("rec_type_vy", &rec->type.vy)) rec->type.vy=0;
	if (!getparlong("rec_type_vx", &rec->type.vx)) rec->type.vx=0;
	if (!getparlong("rec_type_ud", &rec->type.ud)) rec->type.ud=0;
	if (mod->ischeme!=1 &&  rec->type.ud==1) {
		warn("Receiver decomposition only implemented for acoustis scheme (1)");
	}
	if (mod->ischeme>2) {
		rec->type.p=0;
		if (!getparlong("rec_type_txx", &rec->type.txx)) rec->type.txx=0;
		if (!getparlong("rec_type_tyy", &rec->type.tyy)) rec->type.tyy=0;
		if (!getparlong("rec_type_tzz", &rec->type.tzz)) rec->type.tzz=0;
		if (!getparlong("rec_type_txz", &rec->type.txz)) rec->type.txz=0;
		if (!getparlong("rec_type_txy", &rec->type.txy)) rec->type.txy=0;
		if (!getparlong("rec_type_tyz", &rec->type.tyz)) rec->type.tyz=0;
		if (!getparlong("rec_type_pp", &rec->type.pp)) rec->type.pp=0;
		if (!getparlong("rec_type_ss", &rec->type.ss)) rec->type.ss=0;
		/* for up and downgoing waves store all x-positons for Vz, Vx, Txz, Tzz into an array */
	}
	else {
		if (!getparlong("rec_type_p", &rec->type.p)) rec->type.p=1;
		rec->type.txx=0;
		rec->type.tyy=0;
		rec->type.tzz=0;
		rec->type.txz=0;
		rec->type.txy=0;
		rec->type.tyz=0;
		rec->type.pp=0;
		rec->type.ss=0;
		/* for up and downgoing waves store all x-positons for P and Vz into an array */
	}

	/* receivers are on a circle, use default interpolation to real (not on a grid-point) receiver position */
	if (getparfloat("rrcv", &rrcv)) { 
		if (!getparlong("rec_int_p",&rec->int_p)) rec->int_p=3;
		if (!getparlong("rec_int_vx",&rec->int_vx)) rec->int_vx=3;
		if (!getparlong("rec_int_vy",&rec->int_vy)) rec->int_vy=3;
		if (!getparlong("rec_int_vz",&rec->int_vz)) rec->int_vz=3;
	}
	if (rec->int_p==3) {
		rec->int_vx=3;
		rec->int_vy=3;
		rec->int_vz=3;
	}

	if (verbose) {
		if (rec->n) {
			dxrcv = rec->xr[MIN(1,rec->n-1)]-rec->xr[0];
			dyrcv = rec->yr[MIN(1,rec->n-1)]-rec->yr[0];
			dzrcv = rec->zr[MIN(1,rec->n-1)]-rec->zr[0];
			vmess("*******************************************");
			vmess("************* receiver info ***************");
			vmess("*******************************************");
			vmess("ntrcv   = %li nrcv    = %li ", rec->nt, rec->n);
			vmess("dtrcv   = %f              ", dtrcv );
			vmess("dzrcv   = %f dyrcv   = %f dxrcv   = %f ", dzrcv, dyrcv, dxrcv);
			vmess("time-delay = %f = points = %li",  rdelay, rec->delay);
			if ( fmax > (1.0/(2.0*dtrcv)) ) {
				vwarn("Receiver time sampling (dtrcv) is aliased.");
				vwarn("time sampling should be < %.6f", 1.0/(2.0*fmax) );
			}
			vmess("Receiver sampling can be => %.6e", 1.0/(2.0*fmax));
			vmess("Receiver array at coordinates: ");
			vmess("zmin    = %f zmax    = %f ", rec->zr[0]+sub_z0, rec->zr[rec->n-1]+sub_z0);
			vmess("ymin    = %f ymax    = %f ", rec->yr[0]+sub_y0, rec->yr[rec->n-1]+sub_y0);
			vmess("xmin    = %f xmax    = %f ", rec->xr[0]+sub_x0, rec->xr[rec->n-1]+sub_x0);
			vmess("which are gridpoints: ");
			vmess("izmin   = %li izmax   = %li ", rec->z[0], rec->z[rec->n-1]);
			vmess("iymin   = %li iymax   = %li ", rec->y[0], rec->y[rec->n-1]);
			vmess("ixmin   = %li ixmax   = %li ", rec->x[0], rec->x[rec->n-1]);
			if (rec->type.p) {
				fprintf(stderr,"    %s: Receiver interpolation for P: ",xargv[0]);
				if(rec->int_p==0) fprintf(stderr,"p->p\n");
				if(rec->int_p==1) fprintf(stderr,"p->vz\n");
				if(rec->int_p==2) fprintf(stderr,"p->vx\n");
				if(rec->int_p==3) fprintf(stderr,"interpolate to actual (no-grid) position of receiver\n");
			}
			if (rec->type.vx) {
				fprintf(stderr,"    %s: Receiver interpolation for Vx: ",xargv[0]);
				if(rec->int_vx==0) fprintf(stderr,"vx->vx\n");
				if(rec->int_vx==1) fprintf(stderr,"vx->vz\n");
				if(rec->int_vx==2) fprintf(stderr,"vx->txx/tzz\n");
				if(rec->int_vx==3) fprintf(stderr,"interpolate to real(no-grid) position of receiver\n");
			}
			if (rec->type.vy) {
				fprintf(stderr,"    %s: Receiver interpolation for Vx: ",xargv[0]);
				if(rec->int_vy==0) fprintf(stderr,"vy->vy\n");
				if(rec->int_vy==1) fprintf(stderr,"vy->vz\n");
				if(rec->int_vy==2) fprintf(stderr,"vy->tyy/tzz\n");
				if(rec->int_vy==3) fprintf(stderr,"interpolate to real(no-grid) position of receiver\n");
			}
			if (rec->type.vz) {
				fprintf(stderr,"    %s: Receiver interpolation for Vz: ",xargv[0]);
				if(rec->int_vz==0) fprintf(stderr,"vz->vz\n");
				if(rec->int_vz==1) fprintf(stderr,"vz->vx\n");
				if(rec->int_vz==2) fprintf(stderr,"vz->txx/tzz(P)\n");
				if(rec->int_vz==3) fprintf(stderr,"interpolate to real(no-grid) position of receiver\n");
			}
            fprintf(stderr,"    %s: Receiver types        : ",xargv[0]);
			if (rec->type.vz) fprintf(stderr,"Vz ");
			if (rec->type.vy) fprintf(stderr,"Vy ");
			if (rec->type.vx) fprintf(stderr,"Vx ");
			if (rec->type.p) fprintf(stderr,"p ");
    		if (rec->type.ud) fprintf(stderr,"P+ P- ");
			if (mod->ischeme>2) {
				if (rec->type.txx) fprintf(stderr,"Txx ");
				if (rec->type.tyy) fprintf(stderr,"Tyy ");
				if (rec->type.tzz) fprintf(stderr,"Tzz ");
				if (rec->type.txz) fprintf(stderr,"Txz ");
				if (rec->type.txy) fprintf(stderr,"Txy ");
				if (rec->type.tyz) fprintf(stderr,"Tyz ");
				if (rec->type.pp) fprintf(stderr,"P ");
				if (rec->type.ss) fprintf(stderr,"S ");
			}
			fprintf(stderr,"\n");
			if ( ( ((mod->nt*mod->dt-rec->delay)/rec->skipdt)+1) > 16384) {
				vwarn("Number of samples in receiver file is larger that SU can handle ");
				vwarn("use the paramater rec_ntsam=nt (with nt < 16384) to avoid this");
			}
			if ((mod->nt-rec->delay)*mod->dt > rec->nt*dtrcv) {
				long nfiles = ceil((mod->nt*mod->dt)/(rec->nt*dtrcv));
				long lastn = floor((mod->nt)%(rec->nt*rec->skipdt)/rec->skipdt)+1;
				vmess("Receiver recordings will be written to %li files",nfiles);
				vmess("Last file will contain %li samples",lastn);
				
			}
		}
		else {
		 	vmess("*************** no receivers **************");
		}
	}

	return 0;
}