xref: /petsc/src/ksp/pc/tutorials/ex3.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
1c4762a1bSJed Brown 
2c4762a1bSJed Brown static char help[] = "Test PC redistribute on matrix with load imbalance. \n\
3c4762a1bSJed Brown                       Modified from src/ksp/ksp/tutorials/ex2.c.\n\
4c4762a1bSJed Brown Input parameters include:\n\
5c4762a1bSJed Brown   -random_exact_sol : use a random exact solution vector\n\
6c4762a1bSJed Brown   -view_exact_sol   : write exact solution vector to stdout\n\
710582eeaSJed Brown   -n <mesh_y>       : number of mesh points\n\n";
8c4762a1bSJed Brown /*
9c4762a1bSJed Brown Example:
10c4762a1bSJed Brown   mpiexec -n 8 ./ex3 -n 10000 -ksp_type cg -pc_type bjacobi -sub_pc_type icc -ksp_rtol 1.e-8 -log_view
11c4762a1bSJed Brown   mpiexec -n 8 ./ex3 -n 10000 -ksp_type preonly -pc_type redistribute -redistribute_ksp_type cg -redistribute_pc_type bjacobi -redistribute_sub_pc_type icc -redistribute_ksp_rtol 1.e-8 -log_view
12c4762a1bSJed Brown */
13c4762a1bSJed Brown 
14c4762a1bSJed Brown #include <petscksp.h>
15c4762a1bSJed Brown 
16*d71ae5a4SJacob Faibussowitsch int main(int argc, char **args)
17*d71ae5a4SJacob Faibussowitsch {
18c4762a1bSJed Brown   Vec         x, b, u; /* approx solution, RHS, exact solution */
19c4762a1bSJed Brown   Mat         A;       /* linear system matrix */
20c4762a1bSJed Brown   KSP         ksp;     /* linear solver context */
21c4762a1bSJed Brown   PetscRandom rctx;    /* random number generator context */
22c4762a1bSJed Brown   PetscReal   norm;    /* norm of solution error */
23c4762a1bSJed Brown   PetscInt    i, j, Ii, J, Istart, Iend, m, n = 7, its, nloc, matdistribute = 0;
24c4762a1bSJed Brown   PetscBool   flg = PETSC_FALSE;
25c4762a1bSJed Brown   PetscScalar v;
26c4762a1bSJed Brown   PetscMPIInt rank, size;
27c4762a1bSJed Brown #if defined(PETSC_USE_LOG)
28c4762a1bSJed Brown   PetscLogStage stage;
29c4762a1bSJed Brown #endif
30c4762a1bSJed Brown 
31327415f7SBarry Smith   PetscFunctionBeginUser;
329566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &args, (char *)0, help));
339566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
349566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
357827d75bSBarry Smith   PetscCheck(size > 1, PETSC_COMM_WORLD, PETSC_ERR_WRONG_MPI_SIZE, "This example requires at least 2 MPI processes!");
36c4762a1bSJed Brown 
379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-n", &n, NULL));
389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-matdistribute", &matdistribute, NULL));
39c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
40c4762a1bSJed Brown          Compute the matrix and right-hand-side vector that define
41c4762a1bSJed Brown          the linear system, Ax = b.
42c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
43c4762a1bSJed Brown   switch (matdistribute) {
44c4762a1bSJed Brown   case 1: /* very imbalanced process load for matrix A */
45c4762a1bSJed Brown     m    = (1 + size) * size;
46c4762a1bSJed Brown     nloc = (rank + 1) * n;
47c4762a1bSJed Brown     if (rank == size - 1) { /* proc[size-1] stores all remaining rows */
48c4762a1bSJed Brown       nloc = m * n;
49ad540459SPierre Jolivet       for (i = 0; i < size - 1; i++) nloc -= (i + 1) * n;
50c4762a1bSJed Brown     }
51c4762a1bSJed Brown     break;
52c4762a1bSJed Brown   default: /* proc[0] and proc[1] load much smaller row blocks, the rest processes have same loads */
53c4762a1bSJed Brown     if (rank == 0 || rank == 1) {
54c4762a1bSJed Brown       nloc = n;
55c4762a1bSJed Brown     } else {
56c4762a1bSJed Brown       nloc = 10 * n; /* 10x larger load */
57c4762a1bSJed Brown     }
58c4762a1bSJed Brown     m = 2 + (size - 2) * 10;
59c4762a1bSJed Brown     break;
60c4762a1bSJed Brown   }
619566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
629566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(A, nloc, nloc, PETSC_DECIDE, PETSC_DECIDE));
639566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(A));
649566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(A, 5, NULL, 5, NULL));
659566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(A, 5, NULL));
669566063dSJacob Faibussowitsch   PetscCall(MatSetUp(A));
67c4762a1bSJed Brown 
689566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &Istart, &Iend));
69c4762a1bSJed Brown   nloc = Iend - Istart;
7063a3b9bcSJacob Faibussowitsch   PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[%d] A Istart,Iend: %" PetscInt_FMT " %" PetscInt_FMT "; nloc %" PetscInt_FMT "\n", rank, Istart, Iend, nloc));
719566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT));
72c4762a1bSJed Brown 
739566063dSJacob Faibussowitsch   PetscCall(PetscLogStageRegister("Assembly", &stage));
749566063dSJacob Faibussowitsch   PetscCall(PetscLogStagePush(stage));
75c4762a1bSJed Brown   for (Ii = Istart; Ii < Iend; Ii++) {
769371c9d4SSatish Balay     v = -1.0;
779371c9d4SSatish Balay     i = Ii / n;
789371c9d4SSatish Balay     j = Ii - i * n;
799371c9d4SSatish Balay     if (i > 0) {
809371c9d4SSatish Balay       J = Ii - n;
819371c9d4SSatish Balay       PetscCall(MatSetValues(A, 1, &Ii, 1, &J, &v, INSERT_VALUES));
829371c9d4SSatish Balay     }
839371c9d4SSatish Balay     if (i < m - 1) {
849371c9d4SSatish Balay       J = Ii + n;
859371c9d4SSatish Balay       PetscCall(MatSetValues(A, 1, &Ii, 1, &J, &v, INSERT_VALUES));
869371c9d4SSatish Balay     }
879371c9d4SSatish Balay     if (j > 0) {
889371c9d4SSatish Balay       J = Ii - 1;
899371c9d4SSatish Balay       PetscCall(MatSetValues(A, 1, &Ii, 1, &J, &v, INSERT_VALUES));
909371c9d4SSatish Balay     }
919371c9d4SSatish Balay     if (j < n - 1) {
929371c9d4SSatish Balay       J = Ii + 1;
939371c9d4SSatish Balay       PetscCall(MatSetValues(A, 1, &Ii, 1, &J, &v, INSERT_VALUES));
949371c9d4SSatish Balay     }
959371c9d4SSatish Balay     v = 4.0;
969371c9d4SSatish Balay     PetscCall(MatSetValues(A, 1, &Ii, 1, &Ii, &v, INSERT_VALUES));
97c4762a1bSJed Brown   }
989566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
999566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
1009566063dSJacob Faibussowitsch   PetscCall(PetscLogStagePop());
101c4762a1bSJed Brown 
102c4762a1bSJed Brown   /* A is symmetric. Set symmetric flag to enable ICC/Cholesky preconditioner */
1039566063dSJacob Faibussowitsch   PetscCall(MatSetOption(A, MAT_SYMMETRIC, PETSC_TRUE));
104c4762a1bSJed Brown 
105c4762a1bSJed Brown   /* Create parallel vectors. */
1069566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_WORLD, &u));
1079566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(u, nloc, PETSC_DECIDE));
1089566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(u));
1099566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &b));
1109566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(b, &x));
111c4762a1bSJed Brown 
112c4762a1bSJed Brown   /* Set exact solution; then compute right-hand-side vector. */
1139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-random_exact_sol", &flg, NULL));
114c4762a1bSJed Brown   if (flg) {
1159566063dSJacob Faibussowitsch     PetscCall(PetscRandomCreate(PETSC_COMM_WORLD, &rctx));
1169566063dSJacob Faibussowitsch     PetscCall(PetscRandomSetFromOptions(rctx));
1179566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(u, rctx));
1189566063dSJacob Faibussowitsch     PetscCall(PetscRandomDestroy(&rctx));
119c4762a1bSJed Brown   } else {
1209566063dSJacob Faibussowitsch     PetscCall(VecSet(u, 1.0));
121c4762a1bSJed Brown   }
1229566063dSJacob Faibussowitsch   PetscCall(MatMult(A, u, b));
123c4762a1bSJed Brown 
124c4762a1bSJed Brown   /* View the exact solution vector if desired */
125c4762a1bSJed Brown   flg = PETSC_FALSE;
1269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-view_exact_sol", &flg, NULL));
1279566063dSJacob Faibussowitsch   if (flg) PetscCall(VecView(u, PETSC_VIEWER_STDOUT_WORLD));
128c4762a1bSJed Brown 
129c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
130c4762a1bSJed Brown                 Create the linear solver and set various options
131c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1329566063dSJacob Faibussowitsch   PetscCall(KSPCreate(PETSC_COMM_WORLD, &ksp));
1339566063dSJacob Faibussowitsch   PetscCall(KSPSetOperators(ksp, A, A));
134d0609cedSBarry Smith   PetscCall(KSPSetTolerances(ksp, 1.e-2 / ((m + 1) * (n + 1)), PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
1359566063dSJacob Faibussowitsch   PetscCall(KSPSetFromOptions(ksp));
136c4762a1bSJed Brown 
137c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
138c4762a1bSJed Brown                       Solve the linear system
139c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1409566063dSJacob Faibussowitsch   PetscCall(KSPSolve(ksp, b, x));
141c4762a1bSJed Brown 
142c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
143c4762a1bSJed Brown                       Check solution and clean up
144c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1459566063dSJacob Faibussowitsch   PetscCall(VecAXPY(x, -1.0, u));
1469566063dSJacob Faibussowitsch   PetscCall(VecNorm(x, NORM_2, &norm));
1479566063dSJacob Faibussowitsch   PetscCall(KSPGetIterationNumber(ksp, &its));
14863a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Norm of error %g iterations %" PetscInt_FMT "\n", (double)norm, its));
149c4762a1bSJed Brown 
150c4762a1bSJed Brown   /* Free work space. */
1519566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&ksp));
1529371c9d4SSatish Balay   PetscCall(VecDestroy(&u));
1539371c9d4SSatish Balay   PetscCall(VecDestroy(&x));
1549371c9d4SSatish Balay   PetscCall(VecDestroy(&b));
1559371c9d4SSatish Balay   PetscCall(MatDestroy(&A));
1569566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
157b122ec5aSJacob Faibussowitsch   return 0;
158c4762a1bSJed Brown }
159c4762a1bSJed Brown 
160c4762a1bSJed Brown /*TEST
161c4762a1bSJed Brown 
162c4762a1bSJed Brown    test:
163c4762a1bSJed Brown       nsize: 8
164c4762a1bSJed Brown       args: -n 100 -ksp_type cg -pc_type bjacobi -sub_pc_type icc -ksp_rtol 1.e-8
165c4762a1bSJed Brown 
166c4762a1bSJed Brown    test:
167c4762a1bSJed Brown       suffix: 2
168c4762a1bSJed Brown       nsize: 8
169c4762a1bSJed Brown       args: -n 100 -ksp_type preonly -pc_type redistribute -redistribute_ksp_type cg -redistribute_pc_type bjacobi -redistribute_sub_pc_type icc -redistribute_ksp_rtol 1.e-8
170c4762a1bSJed Brown 
171c4762a1bSJed Brown TEST*/
172