Skip to content
Snippets Groups Projects
muteDisp.c 3.98 KiB
#include<stdlib.h>
#include<math.h>
#include<complex.h>
#include<fftw3.h>
#include"fdacrtmc.h"

int k1k2CircFilt(float *in, float *out, size_t n1, size_t n2, float d, float kl, float kh, fftPlansPar *fftPlans){
/* 2D-Wavenumber Circular Filter */
/* Dispersion is muted by applying a circular cosine-square tapered filter around the origin in
   the wavenumber domain. The taper is 1 till kl, after which it decays accoring to the cosine
   squared to 0 at kh.
   
   INPUTS:
      float       *in          Floating point input  array.
      float       *out         Floating point output array.
      size_t       n1          Size of fast dimension
      size_t       n2          Size of slow dimension
      float        d           Spatial step size for both dimensions
      float        kl          Inner radius, or start, of wavenumber filter
      float        kh          Outer radius, or end,   of wavenumber filter
      fftPlansPar *fftPlans    Structure containing FFTw plans

   OUTPUT:
      int                      0 for normal termination

   NOTE:
     1) Input pointer can be the same as output pointer.
*/
	/* Declarations */
	size_t i, i1, i2, n12, nk1p, nk1, nk2p, nk2, nk1k2;
	bool evenk1, evenk2;
	double dk, k, *k1, *k2, *IN;
	fftw_complex *KK, *OP;

	/* Compute Constants */
	n12=n1*n2;    //Total number of elements in arrays
	// Fast Dimension
	nk1p=n1/2;     //Number of positive fast dimension wavenumbers
	nk1 =nk1p+1;   //Number of          fast dimension wavenumbers
//	nk1n=n1-nk1;   //Number of negative fast dimension wavenumbers
	// Slow Dimension
	nk2p=n2/2;     //Number of positive slow dimension wavenumbers
	nk2 =nk2p+1;   //Number of          slow dimension wavenumbers
//	nk2n=n2-nk2;   //Number of negative slow dimension wavenumbers

	/* Check Even or Odd */
	if(n1%2){
		evenk1=false;
		nk1--;
	}else{
		// Note we mute the highest frequency component
		evenk1=true;
		nk1-=2;
	}
	if(n2%2){
		evenk2=false;
		nk2--;
	}else{
		// Note we mute the highest wavenumber component
		evenk2=true;
		nk2-=2;
	}
	nk1k2=nk1*n2;

	/* Allocate Arrays */
	k1 =(double*)fftw_malloc(nk1*sizeof(double));                 //Fast Dimension Wavenumber
	k2 =(double*)fftw_malloc(n2*sizeof(double));                  //Fast Dimension Wavenumber
	IN =(double*)fftw_malloc(n12*sizeof(double));                 //Double precision input  array
	KK =(fftw_complex*)fftw_malloc(nk1k2*sizeof(fftw_complex));   //Wavenumber domain array
	OP =(fftw_complex*)fftw_malloc(nk1k2*sizeof(fftw_complex));   //Wavenumber domain array

	/* Construct Wavenumber Arrays */
	// k1
	if(evenk1){
		dk=6.28318530717958647692528676655900576839433879875021164194989/(((double)n1)*d);
	}else{
		dk=6.28318530717958647692528676655900576839433879875021164194989/(((double)(n1-1))*d);
	}
	*k1=0; //First wavenumber is zero
	for(i1=1;i1<nk1;i1++)k1[i1]=i1*dk;
	// k1
	if(evenk2){
		dk=6.28318530717958647692528676655900576839433879875021164194989/(((double)n1)*d);
	}else{
		dk=6.28318530717958647692528676655900576839433879875021164194989/(((double)(n1-1))*d);
	}
	*k2=0; //First wavenumber is zero
	for(i2=1;i2<nk2p;i2++)k2[i2]=i2*dk;
	if(evenk2)i1=i2-1;else i1=i2;
	for(;i1>0;i1--)k2[++i2]=-k2[i1--];

	/* Compute Operator */
	dk=kh-kl;
	for(i2=0;i2<nk2;i2++){
		for(i1=0;i1<nk1;i1++){
			k=sqrtf(k1[i1]*k1[i1]+k2[i2]*k2[i2]);
			if(k<kl){
				OP[i2*nk1+i1]=1.;
			}else if(k>kh){
				OP[i2*nk1+i1]=0.;
			}else{
				OP[i2*nk1+i1]=cos(1.5707963267948966192313216916398*(k-kl)/dk);
				OP[i2*nk1+i1]*=OP[i2*nk1+i1];
			}
		}
	}
	if(evenk2)i=i2-1;else i=i2;
	for(;i>0;i--)OP[++i2*nk1+i1]=OP[i--*nk1+i1];

	/* Convert to Double */
	for(i=0;i<n12;i++) IN[i]=(double)in[i];

	/* Transform to the Wavenumber Domain */
	fftw_execute_dft_r2c(fftPlans->fft_2d_r2c_XZ,IN,KK);

	/* Apply Operator */
	for(i=0;i<nk1k2;i++)KK[i]*=OP[i];

	/* Transform to the Space Domain */
	fftw_execute_dft_c2r(fftPlans->ifft_2d_c2r_KxKz,KK,IN);

	/* Convert to Single */
	for(i=0;i<n12;i++) out[i]=(float)IN[i];

	/* Clean-Up & Return */
	free(k1);free(k2);
	free(IN);free(KK);
	free(OP);
	return(0);
}