Skip to content
Snippets Groups Projects
getRecTimes.c 11.77 KiB
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<assert.h>
#include"fdelmodc.h"
#include"par.h"

/**
*  Stores the wavefield at the receiver positions.
*
*  On a staggered grid the fields are all on different positions, 
*  to compensate for that the rec.int_vx and rec.int_vz options
*  can be set.
*
*   AUTHOR:
*           Jan Thorbecke (janth@xs4all.nl)
*           The Netherlands 
**/

int getRecTimes(modPar mod, recPar rec, bndPar bnd, int itime, int isam, float *vx, float *vz, float *tzz, float *txx, float *txz, float *l2m, float *rox, float *roz, float *rec_vx, float *rec_vz, float *rec_txx, float *rec_tzz, float *rec_txz, float *rec_p, float *rec_pp, float *rec_ss, float *rec_udp, float *rec_udvz, int verbose)
{
	int n1, ibndx, ibndz;
	int irec, ix, iz, ix2, iz2, ix1, iz1;
	float dvx, dvz, rdz, rdx, C00, C10, C01, C11;
	float *vz_t, c1, c2, lroz, field;

    ibndx = mod.ioPx;
    ibndz = mod.ioPz;
    if (bnd.lef==4 || bnd.lef==2) ibndx += bnd.ntap;
    if (bnd.top==4 || bnd.top==2) ibndz += bnd.ntap;
	n1    = mod.naz;
	c1 = 9.0/8.0;
	c2 = -1.0/24.0;

	if (!rec.n) return 0;

/***********************************************************************
* velocity or txz or potential registrations issues:
* rec_x and rec_z are related to actual txx/tzz/p positions.
* offsets from virtual boundaries must be taken into account.
*
* vx velocities have one sample less in x-direction
* vz velocities have one sample less in z-direction
* txz stresses have one sample less in z-direction and x-direction
*
* Note, in the acoustic scheme P is stored in the Tzz array.
***********************************************************************/

	for (irec=0; irec<rec.n; irec++) {
		iz = rec.z[irec]+ibndz;
		ix = rec.x[irec]+ibndx;
		iz1 = iz-1;
		ix1 = ix-1;
		iz2 = iz+1;
		ix2 = ix+1;
		/* interpolation to precise (not necessary on a grid point) position */
		if ( rec.int_p==3 ) {

			iz = (int)floorf(rec.zr[irec]/mod.dz)+ibndz;
			ix = (int)floorf(rec.xr[irec]/mod.dx)+ibndx;
			rdz = (rec.zr[irec] - (iz-ibndz)*mod.dz)/mod.dz;
			rdx = (rec.xr[irec] - (ix-ibndx)*mod.dx)/mod.dx;
			iz1 = iz-1;
			ix1 = ix-1;
			iz2 = iz+1;
			ix2 = ix+1;
			
			/*
			 // Interpolate according to Dirk Kraaijpool's scheme 
			 // Reference:  "Seismic ray fields and ray field maps : theory and algorithms" , 
			 // PhD thesis Utrecht University,Faculty of Geosciences, 2003) 
			 
			 C00 = tzz[ix*n1+iz]      + 0.5*((tzz[(ix+1)*n1+iz]   +tzz[(ix-1)*n1+iz]+ 
			 tzz[(ix  )*n1+iz+1] +tzz[(ix  )*n1+iz-1])/(2.0*mod.dx));
			 C10 = tzz[(ix+1)*n1+iz]  + 0.5*((tzz[(ix+2)*n1+iz]   +tzz[(ix  )*n1+iz]+
			 tzz[(ix+1)*n1+iz+1] +tzz[(ix+1)*n1+iz-1])/(2.0*mod.dz));
			 C01 = tzz[ix*n1+iz+1]    + 0.5*((tzz[(ix+1)*n1+iz+1] +tzz[(ix-1)*n1+iz+1]+
			 tzz[(ix)*n1+iz+2]   +tzz[(ix  )*n1+iz])/(2.0*mod.dx));
			 C11 = tzz[(ix+1)*n1+iz+1]+ 0.5*((tzz[(ix+2)*n1+iz+1] +tzz[(ix  )*n1+iz+1]+
			 tzz[(ix+1)*n1+iz+2] +tzz[(ix+1)*n1+iz])/(2.0*mod.dz));
			 */
			
			if (rec.type.p){
				/* bi-linear interpolation */
				C00 = tzz[ix*n1+iz];
				C10 = tzz[(ix+1)*n1+iz];
				C01 = tzz[ix*n1+iz+1];
				C11 = tzz[(ix+1)*n1+iz+1];
				rec_p[irec*rec.nt+isam] = C00*(1.0-rdx)*(1.0-rdz) + C10*rdx*(1.0-rdz) +
										  C01*(1.0-rdx)*rdz       + C11*rdx*rdz;
			}
			if (rec.type.txx) {
				C00 = txx[ix*n1+iz];
				C10 = txx[(ix+1)*n1+iz];
				C01 = txx[ix*n1+iz+1];
				C11 = txx[(ix+1)*n1+iz+1];
				rec_txx[irec*rec.nt+isam] = C00*(1.0-rdx)*(1.0-rdz) + C10*rdx*(1.0-rdz) +
											C01*(1.0-rdx)*rdz       + C11*rdx*rdz;
			}
			if (rec.type.tzz) {
				C00 = tzz[ix*n1+iz];
				C10 = tzz[(ix+1)*n1+iz];
				C01 = tzz[ix*n1+iz+1];
				C11 = tzz[(ix+1)*n1+iz+1];
				rec_tzz[irec*rec.nt+isam] = C00*(1.0-rdx)*(1.0-rdz) + C10*rdx*(1.0-rdz) +
											C01*(1.0-rdx)*rdz       + C11*rdx*rdz;
			}
			if (rec.type.txz) {
				C00 = txz[ix2*n1+iz2];
				C10 = txz[(ix2+1)*n1+iz2];
				C01 = txz[ix2*n1+iz2+1];
				C11 = txz[(ix2+1)*n1+iz2+1];
				rec_txz[irec*rec.nt+isam] = C00*(1.0-rdx)*(1.0-rdz) + C10*rdx*(1.0-rdz) +
											C01*(1.0-rdx)*rdz       + C11*rdx*rdz;
			}
			if (rec.type.pp) {
				C00 = (vx[ix2*n1+iz]-vx[ix*n1+iz] +
					   vz[ix*n1+iz2]-vz[ix*n1+iz])/mod.dx;
				C10 = (vx[(ix2+1)*n1+iz]-vx[(ix+1)*n1+iz] +
					   vz[(ix+1)*n1+iz2]-vz[(ix+1)*n1+iz])/mod.dx;
				C01 = (vx[ix2*n1+iz+1]-vx[ix*n1+iz+1] +
					   vz[ix*n1+iz2+1]-vz[ix*n1+iz+1])/mod.dx;
				C11 = (vx[(ix2+1)*n1+iz+1]-vx[(ix+1)*n1+iz+1] +
					   vz[(ix+1)*n1+iz2+1]-vz[(ix+1)*n1+iz+1])/mod.dx;
				rec_pp[irec*rec.nt+isam] = C00*(1.0-rdx)*(1.0-rdz) + C10*rdx*(1.0-rdz) +
										   C01*(1.0-rdx)*rdz       + C11*rdx*rdz;
			}
			if (rec.type.ss) {
				C00 = (vx[ix2*n1+iz2]-vx[ix2*n1+iz] -
					   (vz[ix2*n1+iz2]-vz[ix*n1+iz2]))/mod.dx;
				C10 = (vx[(ix2+1)*n1+iz2]-vx[(ix2+1)*n1+iz] -
						(vz[(ix2+1)*n1+iz2]-vz[(ix+1)*n1+iz2]))/mod.dx;
				C01 = (vx[ix2*n1+iz2+1]-vx[ix2*n1+iz+1] -
						(vz[ix2*n1+iz2+1]-vz[ix*n1+iz2+1]))/mod.dx;;
				C11 = (vx[(ix2+1)*n1+iz2+1]-vx[(ix2+1)*n1+iz+1] -
						(vz[(ix2+1)*n1+iz2+1]-vz[(ix+1)*n1+iz2+1]))/mod.dx;
				rec_ss[irec*rec.nt+isam] = C00*(1.0-rdx)*(1.0-rdz) + C10*rdx*(1.0-rdz) +
										   C01*(1.0-rdx)*rdz       + C11*rdx*rdz;
			}
			if (rec.type.vz) {
				C00 = vz[ix*n1+iz2];
				C10 = vz[(ix+1)*n1+iz2];
				C01 = vz[ix*n1+iz2+1];
				C11 = vz[(ix+1)*n1+iz2+1];
				rec_vz[irec*rec.nt+isam] = C00*(1.0-rdx)*(1.0-rdz) + C10*rdx*(1.0-rdz) +
										   C01*(1.0-rdx)*rdz       + C11*rdx*rdz;
			}
			if (rec.type.vx) {
				C00 = vx[ix2*n1+iz];
				C10 = vx[(ix2+1)*n1+iz];
				C01 = vx[ix2*n1+iz+1];
				C11 = vx[(ix2+1)*n1+iz+1];
				rec_vx[irec*rec.nt+isam] = C00*(1.0-rdx)*(1.0-rdz) + C10*rdx*(1.0-rdz) +
										   C01*(1.0-rdx)*rdz       + C11*rdx*rdz;
			}
			
		}
		else { /* read values directly from the grid points */
			if (verbose>=4 && isam==0) {
				vmess("Receiver %d read at gridpoint ix=%d iz=%d",irec, ix, iz);
			}
			/* interpolation of receivers to same time step is only done for acoustic scheme */
			if (rec.type.p) {
				if (rec.int_p == 1) {
					if (mod.ischeme == 1) { /* interpolate Tzz times -1/2 Dt backward to Vz times */
                        dvx = c1*(vx[(ix+1)*n1+iz] - vx[ix*n1+iz]) +
                              c2*(vx[(ix+2)*n1+iz] - vx[(ix-1)*n1+iz]);
                        dvz = c1*(vz[ix*n1+iz+1]   - vz[ix*n1+iz]) +
                              c2*(vz[ix*n1+iz+2]   - vz[ix*n1+iz-1]);
                        field = tzz[ix*n1+iz] + 0.5*l2m[ix*n1+iz]*(dvx+dvz);
                        dvx = c1*(vx[(ix+1)*n1+iz1] - vx[ix*n1+iz1]) +
                              c2*(vx[(ix+2)*n1+iz1] - vx[(ix-1)*n1+iz1]);
                        dvz = c1*(vz[ix*n1+iz1+1]   - vz[ix*n1+iz1]) +
                              c2*(vz[ix*n1+iz1+2]   - vz[ix*n1+iz1-1]);
                        field += tzz[ix*n1+iz1] + 0.5*l2m[ix*n1+iz1]*(dvx+dvz);
						rec_p[irec*rec.nt+isam] = 0.5*field;
					}
					else {
						rec_p[irec*rec.nt+isam] = 0.5*(tzz[ix*n1+iz1]+tzz[ix*n1+iz]);
					}
				}
				else if (rec.int_p == 2) {
					if (mod.ischeme == 1) { /* interpolate Tzz times -1/2 Dt backward to Vx times */
                        dvx = c1*(vx[(ix+1)*n1+iz] - vx[ix*n1+iz]) +
                              c2*(vx[(ix+2)*n1+iz] - vx[(ix-1)*n1+iz]);
                        dvz = c1*(vz[ix*n1+iz+1]   - vz[ix*n1+iz]) +
                              c2*(vz[ix*n1+iz+2]   - vz[ix*n1+iz-1]);
                        field = tzz[ix*n1+iz] + 0.5*l2m[ix*n1+iz]*(dvx+dvz);
                        dvx = c1*(vx[(ix1+1)*n1+iz] - vx[ix1*n1+iz]) +
                              c2*(vx[(ix+2)*n1+iz] - vx[(ix1-1)*n1+iz]);
                        dvz = c1*(vz[ix1*n1+iz+1]   - vz[ix1*n1+iz]) +
                              c2*(vz[ix1*n1+iz+2]   - vz[ix1*n1+iz-1]);
                        field += tzz[ix1*n1+iz] + 0.5*l2m[ix1*n1+iz]*(dvx+dvz);
						rec_p[irec*rec.nt+isam] = 0.5*field;
					}
					else {
						rec_p[irec*rec.nt+isam] = 0.5*(tzz[ix1*n1+iz]+tzz[ix*n1+iz]);
					}
				}
				else {
					rec_p[irec*rec.nt+isam] = tzz[ix*n1+iz];
				}
			}
			if (rec.type.txx) rec_txx[irec*rec.nt+isam] = txx[ix*n1+iz];
			if (rec.type.tzz) rec_tzz[irec*rec.nt+isam] = tzz[ix*n1+iz];
			if (rec.type.txz) { /* time interpolation to be done */
				if (rec.int_vz == 2 || rec.int_vx == 2) {
					rec_txz[irec*rec.nt+isam] = 0.25*(
							txz[ix*n1+iz2]+txz[ix2*n1+iz2]+
							txz[ix*n1+iz]+txz[ix2*n1+iz]);
				}
				else {
					rec_txz[irec*rec.nt+isam] = txz[ix2*n1+iz2];
				}
			}
			if (rec.type.pp) {
				rec_pp[irec*rec.nt+isam] = (vx[ix2*n1+iz]-vx[ix*n1+iz] +
											vz[ix*n1+iz2]-vz[ix*n1+iz])/mod.dx;
			}
			if (rec.type.ss) {
				rec_ss[irec*rec.nt+isam] = (vx[ix2*n1+iz2]-vx[ix2*n1+iz] -
										   (vz[ix2*n1+iz2]-vz[ix*n1+iz2]))/mod.dx;
			}
			if (rec.type.vz) {
/* interpolate vz to vx position to the right and above of vz */
				if (rec.int_vz == 1) {
					rec_vz[irec*rec.nt+isam] = 0.25*(
							vz[ix*n1+iz2]+vz[ix1*n1+iz2]+
							vz[ix*n1+iz] +vz[ix1*n1+iz]);
				}
/* interpolate vz to Txx/Tzz position by taking the mean of 2 values */
				else if (rec.int_vz == 2) {
					if (mod.ischeme == 1) { /* interpolate Vz times +1/2 Dt forward to P times */
                        field = vz[ix*n1+iz] - 0.5*roz[ix*n1+iz]*(
                        	c1*(tzz[ix*n1+iz]   - tzz[ix*n1+iz-1]) +
                        	c2*(tzz[ix*n1+iz+1] - tzz[ix*n1+iz-2]));
                        field += vz[ix*n1+iz2] - 0.5*roz[ix*n1+iz2]*(
                        	c1*(tzz[ix*n1+iz2]   - tzz[ix*n1+iz2-1]) +
                        	c2*(tzz[ix*n1+iz2+1] - tzz[ix*n1+iz2-2]));
						rec_vz[irec*rec.nt+isam] = 0.5*field;
					}
					else {
						rec_vz[irec*rec.nt+isam] = 0.5*(vz[ix*n1+iz2]+vz[ix*n1+iz]);
					}
				}
				else {
					rec_vz[irec*rec.nt+isam] = vz[ix*n1+iz2];
					//rec_vz[irec*rec.nt+isam] = vz[ix*n1+iz];
					//fprintf(stderr,"isam=%d vz[%d]=%e vz[%d]=%e vz[%d]=%e \n",isam, iz-1,vz[ix*n1+iz-1],iz,vz[ix*n1+iz], iz+1, vz[ix*n1+iz+1]);
				}
			}
			if (rec.type.vx) {
/* interpolate vx to vz position to the left and below of vx */
				if (rec.int_vx == 1) {
					rec_vx[irec*rec.nt+isam] = 0.25*(
							vx[ix2*n1+iz]+vx[ix2*n1+iz1]+
							vx[ix*n1+iz]+vx[ix*n1+iz1]);
				}
/* interpolate vx to Txx/Tzz position by taking the mean of 2 values */
				else if (rec.int_vx == 2) {
					if (mod.ischeme == 1) { /* interpolate Vx times +1/2 Dt forward to P times */
            			field = vx[ix*n1+iz] - 0.5*rox[ix*n1+iz]*(
                			c1*(tzz[ix*n1+iz]     - tzz[(ix-1)*n1+iz]) +
                			c2*(tzz[(ix+1)*n1+iz] - tzz[(ix-2)*n1+iz]));
            			field += vx[ix2*n1+iz] - 0.5*rox[ix2*n1+iz]*(
                			c1*(tzz[ix2*n1+iz]     - tzz[(ix2-1)*n1+iz]) +
                			c2*(tzz[(ix2+1)*n1+iz] - tzz[(ix2-2)*n1+iz]));
						rec_vx[irec*rec.nt+isam] = 0.5*field;
					}
					else {
						rec_vx[irec*rec.nt+isam] = 0.5*(vx[ix2*n1+iz]+vx[ix*n1+iz]);
					}
				}
				else {
					rec_vx[irec*rec.nt+isam] = vx[ix2*n1+iz];
				}
			}
		}

	} /* end of irec loop */

	/* store all x-values on z-level for P Vz for up-down decomposition */
	if (rec.type.ud) {
		iz = rec.z[0]+ibndz;
		iz2 = iz+1;
		vz_t = (float *)calloc(2*mod.nax,sizeof(float));
		/* P and Vz are staggered in time and need to correct for this */
		/* -1- compute Vz at next time step and average with current time step */
		lroz = mod.dt/(mod.dx*rec.rho);
    	for (ix=mod.ioZx; ix<mod.ieZx; ix++) {
           	vz_t[ix] = vz[ix*n1+iz] - lroz*(
                       	c1*(tzz[ix*n1+iz]   - tzz[ix*n1+iz-1]) +
                       	c2*(tzz[ix*n1+iz+1] - tzz[ix*n1+iz-2]));
           	vz_t[mod.nax+ix] = vz[ix*n1+iz2] - lroz*(
                       	c1*(tzz[ix*n1+iz2]   - tzz[ix*n1+iz2-1]) +
                       	c2*(tzz[ix*n1+iz2+1] - tzz[ix*n1+iz2-2]));
       	}
		for (ix=0; ix<mod.nax; ix++) {
			/* -2- compute average in time and depth to get Vz at same depth and time as P */
			rec_udvz[ix*rec.nt+isam] = 0.25*(vz[ix*n1+iz2]+vz[ix*n1+iz]+vz_t[mod.nax+ix]+vz_t[ix]);
			rec_udp[ix*rec.nt+isam]  = tzz[ix*n1+iz];
		}
		free(vz_t);
	}

	return 0;
}