1c4762a1bSJed Brown 2c4762a1bSJed Brown static char help[] = "Tests reusing MPI parallel matrices and MatGetValues().\n\ 3c4762a1bSJed Brown To test the parallel matrix assembly, this example intentionally lays out\n\ 4c4762a1bSJed Brown the matrix across processors differently from the way it is assembled.\n\ 5c4762a1bSJed Brown This example uses bilinear elements on the unit square. Input arguments are:\n\ 6c4762a1bSJed Brown -m <size> : problem size\n\n"; 7c4762a1bSJed Brown 8c4762a1bSJed Brown #include <petscmat.h> 9c4762a1bSJed Brown 10c4762a1bSJed Brown int FormElementStiffness(PetscReal H,PetscScalar *Ke) 11c4762a1bSJed Brown { 12c4762a1bSJed Brown PetscFunctionBegin; 13c4762a1bSJed Brown Ke[0] = H/6.0; Ke[1] = -.125*H; Ke[2] = H/12.0; Ke[3] = -.125*H; 14c4762a1bSJed Brown Ke[4] = -.125*H; Ke[5] = H/6.0; Ke[6] = -.125*H; Ke[7] = H/12.0; 15c4762a1bSJed Brown Ke[8] = H/12.0; Ke[9] = -.125*H; Ke[10] = H/6.0; Ke[11] = -.125*H; 16c4762a1bSJed Brown Ke[12] = -.125*H; Ke[13] = H/12.0; Ke[14] = -.125*H; Ke[15] = H/6.0; 17c4762a1bSJed Brown PetscFunctionReturn(0); 18c4762a1bSJed Brown } 19c4762a1bSJed Brown 20c4762a1bSJed Brown int main(int argc,char **args) 21c4762a1bSJed Brown { 22c4762a1bSJed Brown Mat C; 23c4762a1bSJed Brown Vec u,b; 24c4762a1bSJed Brown PetscMPIInt size,rank; 25c4762a1bSJed Brown PetscInt i,m = 5,N,start,end,M,idx[4]; 26c4762a1bSJed Brown PetscInt j,nrsub,ncsub,*rsub,*csub,mystart,myend; 27c4762a1bSJed Brown PetscBool flg; 28c4762a1bSJed Brown PetscScalar one = 1.0,Ke[16],*vals; 29c4762a1bSJed Brown PetscReal h,norm; 30c4762a1bSJed Brown 31*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscInitialize(&argc,&args,(char*)0,help)); 325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL,NULL,"-m",&m,NULL)); 33c4762a1bSJed Brown 34c4762a1bSJed Brown N = (m+1)*(m+1); /* dimension of matrix */ 35c4762a1bSJed Brown M = m*m; /* number of elements */ 36c4762a1bSJed Brown h = 1.0/m; /* mesh width */ 375f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank)); 385f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size)); 39c4762a1bSJed Brown 40c4762a1bSJed Brown /* Create stiffness matrix */ 415f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PETSC_COMM_WORLD,&C)); 425f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(C,PETSC_DECIDE,PETSC_DECIDE,N,N)); 435f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetFromOptions(C)); 445f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetUp(C)); 45c4762a1bSJed Brown 46c4762a1bSJed Brown start = rank*(M/size) + ((M%size) < rank ? (M%size) : rank); 47c4762a1bSJed Brown end = start + M/size + ((M%size) > rank); 48c4762a1bSJed Brown 49c4762a1bSJed Brown /* Form the element stiffness for the Laplacian */ 505f80ce2aSJacob Faibussowitsch CHKERRQ(FormElementStiffness(h*h,Ke)); 51c4762a1bSJed Brown for (i=start; i<end; i++) { 52c4762a1bSJed Brown /* location of lower left corner of element */ 53c4762a1bSJed Brown /* node numbers for the four corners of element */ 54c4762a1bSJed Brown idx[0] = (m+1)*(i/m) + (i % m); 55c4762a1bSJed Brown idx[1] = idx[0]+1; idx[2] = idx[1] + m + 1; idx[3] = idx[2] - 1; 565f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(C,4,idx,4,idx,Ke,ADD_VALUES)); 57c4762a1bSJed Brown } 585f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY)); 595f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY)); 60c4762a1bSJed Brown 61c4762a1bSJed Brown /* Assemble the matrix again */ 625f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroEntries(C)); 63c4762a1bSJed Brown 64c4762a1bSJed Brown for (i=start; i<end; i++) { 65c4762a1bSJed Brown /* location of lower left corner of element */ 66c4762a1bSJed Brown /* node numbers for the four corners of element */ 67c4762a1bSJed Brown idx[0] = (m+1)*(i/m) + (i % m); 68c4762a1bSJed Brown idx[1] = idx[0]+1; idx[2] = idx[1] + m + 1; idx[3] = idx[2] - 1; 695f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(C,4,idx,4,idx,Ke,ADD_VALUES)); 70c4762a1bSJed Brown } 715f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY)); 725f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY)); 73c4762a1bSJed Brown 74c4762a1bSJed Brown /* Create test vectors */ 755f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_WORLD,&u)); 765f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(u,PETSC_DECIDE,N)); 775f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetFromOptions(u)); 785f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(u,&b)); 795f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(u,one)); 80c4762a1bSJed Brown 81c4762a1bSJed Brown /* Check error */ 825f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(C,u,b)); 835f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(b,NORM_2,&norm)); 84c4762a1bSJed Brown if (norm > PETSC_SQRT_MACHINE_EPSILON) { 855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"Norm of error b %g should be near 0\n",(double)norm)); 86c4762a1bSJed Brown } 87c4762a1bSJed Brown 88c4762a1bSJed Brown /* Now test MatGetValues() */ 895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(NULL,NULL,"-get_values",&flg)); 90c4762a1bSJed Brown if (flg) { 915f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(C,&mystart,&myend)); 92c4762a1bSJed Brown nrsub = myend - mystart; ncsub = 4; 935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nrsub*ncsub,&vals)); 945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nrsub,&rsub)); 955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(ncsub,&csub)); 96c4762a1bSJed Brown for (i=myend-1; i>=mystart; i--) rsub[myend-i-1] = i; 97c4762a1bSJed Brown for (i=0; i<ncsub; i++) csub[i] = 2*(ncsub-i) + mystart; 985f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetValues(C,nrsub,rsub,ncsub,csub,vals)); 995f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(C,PETSC_VIEWER_STDOUT_WORLD)); 1005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(PETSC_COMM_WORLD,"processor number %d: start=%" PetscInt_FMT ", end=%" PetscInt_FMT ", mystart=%" PetscInt_FMT ", myend=%" PetscInt_FMT "\n",rank,start,end,mystart,myend)); 101c4762a1bSJed Brown for (i=0; i<nrsub; i++) { 102c4762a1bSJed Brown for (j=0; j<ncsub; j++) { 103c4762a1bSJed Brown if (PetscImaginaryPart(vals[i*ncsub+j]) != 0.0) { 1045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(PETSC_COMM_WORLD," C[%" PetscInt_FMT ", %" PetscInt_FMT "] = %g + %g i\n",rsub[i],csub[j],(double)PetscRealPart(vals[i*ncsub+j]),(double)PetscImaginaryPart(vals[i*ncsub+j]))); 105c4762a1bSJed Brown } else { 1065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(PETSC_COMM_WORLD," C[%" PetscInt_FMT ", %" PetscInt_FMT "] = %g\n",rsub[i],csub[j],(double)PetscRealPart(vals[i*ncsub+j]))); 107c4762a1bSJed Brown } 108c4762a1bSJed Brown } 109c4762a1bSJed Brown } 1105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT)); 1115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(rsub)); 1125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(csub)); 1135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(vals)); 114c4762a1bSJed Brown } 115c4762a1bSJed Brown 116c4762a1bSJed Brown /* Free data structures */ 1175f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&u)); 1185f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&b)); 1195f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&C)); 120*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscFinalize()); 121*b122ec5aSJacob Faibussowitsch return 0; 122c4762a1bSJed Brown } 123c4762a1bSJed Brown 124c4762a1bSJed Brown /*TEST 125c4762a1bSJed Brown 126c4762a1bSJed Brown test: 127c4762a1bSJed Brown nsize: 4 128c4762a1bSJed Brown 129c4762a1bSJed Brown TEST*/ 130