二维粗糙面的模拟

同一维粗糙面模拟一样,公式和基本理论神马的我就不敲了 有兴趣的同学可以参考

http://files.cnblogs.com/xd-jinjian/%E7%AC%AC%E4%BA%8C%E7%AB%A0%EF%BC%88%E5%BB%BA%E6%A8%A1%EF%BC%89.pdf

二维粗糙面的效果图如下所示

具体代码如下

// 2D_GS_RS.cpp : 定义控制台应用程序的入口点。
//*************本程序基于Monte Carlo方法生成二维高斯粗糙面**************
//by changwei
//**********************************************************************
#include "stdafx.h"
#include<iostream>
#include<iomanip>                                           //格式化输出控制符必包含的头文件
#include<fstream>
#include<cmath>
#include<stdlib.h>
#include<complex>

#define M 64                                                 //x方向采样点数
#define N 64                                                 //y方向采样点数
#define Mdx 8                                                //x方向单位波长内的采样点数
#define Ndy 8                                                //y方向单位波长内的采样点数
#define pi 3.141592627                                       //定义常数pi
using namespace std;

complex<double> unit_i(0.0,1.0);
complex<double> unit_r(1.0,0.0);

//产生随机数的子函数
void random2(double start,double end,double seed,double *rand2)  //在用二维数组作为形参时,必须指明列数
{
	double s=65536.0;
	double w=2053.0;
	double v=13849.0;
	double T=0.0;
	int m;
	for(int i=0;i<N*M;i++)
	{
		T=0.0;
		for(int k=0;k<12;k++)
		{
			seed=w*seed+v;
			m=seed/s;
			seed=seed-m*s;
			T=T+seed/s;
		}
		rand2[i]=start+end*(T-6.0);
	}
	return;
}
//2D傅里叶变换的子程序	
void fft2D(double *data1,int *nn,int ndim,int isign)
{
	 int i1,i2,i2rev,i3,i3rev,ibit,idim,ifp1,ifp2,ip1,ip2,ip3,k1,k2,n,nprev,nrem,ntot;
	 double tempi,tempr;
	 double theta,wi,wpi,wpr,wr,wtemp;
     ntot=1;
     for(idim=0;idim<ndim;idim++)
	 {
		 ntot=ntot*nn[idim];
	 }
     nprev=1;
     for(idim=0;idim<ndim;idim++)
	 {
		 n=nn[idim];
         nrem=ntot/(n*nprev);
         ip1=2*nprev;
         ip2=ip1*n;
         ip3=ip2*nrem;
         i2rev=1;
		 for(i2=1;i2<=ip2;i2=i2+ip1)
		 {
            if(i2<i2rev)
			{
				for(i1=i2;i1<=i2+ip1-2;i1=i1+2)
				{
					for(i3=i1;i3<=ip3;i3=i3+ip2)
					{
						i3rev=i2rev+i3-i2;
						tempr=data1[i3-1];
						tempi=data1[i3];
						data1[i3-1]=data1[i3rev-1];
						data1[i3]=data1[i3rev];
						data1[i3rev-1]=tempr;
						data1[i3rev]=tempi;

					}
				}
			}
            ibit=ip2/2;
			while((ibit>=ip1)&&(i2rev>ibit))
			{
				 i2rev=i2rev-ibit;
				 ibit=ibit/2;
			}
            i2rev=i2rev+ibit;
		 }
         ifp1=ip1;
		 while(ifp1<ip2)
		 {
			  ifp2=2*ifp1;
			  theta=isign*2.0*pi/(ifp2/ip1);
			  wpr=-2.0*sin(0.5*theta)*sin(0.5*theta);
			  wpi=sin(theta);
			  wr=1.0;
			  wi=0.0;
			  for(i3=1;i3<=ifp1;i3=i3+ip1)
			  {
				  for(i1=i3;i1<=i3+ip1-2;i1=i1+2)
				  {
					  for(i2=i1;i2<=ip3;i2=i2+ifp2)
					  {
						  k1=i2;
						  k2=k1+ifp1;
						  tempr=wr*data1[k2-1]-wi*data1[k2];
						  tempi=wr*data1[k2]+wi*data1[k2-1];
						  data1[k2-1]=data1[k1-1]-tempr;
						  data1[k2]=data1[k1]-tempi;
						  data1[k1-1]=data1[k1-1]+tempr;
						  data1[k1]=data1[k1]+tempi;
					  }
				  }
				  wtemp=wr;
				  wr=wr*wpr-wi*wpi+wr;
				  wi=wi*wpr+wtemp*wpi+wi;
			  }
			  ifp1=ifp2;
		 }
		 nprev=n*nprev;
	 }   
      return;	
}  
void Gauss_roughsurface(double hrms,double lcor,double seed,double dx,double dy,double x[][N],double y[][N],double z[][N])
{
	double LX=M*dx;                                                 //粗糙面x方向的长度
	double LY=N*dy;                                                 //粗糙面y方向的长度
	double lx,ly;                                                   //x,y方向的相关长度
	lx=lcor;
	ly=lcor;
	double kx,ky;                                                   //x,y方向的离散空间波数
	double rand2[M*N];                                             //随机数
	double s[M][N];                                                 //功率谱
	double dataF[2*M*N],dataFR[2*M*N],dataFG[2*M*N];
	double tr1,tr2,ti1,ti2;
	int Nij;
	int NN[2];
	NN[0]=N;
	NN[1]=M;
	//相关长度的变换
	lcor=lcor/sqrt(dx*dx+dy*dy);     
	//计算坐标轴
	for(int i=0;i<M;i++)
	{
		for(int j=0;j<N;j++)
		{
			x[i][j]=-LX/2.0+j*dx;                                           //x方向坐标
			y[i][j]=-LY/2.0+i*dy;                                           //y方向坐标
		}
	}
	//计算功率谱
	/*for(int i=0;i<M;i++)
	{
		kx=2*pi*i/LX;                                               //求x方向的空间波数
		for(int j=0;j<N;j++)
		{
			ky=2*pi*j/LY;                                           //求y方向的空间离散波数
			s[i][j]=hrms*hrms*lx*ly/4.0/pi*exp(-kx*kx*lx*lx/4.0-ky*ky*ly*ly/4.0);         //求高斯功率谱
			//s[i][j]=2.0/sqrt(pi)/lcor*exp(-2.0*(x[i][j]*x[i][j]+y[i][j]*y[i][j])/lcor/lcor);
		}
	}*/
	
	double tl1,tl2,temp1,temp2;
	double xx,yy;
	tl1=lcor*lcor/2.0;
	tl2=sqrt(pi)*lcor/2.0;
	for(int i=0;i<M;i++)
	{
		xx=-(M-1)/2+i-0.5;
		for(int j=0;j<N;j++)
		{
			yy=-(N-1)/2+j-0.5;
			temp1=xx*xx+yy*yy;
			temp2=exp(-1.0*temp1/tl1);
			s[i][j]=temp2/tl2;
		}
	}
	//滤波函数的二维傅里叶变换
	
	for(int i=0;i<M;i++)
	{
		for(int j=0;j<N;j++)
		{
			Nij=i*M+j;
			dataFG[2*Nij]=s[i][j];
			dataFG[2*Nij+1]=0.0;
		}
	}
	fft2D(dataFG,NN,2,1);
	
	//正态分布随机数并转换为傅里叶变换数组
	random2(0.0,1.0,seed,rand2);
	for(int i=0;i<M;i++)
	{
		for(int j=0;j<N;j++)
		{
			Nij=i*M+j;
			dataFR[2*Nij]=rand2[Nij];
			dataFR[2*Nij+1]=0.0;
		}
	}
	fft2D(dataFR,NN,2,1);

	//滤波函数与随机数的乘积及其二维逆傅里叶变换
	for(int i=0;i<M*N;i++)
	{
		tr1=dataFR[2*i]*dataFG[2*i];
		tr2=dataFR[2*i+1]*dataFG[2*i+1];
		dataF[2*i]=tr1-tr2;
		ti1=dataFR[2*i]*dataFG[2*i+1];
		ti2=dataFR[2*i+1]*dataFG[2*i];
		dataF[2*i+1]=ti1+ti2;
	}
	fft2D(dataF,NN,2,-1);
	//高度函数的生成
	for(int i=0;i<M;i++)
	{
		for(int j=0;j<N;j++)
		{
			Nij=i*M+j;
			z[i][j]=hrms*dataF[2*Nij]/(M*N);
		}
	}
    return;
}

