xref: /petsc/src/vec/vec/tutorials/ex9.c (revision 732aec7a18f2199fb53bb9a2f3aef439a834ce31)
1c4762a1bSJed Brown static char help[] = "Demonstrates use of VecCreateGhost().\n\n";
2c4762a1bSJed Brown 
31bb3edfdSPatrick Sanan /*
4c4762a1bSJed Brown    Description: Ghost padding is one way to handle local calculations that
5c4762a1bSJed Brown       involve values from other processors. VecCreateGhost() provides
6c4762a1bSJed Brown       a way to create vectors with extra room at the end of the vector
7c4762a1bSJed Brown       array to contain the needed ghost values from other processors,
8c4762a1bSJed Brown       vector computations are otherwise unaffected.
91bb3edfdSPatrick Sanan */
10c4762a1bSJed Brown 
11c4762a1bSJed Brown /*
12c4762a1bSJed Brown   Include "petscvec.h" so that we can use vectors.  Note that this file
13c4762a1bSJed Brown   automatically includes:
14c4762a1bSJed Brown      petscsys.h       - base PETSc routines   petscis.h     - index sets
15c4762a1bSJed Brown      petscviewer.h - viewers
16c4762a1bSJed Brown */
17c4762a1bSJed Brown #include <petscvec.h>
18c4762a1bSJed Brown 
main(int argc,char ** argv)19d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
20d71ae5a4SJacob Faibussowitsch {
21c4762a1bSJed Brown   PetscMPIInt            rank, size;
22c4762a1bSJed Brown   PetscInt               nlocal = 6, nghost = 2, ifrom[2], i, rstart, rend;
23ab4fe330SFande Kong   PetscBool              flg, flg2, flg3, flg4, flg5;
24c4762a1bSJed Brown   PetscScalar            value, *array, *tarray = 0;
25c4762a1bSJed Brown   Vec                    lx, gx, gxs;
26ab4fe330SFande Kong   IS                     ghost;
27ab4fe330SFande Kong   ISLocalToGlobalMapping mapping;
28c4762a1bSJed Brown 
29327415f7SBarry Smith   PetscFunctionBeginUser;
30*c8025a54SPierre Jolivet   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
33be096a46SBarry Smith   PetscCheck(size == 2, PETSC_COMM_WORLD, PETSC_ERR_WRONG_MPI_SIZE, "Must run example with two processors");
34c4762a1bSJed Brown 
35c4762a1bSJed Brown   /*
36c4762a1bSJed Brown      Construct a two dimensional graph connecting nlocal degrees of
37c4762a1bSJed Brown      freedom per processor. From this we will generate the global
38c4762a1bSJed Brown      indices of needed ghost values
39c4762a1bSJed Brown 
40c4762a1bSJed Brown      For simplicity we generate the entire graph on each processor:
41c4762a1bSJed Brown      in real application the graph would stored in parallel, but this
42c4762a1bSJed Brown      example is only to demonstrate the management of ghost padding
43c4762a1bSJed Brown      with VecCreateGhost().
44c4762a1bSJed Brown 
45c4762a1bSJed Brown      In this example we consider the vector as representing
46c4762a1bSJed Brown      degrees of freedom in a one dimensional grid with periodic
47c4762a1bSJed Brown      boundary conditions.
48c4762a1bSJed Brown 
49c4762a1bSJed Brown         ----Processor  1---------  ----Processor 2 --------
50c4762a1bSJed Brown          0    1   2   3   4    5    6    7   8   9   10   11
51c4762a1bSJed Brown                                |----|
52c4762a1bSJed Brown          |-------------------------------------------------|
53c4762a1bSJed Brown 
54c4762a1bSJed Brown   */
55c4762a1bSJed Brown 
56dd400576SPatrick Sanan   if (rank == 0) {
579371c9d4SSatish Balay     ifrom[0] = 11;
589371c9d4SSatish Balay     ifrom[1] = 6;
59c4762a1bSJed Brown   } else {
609371c9d4SSatish Balay     ifrom[0] = 0;
619371c9d4SSatish Balay     ifrom[1] = 5;
62c4762a1bSJed Brown   }
63c4762a1bSJed Brown 
64c4762a1bSJed Brown   /*
65c4762a1bSJed Brown      Create the vector with two slots for ghost points. Note that both
66c4762a1bSJed Brown      the local vector (lx) and the global vector (gx) share the same
67c4762a1bSJed Brown      array for storing vector values.
68c4762a1bSJed Brown   */
699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, "-allocate", &flg));
709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, "-vecmpisetghost", &flg2));
719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, "-minvalues", &flg3));
72c4762a1bSJed Brown   if (flg) {
739566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nlocal + nghost, &tarray));
749566063dSJacob Faibussowitsch     PetscCall(VecCreateGhostWithArray(PETSC_COMM_WORLD, nlocal, PETSC_DECIDE, nghost, ifrom, tarray, &gxs));
75c4762a1bSJed Brown   } else if (flg2) {
769566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_WORLD, &gxs));
779566063dSJacob Faibussowitsch     PetscCall(VecSetType(gxs, VECMPI));
789566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(gxs, nlocal, PETSC_DECIDE));
799566063dSJacob Faibussowitsch     PetscCall(VecMPISetGhost(gxs, nghost, ifrom));
80c4762a1bSJed Brown   } else {
819566063dSJacob Faibussowitsch     PetscCall(VecCreateGhost(PETSC_COMM_WORLD, nlocal, PETSC_DECIDE, nghost, ifrom, &gxs));
824b2bf6caSPierre Jolivet     PetscCall(VecSet(gxs, 1.0));
834b2bf6caSPierre Jolivet     if (rank == 1) PetscCall(VecSetValueLocal(gxs, 0, 2.0, INSERT_VALUES));
844b2bf6caSPierre Jolivet     PetscCall(VecAssemblyBegin(gxs));
854b2bf6caSPierre Jolivet     PetscCall(VecAssemblyEnd(gxs));
864b2bf6caSPierre Jolivet     value = 0.0;
874b2bf6caSPierre Jolivet     if (rank == 1) {
884b2bf6caSPierre Jolivet       PetscCall(VecGetArray(gxs, &array));
894b2bf6caSPierre Jolivet       value = array[0];
904b2bf6caSPierre Jolivet       PetscCall(VecRestoreArray(gxs, &array));
914b2bf6caSPierre Jolivet     }
92462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &value, 1, MPIU_SCALAR, MPIU_SUM, PETSC_COMM_WORLD));
934b2bf6caSPierre Jolivet     PetscCheck(PetscIsCloseAtTolScalar(value, 2.0, PETSC_SMALL, PETSC_SMALL), PETSC_COMM_WORLD, PETSC_ERR_PLIB, "%g != 2.0", (double)PetscAbsScalar(value));
94c4762a1bSJed Brown   }
95c4762a1bSJed Brown 
96c4762a1bSJed Brown   /*
97c4762a1bSJed Brown       Test VecDuplicate()
98c4762a1bSJed Brown   */
999566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(gxs, &gx));
1009566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&gxs));
101c4762a1bSJed Brown 
102c4762a1bSJed Brown   /*
103c4762a1bSJed Brown      Access the local representation
104c4762a1bSJed Brown   */
1059566063dSJacob Faibussowitsch   PetscCall(VecGhostGetLocalForm(gx, &lx));
106c4762a1bSJed Brown 
107c4762a1bSJed Brown   /*
108c4762a1bSJed Brown      Set the values from 0 to 12 into the "global" vector
109c4762a1bSJed Brown   */
1109566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(gx, &rstart, &rend));
111c4762a1bSJed Brown   for (i = rstart; i < rend; i++) {
112c4762a1bSJed Brown     value = (PetscScalar)i;
1139566063dSJacob Faibussowitsch     PetscCall(VecSetValues(gx, 1, &i, &value, INSERT_VALUES));
114c4762a1bSJed Brown   }
1159566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(gx));
1169566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(gx));
117c4762a1bSJed Brown 
1189566063dSJacob Faibussowitsch   PetscCall(VecGhostUpdateBegin(gx, INSERT_VALUES, SCATTER_FORWARD));
1199566063dSJacob Faibussowitsch   PetscCall(VecGhostUpdateEnd(gx, INSERT_VALUES, SCATTER_FORWARD));
120c4762a1bSJed Brown 
121c4762a1bSJed Brown   /*
122c4762a1bSJed Brown      Print out each vector, including the ghost padding region.
123c4762a1bSJed Brown   */
1249566063dSJacob Faibussowitsch   PetscCall(VecGetArray(lx, &array));
12548a46eb9SPierre Jolivet   for (i = 0; i < nlocal + nghost; i++) PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "%" PetscInt_FMT " %g\n", i, (double)PetscRealPart(array[i])));
1269566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(lx, &array));
1279566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT));
1289566063dSJacob Faibussowitsch   PetscCall(VecGhostRestoreLocalForm(gx, &lx));
129c4762a1bSJed Brown 
130c4762a1bSJed Brown   /* Another test that sets ghost values and then accumulates onto the owning processors using MIN_VALUES */
131c4762a1bSJed Brown   if (flg3) {
1329566063dSJacob Faibussowitsch     if (rank == 0) PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "\nTesting VecGhostUpdate with MIN_VALUES\n"));
1339566063dSJacob Faibussowitsch     PetscCall(VecGhostGetLocalForm(gx, &lx));
1349566063dSJacob Faibussowitsch     PetscCall(VecGetArray(lx, &array));
135c4762a1bSJed Brown     for (i = 0; i < nghost; i++) array[nlocal + i] = rank ? (PetscScalar)4 : (PetscScalar)8;
1369566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(lx, &array));
1379566063dSJacob Faibussowitsch     PetscCall(VecGhostRestoreLocalForm(gx, &lx));
138c4762a1bSJed Brown 
1399566063dSJacob Faibussowitsch     PetscCall(VecGhostUpdateBegin(gx, MIN_VALUES, SCATTER_REVERSE));
1409566063dSJacob Faibussowitsch     PetscCall(VecGhostUpdateEnd(gx, MIN_VALUES, SCATTER_REVERSE));
141c4762a1bSJed Brown 
1429566063dSJacob Faibussowitsch     PetscCall(VecGhostGetLocalForm(gx, &lx));
1439566063dSJacob Faibussowitsch     PetscCall(VecGetArray(lx, &array));
144c4762a1bSJed Brown 
14548a46eb9SPierre Jolivet     for (i = 0; i < nlocal + nghost; i++) PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "%" PetscInt_FMT " %g\n", i, (double)PetscRealPart(array[i])));
1469566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(lx, &array));
1479566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT));
1489566063dSJacob Faibussowitsch     PetscCall(VecGhostRestoreLocalForm(gx, &lx));
149c4762a1bSJed Brown   }
150c4762a1bSJed Brown 
151ab4fe330SFande Kong   PetscCall(PetscOptionsHasName(NULL, NULL, "-vecghostgetghostis", &flg4));
152ab4fe330SFande Kong   if (flg4) {
153ab4fe330SFande Kong     PetscCall(VecGhostGetGhostIS(gx, &ghost));
154ab4fe330SFande Kong     PetscCall(ISView(ghost, PETSC_VIEWER_STDOUT_WORLD));
155ab4fe330SFande Kong   }
156ab4fe330SFande Kong   PetscCall(PetscOptionsHasName(NULL, NULL, "-getgtlmapping", &flg5));
157ab4fe330SFande Kong   if (flg5) {
158ab4fe330SFande Kong     PetscCall(VecGetLocalToGlobalMapping(gx, &mapping));
1594b2bf6caSPierre Jolivet     if (rank == 0) PetscCall(ISLocalToGlobalMappingView(mapping, NULL));
160ab4fe330SFande Kong   }
161ab4fe330SFande Kong 
1629566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&gx));
163c4762a1bSJed Brown 
1649566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscFree(tarray));
1659566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
166b122ec5aSJacob Faibussowitsch   return 0;
167c4762a1bSJed Brown }
168c4762a1bSJed Brown 
169c4762a1bSJed Brown /*TEST
170c4762a1bSJed Brown 
171c4762a1bSJed Brown      test:
172c4762a1bSJed Brown        nsize: 2
173c4762a1bSJed Brown 
174c4762a1bSJed Brown      test:
175c4762a1bSJed Brown        suffix: 2
176c4762a1bSJed Brown        nsize: 2
177c4762a1bSJed Brown        args: -allocate
178c4762a1bSJed Brown        output_file: output/ex9_1.out
179c4762a1bSJed Brown 
180c4762a1bSJed Brown      test:
181c4762a1bSJed Brown        suffix: 3
182c4762a1bSJed Brown        nsize: 2
183c4762a1bSJed Brown        args: -vecmpisetghost
184c4762a1bSJed Brown        output_file: output/ex9_1.out
185c4762a1bSJed Brown 
186c4762a1bSJed Brown      test:
187c4762a1bSJed Brown        suffix: 4
188c4762a1bSJed Brown        nsize: 2
189c4762a1bSJed Brown        args: -minvalues
190c4762a1bSJed Brown        output_file: output/ex9_2.out
191c4762a1bSJed Brown        requires: !complex
192c4762a1bSJed Brown 
193ab4fe330SFande Kong      test:
194ab4fe330SFande Kong        suffix: 5
195ab4fe330SFande Kong        nsize: 2
196ab4fe330SFande Kong        args: -vecghostgetghostis
197ab4fe330SFande Kong 
198ab4fe330SFande Kong      test:
199ab4fe330SFande Kong        suffix: 6
200ab4fe330SFande Kong        nsize: 2
201ab4fe330SFande Kong        args: -getgtlmapping
202ab4fe330SFande Kong 
203c4762a1bSJed Brown TEST*/
204