1c4762a1bSJed Brown static char help[] = "Test PC redistribute on matrix with load imbalance. \n\
2c4762a1bSJed Brown Modified from src/ksp/ksp/tutorials/ex2.c.\n\
3c4762a1bSJed Brown Input parameters include:\n\
4c4762a1bSJed Brown -random_exact_sol : use a random exact solution vector\n\
5c4762a1bSJed Brown -view_exact_sol : write exact solution vector to stdout\n\
610582eeaSJed Brown -n <mesh_y> : number of mesh points\n\n";
7c4762a1bSJed Brown /*
8c4762a1bSJed Brown Example:
9c4762a1bSJed Brown mpiexec -n 8 ./ex3 -n 10000 -ksp_type cg -pc_type bjacobi -sub_pc_type icc -ksp_rtol 1.e-8 -log_view
10c4762a1bSJed 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
11c4762a1bSJed Brown */
12c4762a1bSJed Brown
13c4762a1bSJed Brown #include <petscksp.h>
14c4762a1bSJed Brown
main(int argc,char ** args)15d71ae5a4SJacob Faibussowitsch int main(int argc, char **args)
16d71ae5a4SJacob Faibussowitsch {
17c4762a1bSJed Brown Vec x, b, u; /* approx solution, RHS, exact solution */
18c4762a1bSJed Brown Mat A; /* linear system matrix */
19c4762a1bSJed Brown KSP ksp; /* linear solver context */
20c4762a1bSJed Brown PetscRandom rctx; /* random number generator context */
21c4762a1bSJed Brown PetscReal norm; /* norm of solution error */
22c4762a1bSJed Brown PetscInt i, j, Ii, J, Istart, Iend, m, n = 7, its, nloc, matdistribute = 0;
23c4762a1bSJed Brown PetscBool flg = PETSC_FALSE;
24c4762a1bSJed Brown PetscScalar v;
25c4762a1bSJed Brown PetscMPIInt rank, size;
26c4762a1bSJed Brown PetscLogStage stage;
27c4762a1bSJed Brown
28327415f7SBarry Smith PetscFunctionBeginUser;
29*c8025a54SPierre Jolivet PetscCall(PetscInitialize(&argc, &args, NULL, help));
309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
327827d75bSBarry Smith PetscCheck(size > 1, PETSC_COMM_WORLD, PETSC_ERR_WRONG_MPI_SIZE, "This example requires at least 2 MPI processes!");
33c4762a1bSJed Brown
349566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-n", &n, NULL));
359566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-matdistribute", &matdistribute, NULL));
36c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
37c4762a1bSJed Brown Compute the matrix and right-hand-side vector that define
38c4762a1bSJed Brown the linear system, Ax = b.
39c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
40c4762a1bSJed Brown switch (matdistribute) {
41c4762a1bSJed Brown case 1: /* very imbalanced process load for matrix A */
42c4762a1bSJed Brown m = (1 + size) * size;
43c4762a1bSJed Brown nloc = (rank + 1) * n;
44c4762a1bSJed Brown if (rank == size - 1) { /* proc[size-1] stores all remaining rows */
45c4762a1bSJed Brown nloc = m * n;
46ad540459SPierre Jolivet for (i = 0; i < size - 1; i++) nloc -= (i + 1) * n;
47c4762a1bSJed Brown }
48c4762a1bSJed Brown break;
49c4762a1bSJed Brown default: /* proc[0] and proc[1] load much smaller row blocks, the rest processes have same loads */
50c4762a1bSJed Brown if (rank == 0 || rank == 1) {
51c4762a1bSJed Brown nloc = n;
52c4762a1bSJed Brown } else {
53c4762a1bSJed Brown nloc = 10 * n; /* 10x larger load */
54c4762a1bSJed Brown }
55c4762a1bSJed Brown m = 2 + (size - 2) * 10;
56c4762a1bSJed Brown break;
57c4762a1bSJed Brown }
589566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
599566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, nloc, nloc, PETSC_DECIDE, PETSC_DECIDE));
609566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(A));
619566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(A, 5, NULL, 5, NULL));
629566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(A, 5, NULL));
639566063dSJacob Faibussowitsch PetscCall(MatSetUp(A));
64c4762a1bSJed Brown
659566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &Istart, &Iend));
66c4762a1bSJed Brown nloc = Iend - Istart;
6763a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[%d] A Istart,Iend: %" PetscInt_FMT " %" PetscInt_FMT "; nloc %" PetscInt_FMT "\n", rank, Istart, Iend, nloc));
689566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT));
69c4762a1bSJed Brown
709566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Assembly", &stage));
719566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stage));
72c4762a1bSJed Brown for (Ii = Istart; Ii < Iend; Ii++) {
739371c9d4SSatish Balay v = -1.0;
749371c9d4SSatish Balay i = Ii / n;
759371c9d4SSatish Balay j = Ii - i * n;
769371c9d4SSatish Balay if (i > 0) {
779371c9d4SSatish Balay J = Ii - n;
789371c9d4SSatish Balay PetscCall(MatSetValues(A, 1, &Ii, 1, &J, &v, INSERT_VALUES));
799371c9d4SSatish Balay }
809371c9d4SSatish Balay if (i < m - 1) {
819371c9d4SSatish Balay J = Ii + n;
829371c9d4SSatish Balay PetscCall(MatSetValues(A, 1, &Ii, 1, &J, &v, INSERT_VALUES));
839371c9d4SSatish Balay }
849371c9d4SSatish Balay if (j > 0) {
859371c9d4SSatish Balay J = Ii - 1;
869371c9d4SSatish Balay PetscCall(MatSetValues(A, 1, &Ii, 1, &J, &v, INSERT_VALUES));
879371c9d4SSatish Balay }
889371c9d4SSatish Balay if (j < n - 1) {
899371c9d4SSatish Balay J = Ii + 1;
909371c9d4SSatish Balay PetscCall(MatSetValues(A, 1, &Ii, 1, &J, &v, INSERT_VALUES));
919371c9d4SSatish Balay }
929371c9d4SSatish Balay v = 4.0;
939371c9d4SSatish Balay PetscCall(MatSetValues(A, 1, &Ii, 1, &Ii, &v, INSERT_VALUES));
94c4762a1bSJed Brown }
959566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
969566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
979566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop());
98c4762a1bSJed Brown
99c4762a1bSJed Brown /* A is symmetric. Set symmetric flag to enable ICC/Cholesky preconditioner */
1009566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_SYMMETRIC, PETSC_TRUE));
101c4762a1bSJed Brown
102c4762a1bSJed Brown /* Create parallel vectors. */
1039566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &u));
1049566063dSJacob Faibussowitsch PetscCall(VecSetSizes(u, nloc, PETSC_DECIDE));
1059566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(u));
1069566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &b));
1079566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &x));
108c4762a1bSJed Brown
109c4762a1bSJed Brown /* Set exact solution; then compute right-hand-side vector. */
1109566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-random_exact_sol", &flg, NULL));
111c4762a1bSJed Brown if (flg) {
1129566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_WORLD, &rctx));
1139566063dSJacob Faibussowitsch PetscCall(PetscRandomSetFromOptions(rctx));
1149566063dSJacob Faibussowitsch PetscCall(VecSetRandom(u, rctx));
1159566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&rctx));
116c4762a1bSJed Brown } else {
1179566063dSJacob Faibussowitsch PetscCall(VecSet(u, 1.0));
118c4762a1bSJed Brown }
1199566063dSJacob Faibussowitsch PetscCall(MatMult(A, u, b));
120c4762a1bSJed Brown
121c4762a1bSJed Brown /* View the exact solution vector if desired */
122c4762a1bSJed Brown flg = PETSC_FALSE;
1239566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-view_exact_sol", &flg, NULL));
1249566063dSJacob Faibussowitsch if (flg) PetscCall(VecView(u, PETSC_VIEWER_STDOUT_WORLD));
125c4762a1bSJed Brown
126c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
127c4762a1bSJed Brown Create the linear solver and set various options
128c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1299566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_WORLD, &ksp));
1309566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, A, A));
131fb842aefSJose E. Roman PetscCall(KSPSetTolerances(ksp, 1.e-2 / ((m + 1) * (n + 1)), PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT));
1329566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(ksp));
133c4762a1bSJed Brown
134c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
135c4762a1bSJed Brown Solve the linear system
136c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1379566063dSJacob Faibussowitsch PetscCall(KSPSolve(ksp, b, x));
138c4762a1bSJed Brown
139c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
140c4762a1bSJed Brown Check solution and clean up
141c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1429566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, u));
1439566063dSJacob Faibussowitsch PetscCall(VecNorm(x, NORM_2, &norm));
1449566063dSJacob Faibussowitsch PetscCall(KSPGetIterationNumber(ksp, &its));
14563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Norm of error %g iterations %" PetscInt_FMT "\n", (double)norm, its));
146c4762a1bSJed Brown
147c4762a1bSJed Brown /* Free work space. */
1489566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&ksp));
1499371c9d4SSatish Balay PetscCall(VecDestroy(&u));
1509371c9d4SSatish Balay PetscCall(VecDestroy(&x));
1519371c9d4SSatish Balay PetscCall(VecDestroy(&b));
1529371c9d4SSatish Balay PetscCall(MatDestroy(&A));
1539566063dSJacob Faibussowitsch PetscCall(PetscFinalize());
154b122ec5aSJacob Faibussowitsch return 0;
155c4762a1bSJed Brown }
156c4762a1bSJed Brown
157c4762a1bSJed Brown /*TEST
158c4762a1bSJed Brown
159c4762a1bSJed Brown test:
160c4762a1bSJed Brown nsize: 8
161c4762a1bSJed Brown args: -n 100 -ksp_type cg -pc_type bjacobi -sub_pc_type icc -ksp_rtol 1.e-8
162c4762a1bSJed Brown
163c4762a1bSJed Brown test:
164c4762a1bSJed Brown suffix: 2
165c4762a1bSJed Brown nsize: 8
166c4762a1bSJed 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
167c4762a1bSJed Brown
168c4762a1bSJed Brown TEST*/
169