使用 MatSetValuesStencil 将整行替换为 INSERT_VALUES

Replace whole row using MatSetValuesStencil with INSERT_VALUES

我正在使用 Petsc Ksp 例程。 我使用 MatSetValuesStencil 构建了一个运算符,在每次调用此函数时,我指定一个长度为 5 的行矩阵值。 在某些情况下,我有时需要将一行从 5 长模板完全替换为 3 长模板。 INSERT_VALUES 模式会将两个值保留在未更改的位置还是将它们丢弃为零?

未在函数 MatSetValuesStencil(...) 的参数 idxmidxn 中指定的矩阵元素保持不变,即使使用 INSERT_VALUES 也是如此。

这里有一段从 ksp_ex29 开始的小代码来测试它:

static char help[] = "Does INSERT_VALUES changes the whole row ? No.\n\n";

#include <petscdm.h>
#include <petscdmda.h>
#include <petscksp.h>

extern PetscErrorCode ComputeMatrix42(DM da,Mat jac);
extern PetscErrorCode ComputeMatrix(DM da,Mat jac);

#undef __FUNCT__
#define __FUNCT__ "main"
int main(int argc,char **argv)
{

    DM             da;
    PetscErrorCode ierr;
    Mat matrix;

    PetscInitialize(&argc,&argv,(char*)0,help);

    ierr = DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_PERIODIC, DM_BOUNDARY_PERIODIC,DMDA_STENCIL_STAR,-3,-3,PETSC_DECIDE,PETSC_DECIDE,1,1,0,0,&da);CHKERRQ(ierr);

    DMCreateMatrix(da,&matrix);

    ComputeMatrix(da,matrix);

    PetscPrintf(PETSC_COMM_WORLD,"A matrix of negative terms : \n");
    MatView(matrix, PETSC_VIEWER_STDOUT_WORLD );

    ComputeMatrix42(da,matrix);

    PetscPrintf(PETSC_COMM_WORLD,"The diagonal, i-1 and i+1 are set to 42 : \n");
    MatView(matrix, PETSC_VIEWER_STDOUT_WORLD );

    ierr = DMDestroy(&da);CHKERRQ(ierr);
    ierr = MatDestroy(&matrix);CHKERRQ(ierr);
    ierr = PetscFinalize();

    return 0;
}

#undef __FUNCT__
#define __FUNCT__ "ComputeMatrix"
PetscErrorCode ComputeMatrix(DM da,Mat jac)
{
    PetscErrorCode ierr;
    PetscInt       i,j,mx,my,xm,ym,xs,ys;
    PetscScalar    v[5];
    MatStencil     row, col[5];

    PetscFunctionBeginUser;
    ierr      = DMDAGetInfo(da,0,&mx,&my,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
    ierr      = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr);
    for (j=ys; j<ys+ym; j++) {
        for (i=xs; i<xs+xm; i++) {
            row.i = i; row.j = j;
            v[0] = -1;              col[0].i = i;   col[0].j = j-1;
            v[1] = -1;              col[1].i = i-1; col[1].j = j;
            v[2] = -13; col[2].i = i;   col[2].j = j;
            v[3] = -1;              col[3].i = i+1; col[3].j = j;
            v[4] = -1;              col[4].i = i;   col[4].j = j+1;
            ierr = MatSetValuesStencil(jac,1,&row,5,col,v,INSERT_VALUES);CHKERRQ(ierr);
        }
    }

    ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
    ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);

    PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "ComputeMatrix42"
PetscErrorCode ComputeMatrix42(DM da,Mat jac)
{
    PetscErrorCode ierr;
    PetscInt       i,j,mx,my,xm,ym,xs,ys;
    PetscScalar    v[3];
    MatStencil     row, col[3];

    PetscFunctionBeginUser;
    ierr      = DMDAGetInfo(da,0,&mx,&my,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
    ierr      = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr);
    for (j=ys; j<ys+ym; j++) {
        for (i=xs; i<xs+xm; i++) {
            row.i = i; row.j = j;
            v[0] = 42;              col[0].i = i-1; col[0].j = j;
            v[1] = 42; col[1].i = i;   col[1].j = j;
            v[2] = 42;              col[2].i = i+1; col[2].j = j;
            ierr = MatSetValuesStencil(jac,1,&row,3,col,v,INSERT_VALUES);CHKERRQ(ierr);
        }
    }

    ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
    ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);

    PetscFunctionReturn(0);
}

使用以下 makefile 编译它:

include ${PETSC_DIR}/conf/variables
include ${PETSC_DIR}/conf/rules

main: main.o  chkopts
    -${CLINKER} -o main main.o  ${PETSC_LIB}
    ${RM} main.o

输出:

A matrix of negative terms : 
Mat Object: 1 MPI processes
  type: seqaij
row 0: (0, -13)  (1, -1)  (2, -1)  (3, -1)  (6, -1) 
row 1: (0, -1)  (1, -13)  (2, -1)  (4, -1)  (7, -1) 
row 2: (0, -1)  (1, -1)  (2, -13)  (5, -1)  (8, -1) 
row 3: (0, -1)  (3, -13)  (4, -1)  (5, -1)  (6, -1) 
row 4: (1, -1)  (3, -1)  (4, -13)  (5, -1)  (7, -1) 
row 5: (2, -1)  (3, -1)  (4, -1)  (5, -13)  (8, -1) 
row 6: (0, -1)  (3, -1)  (6, -13)  (7, -1)  (8, -1) 
row 7: (1, -1)  (4, -1)  (6, -1)  (7, -13)  (8, -1) 
row 8: (2, -1)  (5, -1)  (6, -1)  (7, -1)  (8, -13) 
The diagonal, i-1 and i+1 are set to 42 : 
Mat Object: 1 MPI processes
  type: seqaij
row 0: (0, 42)  (1, 42)  (2, 42)  (3, -1)  (6, -1) 
row 1: (0, 42)  (1, 42)  (2, 42)  (4, -1)  (7, -1) 
row 2: (0, 42)  (1, 42)  (2, 42)  (5, -1)  (8, -1) 
row 3: (0, -1)  (3, 42)  (4, 42)  (5, 42)  (6, -1) 
row 4: (1, -1)  (3, 42)  (4, 42)  (5, 42)  (7, -1) 
row 5: (2, -1)  (3, 42)  (4, 42)  (5, 42)  (8, -1) 
row 6: (0, -1)  (3, -1)  (6, 42)  (7, 42)  (8, 42) 
row 7: (1, -1)  (4, -1)  (6, 42)  (7, 42)  (8, 42) 
row 8: (2, -1)  (5, -1)  (6, 42)  (7, 42)  (8, 42)

我正在使用 PETSC 3.5.2。