xref: /petsc/src/mat/tests/ex19.c (revision ebead697dbf761eb322f829370bbe90b3bd93fa3)
1 
2 static char help[] = "Tests reusing MPI parallel matrices and MatGetValues().\n\
3 To test the parallel matrix assembly, this example intentionally lays out\n\
4 the matrix across processors differently from the way it is assembled.\n\
5 This example uses bilinear elements on the unit square.  Input arguments are:\n\
6   -m <size> : problem size\n\n";
7 
8 #include <petscmat.h>
9 
10 int FormElementStiffness(PetscReal H,PetscScalar *Ke)
11 {
12   PetscFunctionBegin;
13   Ke[0]  = H/6.0;    Ke[1]  = -.125*H; Ke[2]  = H/12.0;   Ke[3]  = -.125*H;
14   Ke[4]  = -.125*H;  Ke[5]  = H/6.0;   Ke[6]  = -.125*H;  Ke[7]  = H/12.0;
15   Ke[8]  = H/12.0;   Ke[9]  = -.125*H; Ke[10] = H/6.0;    Ke[11] = -.125*H;
16   Ke[12] = -.125*H;  Ke[13] = H/12.0;  Ke[14] = -.125*H;  Ke[15] = H/6.0;
17   PetscFunctionReturn(0);
18 }
19 
20 int main(int argc,char **args)
21 {
22   Mat            C;
23   Vec            u,b;
24   PetscMPIInt    size,rank;
25   PetscInt       i,m = 5,N,start,end,M,idx[4];
26   PetscInt       j,nrsub,ncsub,*rsub,*csub,mystart,myend;
27   PetscBool      flg;
28   PetscScalar    one = 1.0,Ke[16],*vals;
29   PetscReal      h,norm;
30 
31   PetscFunctionBeginUser;
32   PetscCall(PetscInitialize(&argc,&args,(char*)0,help));
33   PetscCall(PetscOptionsGetInt(NULL,NULL,"-m",&m,NULL));
34 
35   N    = (m+1)*(m+1); /* dimension of matrix */
36   M    = m*m;      /* number of elements */
37   h    = 1.0/m;    /* mesh width */
38   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
39   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size));
40 
41   /* Create stiffness matrix */
42   PetscCall(MatCreate(PETSC_COMM_WORLD,&C));
43   PetscCall(MatSetSizes(C,PETSC_DECIDE,PETSC_DECIDE,N,N));
44   PetscCall(MatSetFromOptions(C));
45   PetscCall(MatSetUp(C));
46 
47   start = rank*(M/size) + ((M%size) < rank ? (M%size) : rank);
48   end   = start + M/size + ((M%size) > rank);
49 
50   /* Form the element stiffness for the Laplacian */
51   PetscCall(FormElementStiffness(h*h,Ke));
52   for (i=start; i<end; i++) {
53     /* location of lower left corner of element */
54     /* node numbers for the four corners of element */
55     idx[0] = (m+1)*(i/m) + (i % m);
56     idx[1] = idx[0]+1; idx[2] = idx[1] + m + 1; idx[3] = idx[2] - 1;
57     PetscCall(MatSetValues(C,4,idx,4,idx,Ke,ADD_VALUES));
58   }
59   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
60   PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
61 
62   /* Assemble the matrix again */
63   PetscCall(MatZeroEntries(C));
64 
65   for (i=start; i<end; i++) {
66     /* location of lower left corner of element */
67     /* node numbers for the four corners of element */
68     idx[0] = (m+1)*(i/m) + (i % m);
69     idx[1] = idx[0]+1; idx[2] = idx[1] + m + 1; idx[3] = idx[2] - 1;
70     PetscCall(MatSetValues(C,4,idx,4,idx,Ke,ADD_VALUES));
71   }
72   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
73   PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
74 
75   /* Create test vectors */
76   PetscCall(VecCreate(PETSC_COMM_WORLD,&u));
77   PetscCall(VecSetSizes(u,PETSC_DECIDE,N));
78   PetscCall(VecSetFromOptions(u));
79   PetscCall(VecDuplicate(u,&b));
80   PetscCall(VecSet(u,one));
81 
82   /* Check error */
83   PetscCall(MatMult(C,u,b));
84   PetscCall(VecNorm(b,NORM_2,&norm));
85   if (norm > PETSC_SQRT_MACHINE_EPSILON) {
86     PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Norm of error b %g should be near 0\n",(double)norm));
87   }
88 
89   /* Now test MatGetValues() */
90   PetscCall(PetscOptionsHasName(NULL,NULL,"-get_values",&flg));
91   if (flg) {
92     PetscCall(MatGetOwnershipRange(C,&mystart,&myend));
93     nrsub = myend - mystart; ncsub = 4;
94     PetscCall(PetscMalloc1(nrsub*ncsub,&vals));
95     PetscCall(PetscMalloc1(nrsub,&rsub));
96     PetscCall(PetscMalloc1(ncsub,&csub));
97     for (i=myend-1; i>=mystart; i--) rsub[myend-i-1] = i;
98     for (i=0; i<ncsub; i++) csub[i] = 2*(ncsub-i) + mystart;
99     PetscCall(MatGetValues(C,nrsub,rsub,ncsub,csub,vals));
100     PetscCall(MatView(C,PETSC_VIEWER_STDOUT_WORLD));
101     PetscCall(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));
102     for (i=0; i<nrsub; i++) {
103       for (j=0; j<ncsub; j++) {
104         if (PetscImaginaryPart(vals[i*ncsub+j]) != 0.0) {
105           PetscCall(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])));
106         } else {
107           PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD,"  C[%" PetscInt_FMT ", %" PetscInt_FMT "] = %g\n",rsub[i],csub[j],(double)PetscRealPart(vals[i*ncsub+j])));
108         }
109       }
110     }
111     PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT));
112     PetscCall(PetscFree(rsub));
113     PetscCall(PetscFree(csub));
114     PetscCall(PetscFree(vals));
115   }
116 
117   /* Free data structures */
118   PetscCall(VecDestroy(&u));
119   PetscCall(VecDestroy(&b));
120   PetscCall(MatDestroy(&C));
121   PetscCall(PetscFinalize());
122   return 0;
123 }
124 
125 /*TEST
126 
127    test:
128       nsize: 4
129 
130 TEST*/
131