xref: /petsc/src/mat/tests/ex19.c (revision b122ec5aa1bd4469eb4e0673542fb7de3f411254)
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