使用带有边界条件的指针扫描2d数组 [英] Sweeping through a 2d arrays using pointers with boundary conditions

查看:69
本文介绍了使用带有边界条件的指针扫描2d数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

就ising模型而言,我曾被问到的问题是使用指针扫过2D数组,并确定4个最近的邻居,它们具有周期性边界条件.

The question I have been asked, in terms of the ising model, is to sweep through a 2D array using pointers, and identify the 4 nearest neighbours, with periodic boundary conditions.

到目前为止,这是我的代码;

This is my code so far;

#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; 

}

我现在很困惑如何扫过格子并找到最近的邻居.我在数学上知道如何描述边界条件,但是我不知道如何编写边界条件.

I am stumped now as to how to sweep through the lattice and find the nearest neighbours. I know mathematically how to describe the boundary conditions, but I do not know how to code it.

推荐答案

当将2D数据存储在N * N的线性(本质上)数组中时,您可以使用

When you store 2D data in a linear (essentially) array of N*N, you can find element (i,j) with

element(i,j) = array[j + N * i];

周期边界条件"(意思是-如果从底部跌落到顶部,而如果从左侧跌落则从右边重新输入):

The "periodic boundary condition" (meaning - if you fall off the bottom you go to the top, and if you fall off the left you re-enter from the right) can be described thus:

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 ];

检查我的数学,但我确定这是正确的.

Check my math, but I'm pretty sure that's right.

个人笔记上的PS:我写过的第一个程序(在1975年,使用ALGOL 68)需要我使用Discover)这个技巧(掉线并重新出现在另一面)制作一个魔术方块.感谢您的这次访问.

PS on a personal note: the very first program I ever wrote (in 1975, using ALGOL 68) needed me to use discover) exactly this trick (drop off the edge and re-appear at the other side) to make a magic square. Thanks for this trip down memory lane.

编辑我决定再写一些功能-您将看到它如何使您的主代码更具可读性.我添加了评论以帮助您理解.

EDIT I decided to write a few more functions - you will see how this will make your main code more readable. I have added comments to help in your understanding.

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;元素(5,0)设置为+3;并且元素(4,0)的相邻元素是(从顶部顺时针方向)1、1、3、1(这是从右边缘开始的值……)

As you can see, element (2,3) (two down, three across) is indeed set to +2; element (5, 0) is set to +3; and the neighbors of element (4,0) are (clockwise from the top) 1, 1, 3, 1 (that's the value from the right hand edge…)

试玩一下,让我知道是否还有不清楚的地方.

Play with it and let me know if anything is still not clear.

这篇关于使用带有边界条件的指针扫描2d数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