ChinaNet

标题: [原创]用Monte-Carlo方法研究二维Ising模型的相变问题,求出... [打印本页]

作者: DoubleX    时间: 2015-4-8 10:40
标题: [原创]用Monte-Carlo方法研究二维Ising模型的相变问题,求出...
/**************************************************************************************
*程序用途:用Monte-Carlo方法研究二维Ising模型的相变问题,求出临界温度T,比热C及磁化率χ
*编译环境:Visual C++ 6.0
*作    者:lxg  
*单    位:
*完成时间:2005年12月28日
**************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#define L 150                         /*L×L个格点                          */
#define preN   100000                 /*舍弃前preN个E,M值                  */
#define lateN 5100000                 /*总共计算lateN个E,M值               */
#define deltaN (lateN-preN)           /*Monte-Carlo方法抽样E,M个数         */
double recordEnergy[deltaN];          /*存储抽样能量值                      */
int recordMagnet[deltaN];             /*存储抽样磁矩量                      */
int lattice[L][L];                    /*格点,存储格点状态                  */
int temp[L][L];                       /*保留初始化格点状态                  */
double energy;                        /*记录初试化及试探后系统能量,磁矩    */
int magnet;                           /*并赋给recordEnergy和recordMagnet    */
double T;                             /*温度                                */
struct CX                             /*比热C和磁化率χ                     */
{
    double C;
    double X;
};
/****************************************************************************
*函数原型
*****************************************************************************/
void InitialLattice();
void SaveInitial();
void GetInitial();
void CaculateFirstMagnet();
void CaculateFirstEnergy();
void GenerateNext();
struct CX Caculate_C_and_X();
/****************************************************************************
*主函数
*****************************************************************************/
int main()
{
int i;
    struct CX cx[200];
    FILE *ft,*fx,*fc;
ft=fopen("T.txt","w");
fx=fopen("X.txt","w");
fc=fopen("C.txt","w");
    srand(time(NULL));

T = 1.0;
for(i=0;T<4.0;i++)
{
  InitialLattice();
  cx=Caculate_C_and_X();
  fprintf(ft,"%f\n",T);
  fprintf(fx,"%f\n",cx.X);
  fprintf(fc,"%f\n",cx.C);
  printf("T=%f ",T);
  printf("  X=%f ",cx.X);
  printf("  C=%f\n",cx.C);
        T = T+0.05;
}

fclose(ft);
fclose(fx);
fclose(fc);
return 0;
}
/***************************************************************************
*函数实现
****************************************************************************/
void InitialLattice()                              /*初始化格点状态,可以  */
{                                                  /*通过热初始化和冷初始化*/
    int i,j;                                      
    for(i=0;i<L;i++)
    {
        for(j=0;j<L;j++)
  {
   if((rand()%10)>5) lattice[j]=1;
   else              lattice[j]=1;      /*1冷初始化,-1热初试化*/
        }
    }
}
void SaveInitial()                                  /*保存第一次初始化状态*/
{                                                   /*若为冷初试化,可以不*/
int k,m;                                        /*调用该函数          */
for(k=0;k<L;k++)
{
  for(m=0;m<L;m++)
   temp[k][m]=lattice[k][m];
}
}
void GetInitial()                                   /*提取第一次初始化状态*/
{                                                   /*若为冷初试化,可以不*/
int k,m;                                        /*调用该函数          */
for(k=0;k<L;k++)                                 
{
  for(m=0;m<L;m++)
   lattice[k][m]=temp[k][m];
  
}
}
void CaculateFirstMagnet()                           /*计算初试化后系统磁矩*/
{
    int i,j;
    int iMagnet=0;
    for(i=0;i<L;i++)
    {
        for(j=0;j<L;j++)
   iMagnet += lattice[j];
    }
    magnet = iMagnet;
}
void CaculateFirstEnergy()                           /*计算初试化后系统能量*/
{

    double dEnergy = 0.0;
int up,down,right,left,px,py;
for(px=0;px<L;px++)
{
  for(py=0;py<L;py++)
  {
   up = (L+px-1)%L;
   down = (px+1)%L;
   right = (L+py-1)%L;
   left = (py+1)%L;
   dEnergy += 0.5*lattice[px][py]*(lattice[up][py]+lattice[down][py]+lattice[px][right]+lattice[px][left]);
  }
}

energy = dEnergy;
}
void GenerateNext()                                     /*试探,产生下一状态*/
{
    int px,py;
    int dE,sum;
int up,down,right,left;
px = rand()%L;
    py = rand()%L;

up = (L+px-1)%L;
down = (px+1)%L;
right = (L+py-1)%L;
left = (py+1)%L;

sum = (lattice[px][py])*(lattice[up][py]+lattice[down][py]+lattice[px][right]+lattice[px][left]);
switch(sum)
{
case 4: dE= 8; break;
case 2: dE= 4; break;
case 0: dE= 0; break;
case -2: dE= -4; break;
case -4: dE= -8; break;
default: printf("---Erro!---\n"); break;
}

    if( dE>0 )                                              /*判断是否接受试探*/
    {
        if((rand()*1.0/RAND_MAX) <= exp((-1.0)*dE/T))
  {
   lattice[px][py] = -lattice[px][py];
   magnet += 2*lattice[px][py];                    /*更新磁矩大小*/
   energy += dE;                                   /*更新能量大小*/
  }
  
    }
    else
    {
  lattice[px][py] = -lattice[px][py];
  magnet += 2*lattice[px][py];                        /*更新磁矩大小*/
  energy += dE;                                       /*更新能量大小*/
    }

}
struct CX Caculate_C_and_X()                                /*计算比热C及磁化率χ*/
{
    struct CX cx;
    int i;
    double AvgEnergy=0.0;
    double AvgSquareEnergy=0.0;
    double AvgMagnet=0.0;
    double AvgSquareMagnet=0.0;

CaculateFirstMagnet();                                   /*初始化磁矩*/
CaculateFirstEnergy();                                   /*初始化能量*/

    for(i=0; i<lateN; i++)
    {
        GenerateNext();                                       /*试探        */
        if(i>=preN)                                           /*舍弃前preN个*/
        {
            recordEnergy[i-preN] = energy;                    /*记录能量值  */
            recordMagnet[i-preN] = magnet;                    /*记录磁矩值  */
  }
}

    for(i=0;i<deltaN;i++)                                     /*计算物理量的平均值*/
    {
        AvgEnergy += (double)recordEnergy/deltaN;
        AvgSquareEnergy += (double)recordEnergy*recordEnergy/deltaN;
        AvgMagnet += (double)recordMagnet/deltaN;
        AvgSquareMagnet += (double)recordMagnet*recordMagnet/deltaN;
    }

    cx.C = (AvgSquareEnergy - AvgEnergy*AvgEnergy)/T/T;        /*得出结果,并返回*/
    cx.X = (AvgSquareMagnet - AvgMagnet*AvgMagnet)/T;
   
    return cx;
}
C-T曲线:
C-X曲线:
本帖转自52mc论坛






欢迎光临 ChinaNet (http://www.nuclear.net.cn/) Powered by Discuz! X3.1