Skip to content
Snippets Groups Projects
PlaneWaveDecomposition.c 11.83 KiB
#include<stdlib.h>
#include<stdarg.h>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<complex.h>
#include<fftw3.h>
#include"fdacrtmc.h"
#include"par.h"
/*

	NOTE: If signals are even in length we mute the highest
	frequency/wavenumber component.

*/

// TODO Get rid of deubg in wisdom files

int PlaneWaveDecompositionUpDownRTMImagingCondition(migPar *mig, fftPlansPar *fftPlans,int verbose){
	fftw_complex *Forw, *Back, *Mute;
	bool evenT=false, evenZ=false; //Booleans if nt & nz are even (true) or not (false)
	double *forw, *back;
	float *tap;
	size_t it, it1, ix, iz, iz1, ntz, nw, nwp, nwn, nkz, nkzp, nwkz, perc;
//float *im1, *im2, *im3, *im4;
	va_list args; //Needed to initialize progress
	/* Compute Constants */
	ntz=mig->nt*mig->nz;
	nwp=mig->nt/2;     //Number of positive frequencies
	nw=nwp+1;          
	nwn=mig->nt-nw;    //Number of negative frequencies
	nkzp=mig->nz/2;    //Number of positive wavenumbers
	nkz=nkzp+1;
	nwkz=nkz*mig->nt;
	if(!mig->nt%2) evenT=true; // Note we mute the highest frequency component
	if(!mig->nz%2) evenZ=true; // Note we mute the highest wavenumber component
//im1=(float*)fftw_malloc(mig->sizem*sizeof(float));
//im2=(float*)fftw_malloc(mig->sizem*sizeof(float));
//im3=(float*)fftw_malloc(mig->sizem*sizeof(float));
//im4=(float*)fftw_malloc(mig->sizem*sizeof(float));
	/* Allocate Arrays */
	forw=(double*)fftw_malloc(ntz*sizeof(double));                 //Forward Propagated Wavefield
	Forw=(fftw_complex*)fftw_malloc(nwkz*sizeof(fftw_complex));    // " in the Wavenumber Frequency Domain
	Mute=(fftw_complex*)fftw_malloc(nwkz*sizeof(fftw_complex));    //Muted Wavefields
	back=(double*)fftw_malloc(ntz*sizeof(double));                 //Backward Propagated Wavefield
	Back=(fftw_complex*)fftw_malloc(nwkz*sizeof(fftw_complex));    // " in the Wavenumber Frequency Domain

	/**************************/
	/* Construct Sine^2 Taper */
	/**************************/
	// Format of tap:
	// |--------------| Note: C memory alignment !
	// |              |
	// | Corner Taper |
	// |    Matrix    |
	// |              |
	// |--------------|
	// |     Taper    |
	// |--------------|
	//
	// tap=[  0                      0                     ...                     0                     ]
	//     [  0  sin^2(PI*ix/(nx+1))*sin^2(PI*iz/(ntap+1)) ... sin^2(PI*nx/(nx+1))*sin^2(PI*iz/(ntap+1)) ]
	//     [ ...                    ...                    ...                    ...                    ]
	//     [  0  sin^2(PI*ix/(nx+1))*sin^2(PI*nz/(ntap+1)) ... sin^2(PI*nx/(nx+1))*sin^2(PI*nz/(ntap+1)) ]
	//     [  0              sin^2(PI*ix/(nx+1))           ...             sin^2(PI*nx/(nx+1))           ]
	// Note: Zeros are not included in the taper
mig->tap=50;
	if(mig->tap){
		/* Construct Taper */
		tap=malloc((float)(mig->tap-1)*mig->tap*sizeof(float));
		// Compute Simple Taper
		for(ix=0;ix<mig->tap-1;ix++){
			tap[(mig->tap-1)*(mig->tap-1)+ix]=sin(1.5707963267948966192313216916398*(((float)(ix+1))/((float)(mig->tap+1)))); //Value outside boundary is 1
			tap[(mig->tap-1)*(mig->tap-1)+ix]*=tap[(mig->tap-1)*(mig->tap-1)+ix];
		}
		// Compute Corners
		for(ix=0;ix<mig->tap-1;ix++) for(iz=0;iz<mig->tap-1;iz++) tap[ix*(mig->tap-1)+iz]=tap[(mig->tap-1)*(mig->tap-1)+ix]*tap[(mig->tap-1)*(mig->tap-1)+iz];
	}

	/************************************/
	/* Loop Over Horizontal Coordinates */
	/************************************/
	if(verbose){perc=mig->nx/100;if(!perc)perc=1;fprintf(stderr,"    %s: Progress:   0%%",xargv[0]);}
	for(ix=0;ix<mig->nx;ix++){
		/***************************************/
		/* Forward Propagated Source Wavefield */
		/***************************************/
		/* Copy Array to Double */
		if(mig->tap){ //Additionaly Taper Wavefield
			// Source Wavefield
			memset(forw,0,mig->nz*sizeof(double)); //Zero Boundary
			for(it=1;it<mig->tap;it++){ // Boundary 1
				forw[it*mig->nz]=0; //Zero Boundary
				for(iz=1;iz<mig->tap;iz++) forw[it*mig->nz+iz]=(double)(mig->wav[it].tzz[ix*mig->nz+iz]*tap[(it-1)*(mig->tap-1)+iz-1]); //Corner 1
				for(iz=mig->tap;iz<mig->nz-mig->tap;iz++) forw[it*mig->nz+iz]=(double)(mig->wav[it].tzz[ix*mig->nz+iz]*tap[(mig->tap-1)*(mig->tap-1)+it-1]); //Boundary 1
				for(iz=mig->nz-mig->tap,iz1=mig->tap-2;iz<mig->nz-1;iz++,iz1--) forw[it*mig->nz+iz]=(double)(mig->wav[it].tzz[ix*mig->nz+iz]*tap[(it-1)*(mig->tap-1)+iz1]); //Corner 2
				forw[(it+1)*mig->nz-1]=0; //Zero Boundary
			}
			for(it=mig->tap;it<mig->nt-mig->tap;it++){
				forw[it*mig->nz]=0; //Zero Boundary
				for(iz=1;iz<mig->tap;iz++) forw[it*mig->nz+iz]=(double)(mig->wav[it].tzz[ix*mig->nz+iz]*tap[(mig->tap-1)*(mig->tap-1)+iz-1]); //Boundary 2
				for(iz=mig->tap;iz<mig->nz-mig->tap;iz++) forw[it*mig->nz+iz]=(double)mig->wav[it].tzz[ix*mig->nz+iz];
				for(iz=mig->nz-mig->tap,iz1=mig->tap-2;iz<mig->nz-1;iz++,iz1--) forw[it*mig->nz+iz]=(double)(mig->wav[it].tzz[ix*mig->nz+iz]*tap[(mig->tap-1)*(mig->tap-1)+iz1]); //Boundary 3
				forw[(it+1)*mig->nz-1]=0; //Zero Boundary
			}
			for(it=mig->nt-mig->tap,it1=mig->tap-2;it<mig->nt-1;it++,it1--){ //Boundary 4
				forw[it*mig->nz]=0; //Zero Boundary
				for(iz=1;iz<mig->tap;iz++) forw[it*mig->nz+iz]=(double)(mig->wav[it].tzz[ix*mig->nz+iz]*tap[it1*(mig->tap-1)+iz-1]); //Corner 3
				for(iz=mig->tap;iz<mig->nz-mig->tap;iz++) forw[it*mig->nz+iz]=(double)(mig->wav[it].tzz[ix*mig->nz+iz]*tap[(mig->tap-1)*(mig->tap-1)+it1]); //Boundary 4
				for(iz=mig->nz-mig->tap,iz1=mig->tap-2;iz<mig->nz-1;iz++,iz1--) forw[it*mig->nz+iz]=(double)(mig->wav[it].tzz[ix*mig->nz+iz]*tap[it1*(mig->tap-1)+iz1]); //Corner 4
				forw[(it+1)*mig->nz-1]=0; //Zero Boundary
			}
			memset(&forw[(mig->nt-1)*mig->nz],0,mig->nz*sizeof(double)); //Zero Boundary
		}else for(it=0;it<mig->nt;it++) for(iz=0;iz<mig->nz;iz++) forw[it*mig->nz+iz]=(double)mig->wav[it].tzz[ix*mig->nz+iz];

		/* Compute Forward Fourier Transform */
		fftw_execute_dft_r2c(fftPlans->fft_2d_r2c_TZ,forw,Forw);
		for(iz=0;iz<nkz;iz++)Forw[iz]/=2.;         //Zero-Frequency Component 1
		for(it=1;it<mig->nt;it++)Forw[it*nkz]/=2.; //Zero-Frequency Component 2
		if(evenZ) for(it=0;it<mig->nt;it++) Forw[it*nkz-1]=0;

		/*********************************/
		/* Backward Propagated Wavefield */
		/*********************************/
		/* Copy Array to Double */
		if(mig->tap){ //Additionaly Taper Wavefield
			// Source Wavefield
			memset(back,0,mig->nz*sizeof(double)); //Zero Boundary
			for(it=1;it<mig->tap;it++){ // Boundary 1
				back[it*mig->nz]=0; //Zero Boundary
				for(iz=1;iz<mig->tap;iz++) back[it*mig->nz+iz]=(double)(mig->wav[2*mig->nt-1-it].tzz[ix*mig->nz+iz]*tap[(it-1)*(mig->tap-1)+iz-1]); //Corner 1
				for(iz=mig->tap;iz<mig->nz-mig->tap;iz++) back[it*mig->nz+iz]=(double)(mig->wav[2*mig->nt-1-it].tzz[ix*mig->nz+iz]*tap[(mig->tap-1)*(mig->tap-1)+it-1]); //Boundary 1
				for(iz=mig->nz-mig->tap,iz1=mig->tap-2;iz<mig->nz-1;iz++,iz1--) back[it*mig->nz+iz]=(double)(mig->wav[2*mig->nt-1-it].tzz[ix*mig->nz+iz]*tap[(it-1)*(mig->tap-1)+iz1]); //Corner 2
				back[(it+1)*mig->nz-1]=0; //Zero Boundary
			}
			for(it=mig->tap;it<mig->nt-mig->tap;it++){
				back[it*mig->nz]=0; //Zero Boundary
				for(iz=1;iz<mig->tap;iz++) back[it*mig->nz+iz]=(double)(mig->wav[2*mig->nt-1-it].tzz[ix*mig->nz+iz]*tap[(mig->tap-1)*(mig->tap-1)+iz-1]); //Boundary 2
				for(iz=mig->tap;iz<mig->nz-mig->tap;iz++) back[it*mig->nz+iz]=(double)mig->wav[2*mig->nt-1-it].tzz[ix*mig->nz+iz];
				for(iz=mig->nz-mig->tap,iz1=mig->tap-2;iz<mig->nz-1;iz++,iz1--) back[it*mig->nz+iz]=(double)(mig->wav[2*mig->nt-1-it].tzz[ix*mig->nz+iz]*tap[(mig->tap-1)*(mig->tap-1)+iz1]); //Boundary 3
				back[(it+1)*mig->nz-1]=0; //Zero Boundary
			}
			for(it=mig->nt-mig->tap,it1=mig->tap-2;it<mig->nt-1;it++,it1--){ //Boundary 4
				back[it*mig->nz]=0; //Zero Boundary
				for(iz=1;iz<mig->tap;iz++) back[it*mig->nz+iz]=(double)(mig->wav[2*mig->nt-1-it].tzz[ix*mig->nz+iz]*tap[it1*(mig->tap-1)+iz-1]); //Corner 3
				for(iz=mig->tap;iz<mig->nz-mig->tap;iz++) back[it*mig->nz+iz]=(double)(mig->wav[2*mig->nt-1-it].tzz[ix*mig->nz+iz]*tap[(mig->tap-1)*(mig->tap-1)+it1]); //Boundary 4
				for(iz=mig->nz-mig->tap,iz1=mig->tap-2;iz<mig->nz-1;iz++,iz1--) back[it*mig->nz+iz]=(double)(mig->wav[2*mig->nt-1-it].tzz[ix*mig->nz+iz]*tap[it1*(mig->tap-1)+iz1]); //Corner 4
				back[(it+1)*mig->nz-1]=0; //Zero Boundary
			}
			memset(&back[(mig->nt-1)*mig->nz],0,mig->nz*sizeof(double)); //Zero Boundary
		}else for(it=0,iz1=2*mig->nt-1;it<mig->nt;it++,iz1--) for(iz=0;iz<mig->nz;iz++) back[it*mig->nz+iz]=(double)mig->wav[iz1].tzz[ix*mig->nz+iz];

		/* Compute Forward Fourier Transform */
		fftw_execute_dft_r2c(fftPlans->fft_2d_r2c_TZ,back,Back);
		for(iz=0;iz<nkz;iz++)Back[iz]/=2.;         //Zero-Frequency Component 1
		for(it=1;it<mig->nt;it++)Back[it*nkz]/=2.; //Zero-Frequency Component 2
		if(evenZ) for(it=0;it<mig->nt;it++) Back[it*nkz-1]=0;

		/***************************/
		/* Apply Imaging Condition */
		/***************************/
		/* 1.)Down-Up Imaging */
		// Mute Up-Going Source Wavefield
		memcpy(Mute,Forw,nkz*sizeof(fftw_complex));                        //Zero-Wavenumber Component
		memset(&Mute[nkz],0,nkz*nwp*sizeof(fftw_complex));                 //Mute + Quadrant
		for(it=1;it<mig->nt;it++)Mute[it*nkz]=Forw[it*nkz];                //Zero-Frequency Component
		memcpy(&Mute[nkz*nw],&Forw[nkz*nw],nkz*nwn*sizeof(fftw_complex));  //Copy - Quadrant
		fftw_execute_dft_c2r(fftPlans->ifft_2d_c2r_WKz,Mute,forw);         //Transform Back
//for(iz=0;iz<mig->nz;iz++) im1[ix*mig->nz+iz]=(float)(forw[200*mig->nz+iz]/((double)ntz));
//for(iz=0;iz<mig->nz;iz++) im2[ix*mig->nz+iz]=(float)(forw[400*mig->nz+iz]/((double)ntz));
//for(iz=0;iz<mig->nz;iz++) im3[ix*mig->nz+iz]=(float)(forw[600*mig->nz+iz]/((double)ntz));
//for(iz=0;iz<mig->nz;iz++) im4[ix*mig->nz+iz]=(float)(forw[800*mig->nz+iz]/((double)ntz));
		// Mute Up-Going Receiver Wavefield - for Up-Down Imaging
		memcpy(Mute,Back,nkz*sizeof(fftw_complex));                        //Zero-Frequency Component
		memset(&Mute[nkz],0,nkz*nwp*sizeof(fftw_complex));                 //Mute + Quadrant
		for(it=1;it<mig->nt;it++)Mute[it*nkz]=Back[it*nkz];                //Zero-Frequency Component
		memcpy(&Mute[nkz*nw],&Back[nkz*nw],nkz*nwn*sizeof(fftw_complex));  //Copy - Quadrant

		// Mute Down-Going Receiver Wavefield
		if(evenT) memset(&Back[nkzp*nwp],0,nkz*nw*sizeof(fftw_complex));   //Mute - Quadrant
		else memset(&Back[nkz*nw],0,nkz*nwp*sizeof(fftw_complex));
		fftw_execute_dft_c2r(fftPlans->ifft_2d_c2r_WKz,Back,back);         //Transform Back

		// Apply Zero-Lag Imaging Condition
		for(iz=0;iz<mig->nz;iz++) mig->image[ix*mig->nz+iz]=mig->dt*((float)(forw[iz]/(double)ntz)*(back[iz]/(double)ntz));
		for(it=1;it<mig->nt;it++) for(iz=0;iz<mig->nz;iz++) mig->image[ix*mig->nz+iz]+=mig->dt*((float)(forw[it*mig->nz+iz]/(double)ntz)*(back[it*mig->nz+iz]/(double)ntz));

		/* 2.) Up-Down Imaging */
		// Mute Down-Going Source Wavefield
		if(evenT) memset(&Forw[nkz*nwp],0,nkz*nw*sizeof(fftw_complex));    //Mute - Quadrant
		else memset(&Forw[nkz*nw],0,nkz*nwp*sizeof(fftw_complex));

		fftw_execute_dft_c2r(fftPlans->ifft_2d_c2r_WKz,Forw,forw);         //Transform Back

		// Mute Up-Going Receiver Wavefield
		fftw_execute_dft_c2r(fftPlans->ifft_2d_c2r_WKz,Mute,back);         //Transform Back

		// Apply Zero-Lag Imaging Condition
		for(it=0;it<mig->nt;it++)for(iz=0;iz<mig->nz;iz++)mig->image[ix*mig->nz+iz]+=mig->dt*(float)((forw[it*mig->nz+iz]/(double)ntz)*(back[it*mig->nz+iz]/(double)ntz));

		// Update Progress
		if(verbose&&!(ix%perc)) fprintf(stderr,"\b\b\b\b%3zu%%",(ix+1)*100/mig->nx);
	} //Loop over Horiztonal Locations
	if(verbose) fprintf(stderr,"\b\b\b\b100%%\n");
//writesufile("pw1.su",im1,mig->nz,mig->nx,0.0,0.0,1,1);free(im1);
//writesufile("pw2.su",im2,mig->nz,mig->nx,0.0,0.0,1,1);free(im2);
//writesufile("pw3.su",im3,mig->nz,mig->nx,0.0,0.0,1,1);free(im3);
//writesufile("pw4.su",im4,mig->nz,mig->nx,0.0,0.0,1,1);free(im4);
	/* Deallocate Snapshot Memory */
	for(it=0;it<2*mig->nt;it++) fftw_free(mig->wav[it].tzz);
	fftw_free(forw);fftw_free(Forw);
	fftw_free(Mute);
	fftw_free(back);fftw_free(Back);
	return(0);
}