c语言解二维正方马德隆常数(含晶格图像、晶胞贡献和距离分布)
来自:Geek囧
c语言解二维正方马德隆常数(含晶格图像、晶胞贡献和距离分布) 接触固体物理,难免就会被灌输马德隆常数这个概念,简单的说就是晶体内离子对库伦能贡献的总和,当然如果还是云里雾里的话,可以去网上查查,或者直接请教埃夫琴大师。 首次在习题里遇到它,我完全没思路,因为上课没听。后来发现网上有人用C做CsCl的马德隆常数计算,我想可以先尝试下二维的,预计能编程了八成就把这个概念弄懂了。 程序用的语言很简单,多是for罢了,我的c语言功底不够深厚,编的很繁琐,写了好多行,不建议的同学可以慢慢看,我有注解的。如果有人想借鉴的话,尽管用吧,这种程序现在对我来说不算什么了。有高手提意见,我很荣幸~~ 下面是源程序(这是我3月份写的了,那时哥还没有豆瓣): #include <stdio.h> #include <math.h> #define Positive 1 正离子 #define Negative 2 负离子 #define C_row (2*N)/2 晶体中心离子的坐标位置 #define C_rank (2*N)/2 #define MAX 50 int N,S[MAX],cnt_dc=0,cnt=0; 各种外部变量定义。。。。。后面要用的 float a[MAX][MAX],D[MAX][MAX],dc[MAX],temp,d[MAX][MAX],d0[MAX],K[MAX]; float Madelung_constant=0.0; lattice(int N) { int i,j,k,m,n; k=-1; for(i=0;i<2*N+1;i++) { for(j=0;j<2*N+1;j++) { if(k==-1) { a[i][j]=-1.0; 由于不同性质的离子间的作用,正离子对库伦能贡献的计算时要x -1 if(j!=2*N) printf("%c----",Positive); else printf("%c",Positive); 我创意的把离子的图像设为 白笑脸,和黑笑脸,这里是黑的 } else if(k==1) { a[i][j]=1.0; 同上,负离子x +1 if(j!=2*N) printf("%c----",Negative); else printf("%c",Negative); } k*=-1; } if(i!=2*N) { for(m=1;m<=3;m++) 纵向的连线。。把离子连起来,比较美观 { printf("\n|"); for(n=1;n<=2*N;n++) printf(" |"); } printf("\n"); } else printf("\n"); } } Devotion_cell(int N) 离子对晶胞的贡献 { int i,j; for(i=0;i<2*N+1; i++) for(j=0;j<2*N+1;j++) { if((i==0&&j==0)||(i==0&&j==2*N)||(i==2*N&&j==0)||(i==2*N&&j==2*N)) D[i][j]=0.25; else if((i==0&&j>=1&&j<=2*N-1)||(i>=1&&i<=2*N-1&&j==0)||(i==2*N&&j>=1&&j<=2*N-1)||(i>=1&&i<=2*N-1&&j==2*N)) D[i][j]=0.5; else D[i][j]=1.0; 仔细观察晶体的结构就会发现,对晶胞贡献的多少和所处在晶体的位置有特定的关系,比如四个角上永远都是1/4,而四边上则是1/2等等。。。。。。 } for(i=0;i<2*N+1;i++) { for(j=0;j<2*N+1;j++) printf("%0.4f\t",D[i][j]); printf("\n"); } } Distance(int N) { int i,j,flag,temp1,l; (C_row,C_rank) for(i=0;i<2*N+1;i++) { for(j=0;j<2*N+1;j++) { d[i][j]=sqrt((C_row-i)*(C_row-i)+(C_rank-j)*(C_rank-j)) ; 选中的离子距离中心离子的位置,很简单就是用勾股定理,之前已经设定过中心离子的坐标了 printf("%.4f\t",d[i][j]); d0[cnt]=d[i][j]; 这里把二维的数组映射成一维便于后面数据筛选 cnt++; } printf("\n"); } printf("\n\n\n"); for(i=0;i<=cnt;i++) { flag=1; for(j=0;j<=i-1;j++) 这里是程序难点之一,重复数据的删除 if(dc[j]==d0[i]) { flag=0; break; } if(flag) { dc[cnt_dc]=d0[i]; cnt_dc++; } } for(i=0;i<cnt_dc-1;i++) for(j=i+1;j<cnt_dc;j++) { if(dc[i]>dc[j]) { temp=dc[i]; dc[i]=dc[j]; dc[j]=temp; } } for(i=0;i<MAX;i++) S[i]=0; for(i=0;i<2*N+1;i++) { for(j=0;j<2*N+1;j++) { d[i][j]=sqrt((C_row-i)*(C_row-i)+(C_rank-j)*(C_rank-j)) ; for(l=0;l<cnt_dc;l++) { if(d[i][j]==dc[l]) S[l]++; 根据上面距离分布,统计相同距离时的离子个数,这个在后面的图例有清楚的显示,比较直观 } } } printf("\n\nDistance\tSimilar\n\n\n"); for(i=0;i<cnt_dc;i++) { printf("%8.4f %8d\n",dc[i],S[i]); } } Madelung() { int i,j; for(i=0;i<2*N+1;i++) for(j=0;j<2*N+1;j++) { if(i==C_row&&j==C_rank) continue; 难点之二,中心离子的库伦能贡献忽略,因为算式无意义,会造成计算结果溢出,我当初想了好久 else Madelung_constant+=a[i][j]*D[i][j]/d[i][j]; 以上是马德隆常数的递推公式,你懂得 } } main() { 各种函数和printf使用,作用-----美观,额。。其实是想看一下具体的数值分布 printf("Input the number of the cells on each side: "); scanf("%d",&N); printf("\n\nThe total number of the cells is: %d\n\n",N*N); printf("\n\nShowing the picture of the lattices\n\n\n"); lattice(N); printf("\n\n\n"); printf("\n\nShowing the devotion of each lattice\n\n\n"); Devotion_cell(N); printf("\n\n\nShowing the distribution of the distance of each lattice: \n\n\n"); Distance(N); Madelung(N); printf("\n\n\nThe Madelung constant of all is = %f\n\n",Madelung_constant); printf("\n\n\n Author---------Dounimei\n\t2011/3/30\n"); getch(); return 0; } 一下先给出单个二维晶胞的图像和数据: (才发现豆瓣里不能发图呢,大家自己试一下好了= =|||) 先试下1*1的,以下是对显示的注解: 以上是二维晶体图像,对晶胞贡献分布,对中心离子距离分布,这样很容易想象二维晶体的样子了 由上与中心距离为1的离子有4个,距离为1.414的有4个 这里马德隆常数算出来和书上是一样的,而且更精确。。 同理,可以试一下2*2以上的晶胞,但是5*5以上的VC++显示怎么有问题,数据出现重叠了,希望高人解决。。。
最新讨论 ( 更多 )
- 帮学弟填个问卷🤣🤣 (豆友ujPRwCuM5E)
- 学术讨论|这道题怎么做… (Koi)
- 想组个物理讨论小组有约的吗? (孤勇者)
- 引力是怎么产生的?如果物体会产生引力那么物体中的什么东西... (☘)
- 物理学的进化 (☘)