方网格上的基本方程是发散的(计算流体动力学)

时间:2018-11-17 21:59:12

标签: java physics

我正在尝试制作一个用于模拟原始方程式的基本程序,但是由于它迅速发散,所以出现了问题。 我以这篇论文为指导: http://www.met.reading.ac.uk/~ross/Science/PrimEqs.html确实不错,但并没有帮助我将其转换为工作代码。我得到了概念(发散,导数,材料导数(某种),压力梯度等...),但是由于我的代码一直在混乱,所以它很奇怪。

黏度和扩散度均为0,所以不必担心它们。(我已经分别测试了它们,并且两者都很稳定)

void update()
{
  VDiv = Divergence(Velocity);
  PVector[][] ViscosityVector = VectorLaplace(Velocity);
  TempChange = Laplace(Temp);//diffusion operator
  PGrad = Gradient(Pressure);//pressure force
  for(int i=amountX-1;i>=0;i--)
  {
    for(int j=amountY-1;j>=0;j--)
    {
      TempChange[i][j]*=Diffusion;
      TempChange[i][j]-=VDiv[i][j]*Pressure[i][j];// temp changes as volume changes

      PVector Accel=new PVector(0,Grav).sub(PVector.div(PGrad[i][j],Density[i][j]));

      Accel.add(PVector.mult(ViscosityVector[i][j],Viscosity));//viscocity
      float TS=(Density[i][j]*HeatCapacity);

      //the material derivative
      Velocity[i][j].add(Accel.mult(DT));
      Temp[i][j]+=DT*TempChange[i][j]/TS;
      if(i<amountX-1)
      {
        Temp[i+1][1]+=    Velocity[i][j].x*DT;
        Temp[i][j]-=      Velocity[i][j].x*DT;
        Density[i+1][j]+= Velocity[i][j].x*DT;
        Density[i][j]-=   Velocity[i][j].x*DT;
      }
      if(j<amountY-1)
      {
        Temp[i][j+1]+=    Velocity[i][j].y*DT;
        Temp[i][j]-=      Velocity[i][j].y*DT;
        Density[i][j+1]+= Velocity[i][j].y*DT;
        Density[i][j]-=   Velocity[i][j].y*DT;
      }
      // ideal gas law
      Pressure[i][j]=Density[i][j]*(GasConst*Temp[i][j]);
    }
  }
}

我很确定子功能没有问题,但是在这里以防万一。

PVector[][] Gradient(float[][] Input)
{
  PVector[][] Out = new PVector[amountX][amountY];
  for(int i=0;i<amountX;i++)
  {
    for(int j=0;j<amountY;j++)
    {
      Out[i][j]=new PVector();
      if(j<amountY-1)
        Out[i][j].y=(-Input[i][j]+Input[i][j+1])*DY;
      if(i<amountX-1)
        Out[i][j].x=(-Input[i][j]+Input[i+1][j])*DX;

    }
  }
  return Out;
}
PVector[][] VectorLaplace(PVector[][] Input)
{
  float[][] InputX=new float[amountX][amountY];
  float[][] InputY=new float[amountX][amountY];
  for(int i =0;i<amountX;i++)
  {
    for(int j =0;j<amountY;j++)
    {
      InputX[i][j]=Input[i][j].x;
      InputY[i][j]=Input[i][j].y;
    }
  }
  InputX = Laplace(InputX);
  InputY = Laplace(InputY);
  PVector[][] Out = new PVector[amountX][amountY];
  for(int i =0;i<amountX;i++)
  {
    for(int j =0;j<amountY;j++)
    {
      Out[i][j]=new PVector(InputX[i][j],InputY[i][j]);
    }
  }
  return Out;
}
float[][] Laplace(float[][] Input)
{
  float[][] Flow = new float[amountX][amountY];
  for(int i =0;i<amountX;i++)
  {
    for(int j =0;j<amountY;j++)
    {
      if(i>0)
      {
        Flow[i][j]-=Input[i][j];
        Flow[i-1][j]+=Input[i][j];
      }
      if(j>0)
      {
        Flow[i][j]-=Input[i][j];
        Flow[i][j-1]+=Input[i][j];
      }
      if(i<amountX-1)
      {
        Flow[i][j]-=Input[i][j];
        Flow[i+1][j]+=Input[i][j];
      }
      if(j<amountY-1)
      {
        Flow[i][j]-=Input[i][j];
        Flow[i][j+1]+=Input[i][j];
      }
    }
  }
  return Flow;
}
float[][] Divergence(PVector[][] Input)
{
  float[][] Out = new float[amountX][amountY];
  for(int i=0;i<amountX;i++)
  {
    for(int j=0;j<amountY;j++)
    {
      if(i>0)
      {
        Out[i][j]-=(Input[i-1][j].x)*DX;
      }
      if(j>0)
      {
        Out[i][j]-=(Input[i][j-1].y)*DY;
      }
      if(i<amountX-1)
      {
        Out[i][j]+=(Input[i][j].x)*DX;
      }
      if(j<amountY-1)
      {
        Out[i][j]+=(Input[i][j].y)*DY;
      }
    }
  }
  return Out;
}

