ising模型(伊辛模型)
一、关于ising模型
- 简介
伊辛模型(Ising model)是一类描述物质相变的随机过程(stochastic process)模型。物质经过相变,要出现新的结构和物性。发生相变的系统一般是在分子之间有较强相互作用的系统,又称合作系统。
伊辛模型所研究的系统由多维周期性点阵组成,点阵的几何结构可以是立方的或六角形的,每个阵点上都赋予一个取值表示自旋变数,即自旋向上或自旋向下。伊辛模型假设只有最近邻的自旋之间有相互作用,点阵的位形用一组自旋变数来确定。常见的二维伊辛模型示意图使用箭头方向表示自旋方向。 - 历史
伊辛模型由德国物理学家威廉·楞次(Wilhelm Lenz)在1920年提出以描述铁磁性物质的内部的原子自旋状态及其与宏观磁矩的关系。1924年,楞次的学生Ernst Ising求解了不包含相变的一维伊辛模型 。20世纪30-40年代,劳伦斯·布拉格(Lawrence Bragg)、E. J. Williams、汉斯·贝特(Hans Bethe)、Rudolf Peierls等学者使用平均场近似理论(mean-field theory)对二维伊辛点阵模型(two-dimensional square-lattice Ising model)进行了研究 。1944年美国物理学家拉斯·昂萨格(Lars Onsager)得到了二维伊辛模型在没有外磁场时的解析解,即Onsager解 - PS:代码依据,基于蒙特卡洛的随机方式,对磁性材料的自发磁化现象进行模拟,1.磁性材料在相变温度T0以下产生自发磁化,展现出铁磁性,高于T0,无法被磁化,展现出顺磁性。2.简化处理:二维模型,即磁矩仅有两种状态,用1或-1来表示。3.低温时,体系总体能量趋向于最低状态,而高温时体系去向混乱度最大。且磁矩变化取决于翻转前后体系能量变化 deltaE ,从高能量态想低能量态转变时容易的,反之以exp(-deltaE/(KT))的概率翻转。关于此模型的一个非常有趣的比喻,以及详细原理,可参考:http://wiki.swarma.net/index.php/ISING%E6%A8%A1%E5%9E%8B 好了话不多说直接上C代码。
二、代码
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
unsigned long _RandomNumber = time(NULL);
#define GET_NEXT_RANDOM (_RandomNumber = (_RandomNumber << 7) + (_RandomNumber >> 7))
#define big 25
void put(FILE *outstream, double data1, double data2)
{
fprintf(outstream, "%f,%f\n,", data1, data2);
}
/*
函数功能:计算平均磁矩
参数:
spots:点阵
size:点阵大小
返回值:
平均磁矩
*/
double record(int *spots,int size)
{
/*统计磁矩状态*/
int *p = spots;
double sum = 0;
while(p<(spots+size))
{
sum += *p;
p++;
}
return sum/size;
}
/*
函数功能:产生随机数 -1 或 1
参数:
*/
int random()
{
int rand;
rand = GET_NEXT_RANDOM % 2;
if(rand==0)
return -1;
else
return 1;
}
/*
函数功能:均匀分布随机数
参数:
*/
double ran()
{
long a = GET_NEXT_RANDOM % 100000;
return a/99999.0;
}
/*
函数功能:计算磁矩翻转概率
参数:
deltae:翻转前能量E1-翻转后能量E2
T:温度
*/
double probli(int deltae, double T)
{
return exp(-deltae/T);
}
/*
函数功能:随机初始化磁矩
参数:
spots:点阵
size:点阵大小
*/
void initial(int *spots, int size)
{
double sum = 0;
int *p = spots;// 首元素地址
// 永磁体 1
while(p<(spots+size))
{
*p++ = random();
//*p++ = -1;
}
sum = record(spots, size);
printf("磁性前:%f\t",sum);
}
/*
函数功能:磁矩随机翻转
参数:
spots:点阵
t:温度
*/
void flip(int spots[][big], double t)
{
long k;
double sum = 0;
int size = (sizeof(*spots)/4)*(sizeof(*spots)/4);
for(k = 0; k<100000; k++)
{
// 随机取点 100000 个
int i = rand()%big;
int j = rand()%big;
//计算E1、E2、deltaE
int h1 = i-1;
int h2 = i+1;
int l1 = j-1;
int l2 = j+1;
if(i==0)
h1 = big-1;
else if(i==big-1)
h2 = 0;
if(j==0)
l1= big-1;
else if(j==big-1)
l2= 0;
int e1 = -(spots[i][l1]+spots[i][l2]+spots[h1][j]+spots[h2][j])*spots[i][j];
int e2 = -e1;
int deltae = e2-e1;
// 判断是否翻转
if(deltae<=0)
{
spots[i][j] = -spots[i][j];
}
else if(ran()<probli(deltae, t))
{
spots[i][j] = -spots[i][j];
}
}
}
int main(int argc, char *argv[])
{
double sum;
int spots[big][big] = {0};
int size = sizeof(spots)/4; // 二维点阵大小
//磁性初始化
initial(*spots, size);
/*
功能:不同温度下的磁性状况
参数:
tStart:起始温度
tEnd:终止温度
deta:温度间隔
PS:相变温度为2左右,间隔不宜设置太大
*/
double tStart=0.5;
double tEnd=2.5;
double deta = 0.05;
double t = tStart;
//输出温度、平均磁矩到文件 "isingData.txt"
FILE *outstream;
if((outstream=fopen("isingData.txt", "a")) == NULL)
{
printf("Cannot open file, press any key to exit!\n");
exit(1);
}
while(t<tEnd){
t = t+deta;
flip(spots, t);
//统计平均磁性(范围-1~1)
sum = record(*spots, size);
printf("温度:%f\t平均磁性:%f\n",t,sum);
fprintf(outstream, "%f\t%f\n", t, sum);
}
fclose(outstream);
return 0;
}
出于对视觉效果的追求,又写了一个可视化脚本,效果如下:
需要的朋友,到这里–>下载
三、数据分析
1.图一(温度-磁性曲线)
从演化的结果来看,材料的磁性在2.3-2.5之间发生了突变,即该范围内存在相变点。
2.图二
T>T0,材料展现顺磁性,无论演化次数如何增加,磁性始终在0附近小范围波动。
3.图三
T<T0,材料展现出铁磁性
并且存在两种演化结果,平均磁矩为1或-1
四、写在最后
模型的理念启示非常简单,整个就是一个随大流的趋势,每次翻转,都是先进行一次随机选择,被选中者将面临两种选择,要么“顺势而为”(能量最低),要么活出自我(低到高)。最后在一次次的随机选择,概率翻转下演化出最后的结果。
其实不难发现,模型本身的内涵并不复杂,但模型给人造成的感觉却非常奇妙,该模型的意义便是将这种看似复杂的演化过程,通过计算机实现。