xref: /petsc/src/mat/tests/ex19.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
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   PetscErrorCode ierr;
25c4762a1bSJed Brown   PetscMPIInt    size,rank;
26c4762a1bSJed Brown   PetscInt       i,m = 5,N,start,end,M,idx[4];
27c4762a1bSJed Brown   PetscInt       j,nrsub,ncsub,*rsub,*csub,mystart,myend;
28c4762a1bSJed Brown   PetscBool      flg;
29c4762a1bSJed Brown   PetscScalar    one = 1.0,Ke[16],*vals;
30c4762a1bSJed Brown   PetscReal      h,norm;
31c4762a1bSJed Brown 
32c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&args,(char*)0,help);if (ierr) return ierr;
33*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetInt(NULL,NULL,"-m",&m,NULL));
34c4762a1bSJed Brown 
35c4762a1bSJed Brown   N    = (m+1)*(m+1); /* dimension of matrix */
36c4762a1bSJed Brown   M    = m*m;      /* number of elements */
37c4762a1bSJed Brown   h    = 1.0/m;    /* mesh width */
38*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
39*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size));
40c4762a1bSJed Brown 
41c4762a1bSJed Brown   /* Create stiffness matrix */
42*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(PETSC_COMM_WORLD,&C));
43*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(C,PETSC_DECIDE,PETSC_DECIDE,N,N));
44*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetFromOptions(C));
45*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetUp(C));
46c4762a1bSJed Brown 
47c4762a1bSJed Brown   start = rank*(M/size) + ((M%size) < rank ? (M%size) : rank);
48c4762a1bSJed Brown   end   = start + M/size + ((M%size) > rank);
49c4762a1bSJed Brown 
50c4762a1bSJed Brown   /* Form the element stiffness for the Laplacian */
51*5f80ce2aSJacob Faibussowitsch   CHKERRQ(FormElementStiffness(h*h,Ke));
52c4762a1bSJed Brown   for (i=start; i<end; i++) {
53c4762a1bSJed Brown     /* location of lower left corner of element */
54c4762a1bSJed Brown     /* node numbers for the four corners of element */
55c4762a1bSJed Brown     idx[0] = (m+1)*(i/m) + (i % m);
56c4762a1bSJed Brown     idx[1] = idx[0]+1; idx[2] = idx[1] + m + 1; idx[3] = idx[2] - 1;
57*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValues(C,4,idx,4,idx,Ke,ADD_VALUES));
58c4762a1bSJed Brown   }
59*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
60*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
61c4762a1bSJed Brown 
62c4762a1bSJed Brown   /* Assemble the matrix again */
63*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatZeroEntries(C));
64c4762a1bSJed Brown 
65c4762a1bSJed Brown   for (i=start; i<end; i++) {
66c4762a1bSJed Brown     /* location of lower left corner of element */
67c4762a1bSJed Brown     /* node numbers for the four corners of element */
68c4762a1bSJed Brown     idx[0] = (m+1)*(i/m) + (i % m);
69c4762a1bSJed Brown     idx[1] = idx[0]+1; idx[2] = idx[1] + m + 1; idx[3] = idx[2] - 1;
70*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValues(C,4,idx,4,idx,Ke,ADD_VALUES));
71c4762a1bSJed Brown   }
72*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
73*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
74c4762a1bSJed Brown 
75c4762a1bSJed Brown   /* Create test vectors */
76*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_WORLD,&u));
77*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(u,PETSC_DECIDE,N));
78*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetFromOptions(u));
79*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDuplicate(u,&b));
80*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(u,one));
81c4762a1bSJed Brown 
82c4762a1bSJed Brown   /* Check error */
83*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMult(C,u,b));
84*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecNorm(b,NORM_2,&norm));
85c4762a1bSJed Brown   if (norm > PETSC_SQRT_MACHINE_EPSILON) {
86*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"Norm of error b %g should be near 0\n",(double)norm));
87c4762a1bSJed Brown   }
88c4762a1bSJed Brown 
89c4762a1bSJed Brown   /* Now test MatGetValues() */
90*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHasName(NULL,NULL,"-get_values",&flg));
91c4762a1bSJed Brown   if (flg) {
92*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetOwnershipRange(C,&mystart,&myend));
93c4762a1bSJed Brown     nrsub = myend - mystart; ncsub = 4;
94*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nrsub*ncsub,&vals));
95*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nrsub,&rsub));
96*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(ncsub,&csub));
97c4762a1bSJed Brown     for (i=myend-1; i>=mystart; i--) rsub[myend-i-1] = i;
98c4762a1bSJed Brown     for (i=0; i<ncsub; i++) csub[i] = 2*(ncsub-i) + mystart;
99*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetValues(C,nrsub,rsub,ncsub,csub,vals));
100*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatView(C,PETSC_VIEWER_STDOUT_WORLD));
101*5f80ce2aSJacob 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));
102c4762a1bSJed Brown     for (i=0; i<nrsub; i++) {
103c4762a1bSJed Brown       for (j=0; j<ncsub; j++) {
104c4762a1bSJed Brown         if (PetscImaginaryPart(vals[i*ncsub+j]) != 0.0) {
105*5f80ce2aSJacob 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])));
106c4762a1bSJed Brown         } else {
107*5f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSynchronizedPrintf(PETSC_COMM_WORLD,"  C[%" PetscInt_FMT ", %" PetscInt_FMT "] = %g\n",rsub[i],csub[j],(double)PetscRealPart(vals[i*ncsub+j])));
108c4762a1bSJed Brown         }
109c4762a1bSJed Brown       }
110c4762a1bSJed Brown     }
111*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT));
112*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(rsub));
113*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(csub));
114*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(vals));
115c4762a1bSJed Brown   }
116c4762a1bSJed Brown 
117c4762a1bSJed Brown   /* Free data structures */
118*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&u));
119*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&b));
120*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&C));
121c4762a1bSJed Brown   ierr = PetscFinalize();
122c4762a1bSJed Brown   return ierr;
123c4762a1bSJed Brown }
124c4762a1bSJed Brown 
125c4762a1bSJed Brown /*TEST
126c4762a1bSJed Brown 
127c4762a1bSJed Brown    test:
128c4762a1bSJed Brown       nsize: 4
129c4762a1bSJed Brown 
130c4762a1bSJed Brown TEST*/
131