有人可以看到问题所在吗?

失败所需的最少代码:

void update()
{
  PGrad = Gradient(Pressure);//pressure force
  for(int i=amountX-1;i>=0;i--)
  {
    for(int j=amountY-1;j>=0;j--)
    {

      PVector Accel=new PVector(0,Grav).sub(PVector.div(PGrad[i][j],Density[i][j]));


      //the material derivative
      Velocity[i][j].add(Accel.mult(DT));
      if(i<amountX-1)
      {
        Density[i+1][j]+= Velocity[i][j].x*DT*Density[i][j];
        Density[i][j]-=   Velocity[i][j].x*DT*Density[i][j];
      }
      if(j<amountY-1)
      {
        Density[i][j+1]+= Velocity[i][j].y*DT*Density[i][j];
        Density[i][j]-=   Velocity[i][j].y*DT*Density[i][j];
      }
      // ideal gas law
      Pressure[i][j]=Density[i][j];
    }
  }
}

PVector[][] Gradient(float[][] Input)
{
  PVector[][] Out = new PVector[amountX][amountY];
  for(int i=0;i<amountX;i++)
  {
    for(int j=0;j<amountY;j++)
    {
      Out[i][j]=new PVector();
      if(j<amountY-1)
        Out[i][j].y=(-Input[i][j]+Input[i][j+1])*DY;
      if(i<amountX-1)
        Out[i][j].x=(-Input[i][j]+Input[i+1][j])*DX;

    }
  }
  return Out;
}

简单的一维伪代码:

for(int i =0;i<N-1;i++) 
  Gradient[i]=(Pressure[i]-Pressure[i+1])*dx; 
for(int i =0;i<N;i++) 
{ 
  Accel = -Gradient[i]/Density[i]; 
  Velocity[i]+=Accel*dt; 
  if(i<N-1) 
  { 
    Density[i+1]+=Velocity*dt; 
    Density[i]-=Velocity*dt; 
  } 
  Pressure[i]=Density[i]; 
}

这里是测试的全部内容。包含温度,粘度和扩散。如果需要,可以禁用它们。需要处理https://processing.org/

int amountX=40;
int amountY=20;
float[][] Temp=new float[amountX][amountY];
float[][] Density=new float[amountX][amountY];
float[][] Pressure=new float[amountX][amountY];
PVector[][] Velocity=new PVector[amountX][amountY];
float Grav=0.05;
float GasConst=1;
float HeatCapacity=5;
float Diffusion=0.5;
float Viscosity=0.4;
float DX=1;
float DY=1;
float DT=0.001;
int Warp = 1;
float[][] VDiv;
float[][] TempChange;
PVector[][] PGrad;
void setup()
{
  size(1000,500);
  for(int i=0;i<amountX;i++)
  {
    for(int j=0;j<amountY;j++)
    {
      Temp[i][j]=3;
      Pressure[i][j]=exp(j*Grav/(GasConst*Temp[i][j]))*40;
      Density[i][j]=Pressure[i][j]/(GasConst*Temp[i][j]);
    }

  }
  for(int i=0;i<amountX;i++)
  {
    for(int j=0;j<amountY;j++)
    {
      Velocity[i][j]=new PVector(0,0);
    }
  }
  int Min=10;
  int Max=15;
  for(int i=Min;i<Max;i++)
  {
    for(int j=Min;j<Max;j++)
    {
      float x=(i-Min)/(float)(Max-Min);
      float y=(j-Min)/(float)(Max-Min);
      Temp[i][j]=lerp(3,6,exp(-(sq(2*x-1)+sq(2*y-1))*3));
    }
  }

  for(int i =0;i<0;i++)
  {
    update();
  }
}
void draw()
{
  background(201);
  for(int i = 0;i<Warp;i++)
  {
    update();
  }
  show();

}
void show()
{

  float dx=width/(float)amountX;
  float dy=height/(float)amountY;
  float dv=10*dx;
  noStroke();
  for(int i=0;i<amountX;i++)
  {
    for(int j=0;j<amountY;j++)
    {
      fill(Temp[i][j]*10,0,Density[i][j]*10);
      rect(dx*i,dy*j,dx,dy);

    }
  }
  stroke(255);
  for(int i=0;i<amountX;i+=1)
  {
    for(int j=0;j<amountY;j+=1)
    {
      line(dx*(i+0.5),dy*(j+0.5),dx*(i+0.5)+Velocity[i][j].x*dv,dy*(j+0.5)+Velocity[i][j].y*dv);
    }
  }
  int MouseI=(int)(mouseX/dx);
  int MouseJ=(int)(mouseY/dy);
  fill(255);
  if(MouseI>0&&MouseJ>0&&MouseI<amountX-1&&MouseJ<amountY-1)
  {
    text("Temp:"+Temp[MouseI][MouseJ],10,20);
    text("Pres:"+Pressure[MouseI][MouseJ],10,40);
    text("Dens:"+Density[MouseI][MouseJ],10,60);
  }
}
void update()
{
  VDiv = Divergence(Velocity);
  PVector[][] ViscosityVector = VectorLaplace(Velocity);
  TempChange = Laplace(Temp);//diffusion operator
  PGrad = Gradient(Pressure);//pressure force
  for(int i=amountX-1;i>=0;i--)
  {
    for(int j=amountY-1;j>=0;j--)
    {
      TempChange[i][j]*=Diffusion;
      TempChange[i][j]-=VDiv[i][j]*Pressure[i][j];// temp changes as volume changes

      PVector Accel=new PVector(0,Grav).sub(PVector.div(PGrad[i][j],Density[i][j]));

      Accel.add(PVector.mult(ViscosityVector[i][j],Viscosity));//viscocity
      float TS=(Density[i][j]*HeatCapacity);

      //the material derivative
      Velocity[i][j].add(Accel.mult(DT));
      Temp[i][j]+=DT*TempChange[i][j]/TS;
      if(i<amountX-1)
      {
        Temp[i+1][1]+=    Velocity[i][j].x*DT;
        Temp[i][j]-=      Velocity[i][j].x*DT;
        Density[i+1][j]+= Velocity[i][j].x*Density[i][j];
        Density[i][j]-=   Velocity[i][j].x*Density[i][j];
      }
      if(j<amountY-1)
      {
        Temp[i][j+1]+=    Velocity[i][j].y*DT;
        Temp[i][j]-=      Velocity[i][j].y*DT;
        Density[i][j+1]+= Velocity[i][j].y*DT*Density[i][j];
        Density[i][j]-=   Velocity[i][j].y*DT*Density[i][j];
      }
      // ideal gas law
      Pressure[i][j]=Density[i][j]*(GasConst*Temp[i][j]);
    }
  }
}