int _tmain(int argc, _TCHAR* argv[])
{
	double wavespeed=3.0*pow(10.0,8);                                 //波速
	double frequence=1.0*pow(10.0,9);                                 //频率
	double lamd=wavespeed/frequence;                                  //波长
	double hrms=0.1*lamd;                                             //均方根高度
	double lcor=0.5*lamd;                                             //相关长度
	double seed=123.456;                                              //随机数种子
	double dx=lamd/Mdx;                                               //x方向采样间距
	double dy=lamd/Ndy;                                               //y方向采样间距
	double x[M][N];                                                   //二维粗糙面x方向坐标
	double y[M][N];                                                   //二维粗糙面y方向坐标
	double z[M][N];                                                  //二维粗糙面高度起伏值

	Gauss_roughsurface(hrms,lcor,seed,dx,dy,x,y,z);
	ofstream foutrs("2DGRS.dat",ios::out);
	for(int i=0;i<M;i++)
		for(int j=0;j<N;j++)
			foutrs<<setiosflags(ios::left)<<setw(8)<<x[i][j]<<setiosflags(ios::left)<<setw(8)<<y[i][j]<<setiosflags(ios::left)<<setw(8)<<z[i][j]<<endl;
	foutrs.close();
	return 0;
}

  

原文地址:https://www.cnblogs.com/xd-jinjian/p/3674578.html