我正在查看DMDAVecGetArray的文档,很惊讶它可以创建一个普通的普通 C 数组,其索引以某种方式从istart到istart + size - 1,而不是从 0 到size - 1,或者一个多维数组(也是一个普通的 C 数组),其索引范围from istartto istart + isize - 1, jstarttojstart + jsize - 1等。我不确定它是如何工作的,所以我查看了代码,发现 DMDAVecGetArray 在幕后使用函数 VecGetArray1d、VecGetArray2d 等来创建这些奇怪的索引数组。VecGetArray1d 的代码如下所示:
PetscErrorCode VecGetArray1d(Vec x,PetscInt m,PetscInt mstart,PetscScalar *a[])
{
PetscInt N;
VecGetLocalSize(x,&N);
if (m != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local array size %D does not match 1d array dimensions %D",N,m);
VecGetArray(x,a);
*a -= mstart;
return(0);
}
至少从表面上看,这看起来类似于在 C 中执行 1 索引数组的技巧,即
int realarray[10];
int *array = &realarray[-1];
除了a上面 PETSc 代码中的指针直接递减,而不是像array上面那样有第二个指针变量。
我在看我认为我在看的东西吗?我很难相信像 PETSc 这样使用良好的库代码会依赖未定义的行为,所以我不确定 PETSc 代码是否真的非法。
究竟发生了什么?