根据ising模型,我被问到的问题是使用指针扫描2D数组,并使用周期性边界条件识别4个最近邻居。
到目前为止,这是我的代码;
#include <stdio.h>
#include <stdlib.h>
int Lattice_Size=100;
main()
{
int *ptr, *mat;
int i, j ;
int spin_up = 1;
int spin_down = -1;
mat = (int *)malloc(sizeof(int)*Lattice_Size*Lattice_Size); // dynamic memory for Lattice
ptr = mat;
for (i=0; i<Lattice_Size; i++)
{
for (j=0; j<Lattice_Size; j++)
{
*ptr++=spin_up; // initilizing to parallel spins
}
}
free(mat);
mat=NULL;
}
我现在很难过如何扫过格子并找到最近的邻居。我在数学上知道如何描述边界条件,但我不知道如何编码它。
答案 0 :(得分:3)
当您将2D数据存储在N * N的线性(本质)数组中时,您可以找到带有
的元素(i,j)element(i,j) = array[j + N * i];
“周期性边界条件”(意思是 - 如果你从底部掉下来,你会从右边掉下来,你从右边重新进入)可以这样描述:
element( i - 1, j ) = ( i == 0 ) ? array[ j + N * (N - 1) ] : array[ j + N * i ];
element( i + 1, j ) = ( i == N - 1 ) ? array[ j ] : array[ j + N * i ];
element( i, j - 1 ) = ( j == 0 ) ? array[ N - 1 + N * i] : array[ j + N * i ];
element( i, j + 1 ) = ( j == N - 1 ) ? array[ N * i ] : array[ j + N * i ];
检查我的数学,但我很确定这是正确的。
PS在个人笔记中:我写的第一个程序(1975年,使用ALGOL 68)需要我使用发现这个技巧(退出边缘并重新出现在另一边)制作一个魔方。感谢这次记忆之旅。
编辑我决定再编写一些函数 - 您将看到这将如何使您的主代码更具可读性。我添加了评论以帮助您理解。
include <stdio.h>
#include <stdlib.h>
int Lattice_Size=10;
// some code to handle a matrix with wrapping at the edges
// as might be useful in lattice spin analysis
// note - assumption is that grid is same size in i and j direction
// code needs minor modifcation if grid is non-square
int getElement(int *p, int i, int j, int n) {
// find element with wrapping
i = (i + n) % n;
j = (j + n) % n;
return p[ i * n + j ];
}
int setElement(int *p, int i, int j, int n, int val) {
// set the i, j element to value val
// if the element points "off the edge"
// this code puts it back in the range [0, n-1]
// for both i and j
// assuming i, j are not "very negative" (i.e. i+n is always > 0)
// this will be the case when "off the edge" is by a single step
// could write i = ( i < 0 ) ? (i % n) + n : i % n;
// if this has to work for any values of i (ditto j)
// but that is slower
i = (i + n) % n; // coerce in range: takes care of wrapping
j = (j + n) % n;
p[ i * n + j ] = val;
return val; // could make this void function and not return anything
}
void setNeighbors(int *p, int i, int j, int n, int val) {
// set 4 nearest neighbors to value val
// with wrapping (if you fall off the left edge
// you re-appear on the right)
setElement( p, i + 1, j , n, val );
setElement( p, i - 1, j , n, val );
setElement( p, i , j + 1, n, val );
setElement( p, i , j - 1, n, val );
return; // return nothing: void function
}
int* getNeighbors(int *p, int i, int j, int n, int dest[4]) {
// return the 4 neighbors (with wrapping)
// in space allocated in dest[4]
// order: N, E, S, W
dest[0] = getElement( p, i - 1, j , n );
dest[1] = getElement( p, i , j + 1, n );
dest[2] = getElement( p, i + 1, j , n );
dest[3] = getElement( p, i , j - 1, n );
return dest; // return pointer to neighbor elements (same as input pointer)
}
void printMatrix(int* mat, int n) {
// print a simple square matrix
// with fixed width formatting
// and sign appended
int i, j;
for(i = 0; i < n; i++) {
for(j = 0; j < n; j++) {
printf("%+2d ", getElement(mat, i, j, n));
}
printf("\n");
}
}
main()
{
int *ptr, *mat;
int i, j ;
int spin_up = 1;
int spin_down = -1;
int neighbors[4];
// allocate memory for the spin matrix:
mat = (int *)malloc(sizeof(int)*Lattice_Size*Lattice_Size);
ptr = mat; // copy pointer
for (i=0; i<Lattice_Size; i++)
{
for (j=0; j<Lattice_Size; j++)
{
*ptr++=spin_up; // initializing to parallel spins
// this could be done with setElement(mat, i, j, Lattice_Size);
// for greater readability
}
}
// change a few elements to different values:
setElement(mat, 2, 3, Lattice_Size, 2);
setElement(mat, 5, 0, Lattice_Size, 3);
// set the neighbors of an element on the edge:
setNeighbors(mat, 5, 0, Lattice_Size, -1);
// print the result
printMatrix(mat, Lattice_Size);
// read back the 4 neighbors of an element on the edge:
getNeighbors(mat, 4, 0, Lattice_Size, neighbors);
// print the result:
printf("neighbors of (4,0):\n");
for (i = 0; i < 4; i++) printf("%+2d ", neighbors[i]);
printf("\n");
// clean up:
free(mat);
mat=NULL;
}
上述示例输出:
+1 +1 +1 +1 +1 +1 +1 +1 +1 +1
+1 +1 +1 +1 +1 +1 +1 +1 +1 +1
+1 +1 +1 +2 +1 +1 +1 +1 +1 +1
+1 +1 +1 +1 +1 +1 +1 +1 +1 +1
-1 +1 +1 +1 +1 +1 +1 +1 +1 +1
+3 -1 +1 +1 +1 +1 +1 +1 +1 -1
-1 +1 +1 +1 +1 +1 +1 +1 +1 +1
+1 +1 +1 +1 +1 +1 +1 +1 +1 +1
+1 +1 +1 +1 +1 +1 +1 +1 +1 +1
+1 +1 +1 +1 +1 +1 +1 +1 +1 +1
neighbors of (4,0):
+1 +1 +3 +1
如您所见,元素(2,3)(两个向下,三个跨越)确实设置为+2; element(5,0)设置为+3;元素(4,0)的邻居是(从顶部开始顺时针)1,1,3,1(这是右边缘的值......)
玩它并让我知道是否仍然不清楚。