PVector[][] Gradient(float[][] Input)
{
  PVector[][] Out = new PVector[amountX][amountY];
  for(int i=0;i<amountX;i++)
  {
    for(int j=0;j<amountY;j++)
    {
      Out[i][j]=new PVector();
      if(j<amountY-1)
        Out[i][j].y=(-Input[i][j]+Input[i][j+1])*DY;
      if(i<amountX-1)
        Out[i][j].x=(-Input[i][j]+Input[i+1][j])*DX;

    }
  }
  return Out;
}
PVector[][] VectorLaplace(PVector[][] Input)
{
  float[][] InputX=new float[amountX][amountY];
  float[][] InputY=new float[amountX][amountY];
  for(int i =0;i<amountX;i++)
  {
    for(int j =0;j<amountY;j++)
    {
      InputX[i][j]=Input[i][j].x;
      InputY[i][j]=Input[i][j].y;
    }
  }
  InputX = Laplace(InputX);
  InputY = Laplace(InputY);
  PVector[][] Out = new PVector[amountX][amountY];
  for(int i =0;i<amountX;i++)
  {
    for(int j =0;j<amountY;j++)
    {
      Out[i][j]=new PVector(InputX[i][j],InputY[i][j]);
    }
  }
  return Out;
}
float[][] Laplace(float[][] Input)
{
  float[][] Flow = new float[amountX][amountY];
  for(int i =0;i<amountX;i++)
  {
    for(int j =0;j<amountY;j++)
    {
      if(i>0)
      {
        Flow[i][j]-=Input[i][j];
        Flow[i-1][j]+=Input[i][j];
      }
      if(j>0)
      {
        Flow[i][j]-=Input[i][j];
        Flow[i][j-1]+=Input[i][j];
      }
      if(i<amountX-1)
      {
        Flow[i][j]-=Input[i][j];
        Flow[i+1][j]+=Input[i][j];
      }
      if(j<amountY-1)
      {
        Flow[i][j]-=Input[i][j];
        Flow[i][j+1]+=Input[i][j];
      }
    }
  }
  return Flow;
}
float[][] Divergence(PVector[][] Input)
{
  float[][] Out = new float[amountX][amountY];
  for(int i=0;i<amountX;i++)
  {
    for(int j=0;j<amountY;j++)
    {
      if(i>0)
      {
        Out[i][j]-=(Input[i-1][j].x)*DX;
      }
      if(j>0)
      {
        Out[i][j]-=(Input[i][j-1].y)*DY;
      }
      if(i<amountX-1)
      {
        Out[i][j]+=(Input[i][j].x)*DX;
      }
      if(j<amountY-1)
      {
        Out[i][j]+=(Input[i][j].y)*DY;
      }
    }
  }
  return Out;
}

0 个答案:

没有答案