xref: /petsc/src/vec/vec/tutorials/ex9.c (revision c3e4dd79e17d3f0a51a524340fae4661630fd09e)
1 
2 static char help[] = "Demonstrates use of VecCreateGhost().\n\n";
3 
4 /*
5    Description: Ghost padding is one way to handle local calculations that
6       involve values from other processors. VecCreateGhost() provides
7       a way to create vectors with extra room at the end of the vector
8       array to contain the needed ghost values from other processors,
9       vector computations are otherwise unaffected.
10 */
11 
12 /*
13   Include "petscvec.h" so that we can use vectors.  Note that this file
14   automatically includes:
15      petscsys.h       - base PETSc routines   petscis.h     - index sets
16      petscviewer.h - viewers
17 */
18 #include <petscvec.h>
19 
20 int main(int argc,char **argv)
21 {
22   PetscMPIInt    rank,size;
23   PetscInt       nlocal = 6,nghost = 2,ifrom[2],i,rstart,rend;
24   PetscBool      flg,flg2,flg3;
25   PetscScalar    value,*array,*tarray=0;
26   Vec            lx,gx,gxs;
27 
28   PetscCall(PetscInitialize(&argc,&argv,(char*)0,help));
29   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
30   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size));
31   PetscCheck(size == 2,PETSC_COMM_WORLD,PETSC_ERR_WRONG_MPI_SIZE,"Must run example with two processors");
32 
33   /*
34      Construct a two dimensional graph connecting nlocal degrees of
35      freedom per processor. From this we will generate the global
36      indices of needed ghost values
37 
38      For simplicity we generate the entire graph on each processor:
39      in real application the graph would stored in parallel, but this
40      example is only to demonstrate the management of ghost padding
41      with VecCreateGhost().
42 
43      In this example we consider the vector as representing
44      degrees of freedom in a one dimensional grid with periodic
45      boundary conditions.
46 
47         ----Processor  1---------  ----Processor 2 --------
48          0    1   2   3   4    5    6    7   8   9   10   11
49                                |----|
50          |-------------------------------------------------|
51 
52   */
53 
54   if (rank == 0) {
55     ifrom[0] = 11; ifrom[1] = 6;
56   } else {
57     ifrom[0] = 0;  ifrom[1] = 5;
58   }
59 
60   /*
61      Create the vector with two slots for ghost points. Note that both
62      the local vector (lx) and the global vector (gx) share the same
63      array for storing vector values.
64   */
65   PetscCall(PetscOptionsHasName(NULL,NULL,"-allocate",&flg));
66   PetscCall(PetscOptionsHasName(NULL,NULL,"-vecmpisetghost",&flg2));
67   PetscCall(PetscOptionsHasName(NULL,NULL,"-minvalues",&flg3));
68   if (flg) {
69     PetscCall(PetscMalloc1(nlocal+nghost,&tarray));
70     PetscCall(VecCreateGhostWithArray(PETSC_COMM_WORLD,nlocal,PETSC_DECIDE,nghost,ifrom,tarray,&gxs));
71   } else if (flg2) {
72     PetscCall(VecCreate(PETSC_COMM_WORLD,&gxs));
73     PetscCall(VecSetType(gxs,VECMPI));
74     PetscCall(VecSetSizes(gxs,nlocal,PETSC_DECIDE));
75     PetscCall(VecMPISetGhost(gxs,nghost,ifrom));
76   } else {
77     PetscCall(VecCreateGhost(PETSC_COMM_WORLD,nlocal,PETSC_DECIDE,nghost,ifrom,&gxs));
78   }
79 
80   /*
81       Test VecDuplicate()
82   */
83   PetscCall(VecDuplicate(gxs,&gx));
84   PetscCall(VecDestroy(&gxs));
85 
86   /*
87      Access the local representation
88   */
89   PetscCall(VecGhostGetLocalForm(gx,&lx));
90 
91   /*
92      Set the values from 0 to 12 into the "global" vector
93   */
94   PetscCall(VecGetOwnershipRange(gx,&rstart,&rend));
95   for (i=rstart; i<rend; i++) {
96     value = (PetscScalar) i;
97     PetscCall(VecSetValues(gx,1,&i,&value,INSERT_VALUES));
98   }
99   PetscCall(VecAssemblyBegin(gx));
100   PetscCall(VecAssemblyEnd(gx));
101 
102   PetscCall(VecGhostUpdateBegin(gx,INSERT_VALUES,SCATTER_FORWARD));
103   PetscCall(VecGhostUpdateEnd(gx,INSERT_VALUES,SCATTER_FORWARD));
104 
105   /*
106      Print out each vector, including the ghost padding region.
107   */
108   PetscCall(VecGetArray(lx,&array));
109   for (i=0; i<nlocal+nghost; i++) {
110     PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD,"%" PetscInt_FMT " %g\n",i,(double)PetscRealPart(array[i])));
111   }
112   PetscCall(VecRestoreArray(lx,&array));
113   PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT));
114   PetscCall(VecGhostRestoreLocalForm(gx,&lx));
115 
116   /* Another test that sets ghost values and then accumulates onto the owning processors using MIN_VALUES */
117   if (flg3) {
118     if (rank == 0)PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD,"\nTesting VecGhostUpdate with MIN_VALUES\n"));
119     PetscCall(VecGhostGetLocalForm(gx,&lx));
120     PetscCall(VecGetArray(lx,&array));
121     for (i=0; i<nghost; i++) array[nlocal+i] = rank ? (PetscScalar)4 : (PetscScalar)8;
122     PetscCall(VecRestoreArray(lx,&array));
123     PetscCall(VecGhostRestoreLocalForm(gx,&lx));
124 
125     PetscCall(VecGhostUpdateBegin(gx,MIN_VALUES,SCATTER_REVERSE));
126     PetscCall(VecGhostUpdateEnd(gx,MIN_VALUES,SCATTER_REVERSE));
127 
128     PetscCall(VecGhostGetLocalForm(gx,&lx));
129     PetscCall(VecGetArray(lx,&array));
130 
131     for (i=0; i<nlocal+nghost; i++) {
132       PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD,"%" PetscInt_FMT " %g\n",i,(double)PetscRealPart(array[i])));
133     }
134     PetscCall(VecRestoreArray(lx,&array));
135     PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT));
136     PetscCall(VecGhostRestoreLocalForm(gx,&lx));
137   }
138 
139   PetscCall(VecDestroy(&gx));
140 
141   if (flg) PetscCall(PetscFree(tarray));
142   PetscCall(PetscFinalize());
143   return 0;
144 }
145 
146 /*TEST
147 
148      test:
149        nsize: 2
150 
151      test:
152        suffix: 2
153        nsize: 2
154        args: -allocate
155        output_file: output/ex9_1.out
156 
157      test:
158        suffix: 3
159        nsize: 2
160        args: -vecmpisetghost
161        output_file: output/ex9_1.out
162 
163      test:
164        suffix: 4
165        nsize: 2
166        args: -minvalues
167        output_file: output/ex9_2.out
168        requires: !complex
169 
170 TEST*/
171