2016-08-05 3 views
2

최근에 PETSc를 배우기 시작하면서 간단한 작업을 수행하는 동안 문제가 발생했습니다. 이 코드의 문제점 :PETSC DMDA vec 값이 wrang에 할당되었습니다.

static char help[] = "Test 2d DMDAs Vecs.\n\n"; 
#include <petscdm.h> 
#include <petscdmda.h> 
#include <petscsys.h> 
PetscReal process_value(int rank, int i) { 
    return i*PetscPowScalar(10,rank*2); 
} 
int main(int argc,char **argv) { 
    PetscErrorCode ierr; 
    PetscMPIInt  rank; 
    PetscInt   M = -5,N = -3; 
    DM    da; 
    Vec    local,global; 
    ierr = PetscInitialize(&argc,&argv,(char*)0,help);CHKERRQ(ierr); 
    ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); 
    ierr = DMDACreate2d(PETSC_COMM_WORLD , DM_BOUNDARY_NONE , DM_BOUNDARY_NONE 
    , DMDA_STENCIL_BOX , M , N , PETSC_DECIDE, PETSC_DECIDE 
    , 1 , 1 , NULL , NULL , &da); CHKERRQ(ierr); 
    ierr = DMCreateGlobalVector(da,&global);CHKERRQ(ierr); 
    ierr = DMCreateLocalVector(da,&local);CHKERRQ(ierr); 
    { 
     PetscInt  v,i, j, xm, ym, xs, ys; 
     PetscScalar **array; 
     ierr = DMDAGetCorners(da, &xs, &ys, 0, &xm, &ym, 0); CHKERRQ(ierr); 
     PetscSynchronizedPrintf(PETSC_COMM_WORLD,"%d:xs=%d\txm=%d\tys=%d\tym=%d\n",rank,xs,xm,ys,ym); 
     PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT); 
     ierr = DMDAVecGetArray(da, global, &array); CHKERRQ(ierr); 
    v=0; 
     for (j = ys; j < ys + ym; j++) { 
     for (i = xs; i < xs + xm; i++) { 
      array[j][i] = process_value(rank,v+=1); 
     } 
     } 
    ierr = DMDAVecRestoreArray(da, global, &array); CHKERRQ(ierr); 
    } 
    ierr = VecView(global,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 
    ierr = VecDestroy(&local);CHKERRQ(ierr); 
    ierr = VecDestroy(&global);CHKERRQ(ierr); 
    ierr = DMDestroy(&da);CHKERRQ(ierr); 
    ierr = PetscFinalize(); 
    return 0; 
} 

프로세스 순위별로 표시된 수량으로 작은 배열을 채 웁니다. 성공적으로 컴파일 한 후이를 연결은 다음과 같은 결과를 제공합니다

> mpiexec -n 2 ./problem 
0:xs=0 xm=3 ys=0 ym=3 
1:xs=3 xm=2 ys=0 ym=3 
Vec Object: 2 MPI processes 
    type: mpi 
Vec Object:Vec_0x84000004_0 2 MPI processes 
    type: mpi 
Process [0] 
1. 
2. 
3. 
100. 
200. 
4. 
5. 
6. 
300. 
Process [1] 
400. 
7. 
8. 
9. 
500. 
600. 
> 

VecView 프로세스가 다른 프로세스에 속하는 곳으로 쓴 것을 알 수있다. 오류는 어디에 있습니까? DMDAVecGetArray/DMDAVecRestoreArray가 잘못된 배열을 제공하거나 VecView가 DM 객체에서 얻은 Vec를보기에 적합하지 않습니까?

답변

1

DMDAVecGetArray()DMDAVecRestoreArray()은 정상적으로 작동합니다. 사실 몇 년 전에 mailing list of petsc에 설명 된 VecView()의 기능을 처리하고 있습니다.

마찬가지로, VecView()은 자연 정렬을 사용하여 DMDA에서 벡터를 인쇄합니다.

proc0 proc1 
1 2 | 3 4 
5 6 | 7 8 
___________ 
9 10 | 11 12 
13 14 | 15 16 
proc2 proc3 

자연 순서와 Petsc의 순서 차이 구조화 된 격자에 대해 섹션 2.5에서 documentation of Petsc 밑줄된다. 여기 Petsc의 순서는 모습입니다 같은 : 스레드 VecView doesn't work properly with DA global vectors에 신호로

proc0 proc1 
1 2 | 5 6 
3 4 | 7 8 
___________ 
9 10 | 13 14 
11 12 | 15 16 
proc2 proc3 

, 그것을 사용하여 Petsc의 순서를 사용하여 벡터를 인쇄하는 것은 여전히 ​​가능하다 :

PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_NATIVE); 
VecView(global,PETSC_VIEWER_STDOUT_WORLD); 
PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD); 

가의가 보자 Petsc의 출처를 자세히보고 어떻게 작동하는지 확인하십시오. DMDS 벡터에 대한 VecView() 연산은 DMCreateGlobalVector_DA() 함수가 호출 될 때 오버로드됩니다 (dadist.c 참조). 새 메서드는 VecView_MPI_DA()이고, gr2.c입니다. 당연히 함수 DMDACreateNaturalVector()을 호출하고 나중에 기본 벡터 VecView()을 사용하여 자연 벡터를 인쇄합니다. 형식이 PETSC_VIEWER_NATIVE 인 경우 vector interface*vec->ops->viewnative 작업을 호출하며 이는 VecView() 함수 VecView_MPI_ASCII()pdvec.c에 지정합니다. 이것은 DMDA 벡터에 대한 VecView의 이상한 (하지만 실용적인!) 동작을 설명합니다.

당신이 자연 순서를 유지하려면, 당신은 사용하여 인쇄되는 의미없는 Process[0]...Process[3] revome 수 있습니다

PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_COMMON);