xref: /petsc/src/vec/vec/tests/ex45.c (revision 732aec7a18f2199fb53bb9a2f3aef439a834ce31)
1 static char help[] = "Demonstrates VecStrideSubSetScatter() and VecStrideSubSetGather().\n\n";
2 
3 /*
4    Allows one to easily pull out some components of a multi-component vector and put them in another vector.
5 
6    Note that these are special cases of VecScatter
7 */
8 
9 /*
10   Include "petscvec.h" so that we can use vectors.  Note that this file
11   automatically includes:
12      petscsys.h       - base PETSc routines   petscis.h     - index sets
13      petscviewer.h - viewers
14 */
15 
16 #include <petscvec.h>
17 
main(int argc,char ** argv)18 int main(int argc, char **argv)
19 {
20   Vec            v, s;
21   PetscInt       i, start, end, n = 8;
22   PetscScalar    value;
23   const PetscInt vidx[] = {1, 2}, sidx[] = {1, 0};
24   PetscInt       miidx[2];
25   PetscReal      mvidx[2];
26 
27   PetscFunctionBeginUser;
28   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
29   PetscCall(PetscOptionsGetInt(NULL, NULL, "-n", &n, NULL));
30 
31   /*
32       Create multi-component vector with 4 components
33   */
34   PetscCall(VecCreate(PETSC_COMM_WORLD, &v));
35   PetscCall(VecSetSizes(v, PETSC_DECIDE, n));
36   PetscCall(VecSetBlockSize(v, 4));
37   PetscCall(VecSetFromOptions(v));
38 
39   /*
40       Create double-component vectors
41   */
42   PetscCall(VecCreate(PETSC_COMM_WORLD, &s));
43   PetscCall(VecSetSizes(s, PETSC_DECIDE, n / 2));
44   PetscCall(VecSetBlockSize(s, 2));
45   PetscCall(VecSetFromOptions(s));
46 
47   /*
48      Set the vector values
49   */
50   PetscCall(VecGetOwnershipRange(v, &start, &end));
51   for (i = start; i < end; i++) {
52     value = i;
53     PetscCall(VecSetValues(v, 1, &i, &value, INSERT_VALUES));
54   }
55   PetscCall(VecAssemblyBegin(v));
56   PetscCall(VecAssemblyEnd(v));
57 
58   /*
59      Get the components from the large multi-component vector to the small multi-component vector,
60      scale the smaller vector and then move values back to the large vector
61   */
62   PetscCall(VecStrideSubSetGather(v, PETSC_DETERMINE, vidx, NULL, s, INSERT_VALUES));
63   PetscCall(VecView(s, PETSC_VIEWER_STDOUT_WORLD));
64   PetscCall(VecScale(s, 100.0));
65 
66   PetscCall(VecStrideSubSetScatter(s, PETSC_DETERMINE, NULL, vidx, v, ADD_VALUES));
67   PetscCall(VecView(v, PETSC_VIEWER_STDOUT_WORLD));
68 
69   /*
70      Get the components from the large multi-component vector to the small multi-component vector,
71      scale the smaller vector and then move values back to the large vector
72   */
73   PetscCall(VecStrideSubSetGather(v, 2, vidx, sidx, s, INSERT_VALUES));
74   PetscCall(VecView(s, PETSC_VIEWER_STDOUT_WORLD));
75   PetscCall(VecScale(s, 100.0));
76 
77   PetscCall(VecStrideSubSetScatter(s, 2, sidx, vidx, v, ADD_VALUES));
78   PetscCall(VecView(v, PETSC_VIEWER_STDOUT_WORLD));
79 
80   PetscCall(VecStrideMax(v, 1, &miidx[0], &mvidx[0]));
81   PetscCall(VecStrideMin(v, 1, &miidx[1], &mvidx[1]));
82   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Min/Max: %" PetscInt_FMT " %g, %" PetscInt_FMT " %g\n", miidx[0], (double)mvidx[0], miidx[1], (double)mvidx[1]));
83   /*
84      Free work space.  All PETSc objects should be destroyed when they
85      are no longer needed.
86   */
87   PetscCall(VecDestroy(&v));
88   PetscCall(VecDestroy(&s));
89   PetscCall(PetscFinalize());
90   return 0;
91 }
92 
93 /*TEST
94 
95    test:
96       filter: grep -v type | grep -v " MPI process" | grep -v Process
97       diff_args: -j
98       nsize: 2
99 
100    test:
101       filter: grep -v type | grep -v " MPI process" | grep -v Process
102       output_file: output/ex45_1.out
103       diff_args: -j
104       suffix: 2
105       nsize: 1
106       args: -vec_type {{seq mpi}}
107 
108 TEST*/
109