Actual source code: ex53.c
1: static char help[] = "Solves a tridiagonal linear system with KSP. \n\
2: Modified from ex1.c to illustrate reuse of preconditioner \n\
3: Written as requested by [petsc-maint #63875] \n\n";
5: #include <petscksp.h>
7: int main(int argc, char **args)
8: {
9: Vec x, x2, b, u; /* approx solution, RHS, exact solution */
10: Mat A; /* linear system matrix */
11: KSP ksp; /* linear solver context */
12: PC pc; /* preconditioner context */
13: PetscReal norm, tol = 100. * PETSC_MACHINE_EPSILON; /* norm of solution error */
14: PetscInt i, n = 10, col[3], its;
15: PetscMPIInt rank, size;
16: PetscScalar one = 1.0, value[3];
18: PetscFunctionBeginUser;
19: PetscCall(PetscInitialize(&argc, &args, NULL, help));
20: PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
21: PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
22: PetscCall(PetscOptionsGetInt(NULL, NULL, "-n", &n, NULL));
24: /* Create vectors.*/
25: PetscCall(VecCreate(PETSC_COMM_WORLD, &x));
26: PetscCall(PetscObjectSetName((PetscObject)x, "Solution"));
27: PetscCall(VecSetSizes(x, PETSC_DECIDE, n));
28: PetscCall(VecSetFromOptions(x));
29: PetscCall(VecDuplicate(x, &b));
30: PetscCall(VecDuplicate(x, &u));
31: PetscCall(VecDuplicate(x, &x2));
33: /* Create matrix. Only proc[0] sets values - not efficient for parallel processing!
34: See ex23.c for efficient parallel assembly matrix */
35: PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
36: PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, n, n));
37: PetscCall(MatSetFromOptions(A));
38: PetscCall(MatSetUp(A));
40: if (rank == 0) {
41: value[0] = -1.0;
42: value[1] = 2.0;
43: value[2] = -1.0;
44: for (i = 1; i < n - 1; i++) {
45: col[0] = i - 1;
46: col[1] = i;
47: col[2] = i + 1;
48: PetscCall(MatSetValues(A, 1, &i, 3, col, value, INSERT_VALUES));
49: }
50: i = n - 1;
51: col[0] = n - 2;
52: col[1] = n - 1;
53: PetscCall(MatSetValues(A, 1, &i, 2, col, value, INSERT_VALUES));
54: i = 0;
55: col[0] = 0;
56: col[1] = 1;
57: value[0] = 2.0;
58: value[1] = -1.0;
59: PetscCall(MatSetValues(A, 1, &i, 2, col, value, INSERT_VALUES));
61: i = 0;
62: col[0] = n - 1;
63: value[0] = 0.5; /* make A non-symmetric */
64: PetscCall(MatSetValues(A, 1, &i, 1, col, value, INSERT_VALUES));
65: }
66: PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
67: PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
69: /* Set exact solution */
70: PetscCall(VecSet(u, one));
72: /* Create linear solver context */
73: PetscCall(KSPCreate(PETSC_COMM_WORLD, &ksp));
74: PetscCall(KSPSetOperators(ksp, A, A));
75: PetscCall(KSPGetPC(ksp, &pc));
76: PetscCall(PCSetType(pc, PCLU));
77: #if defined(PETSC_HAVE_MUMPS)
78: if (size > 1) PetscCall(PCFactorSetMatSolverType(pc, MATSOLVERMUMPS));
79: #endif
80: PetscCall(KSPSetFromOptions(ksp));
82: /* 1. Solve linear system A x = b */
83: PetscCall(MatMult(A, u, b));
84: PetscCall(KSPSolve(ksp, b, x));
86: /* Check the error */
87: PetscCall(VecAXPY(x, -1.0, u));
88: PetscCall(VecNorm(x, NORM_2, &norm));
89: PetscCall(KSPGetIterationNumber(ksp, &its));
90: if (norm > tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "1. Norm of error for Ax=b: %g, Iterations %" PetscInt_FMT "\n", (double)norm, its));
92: /* 2. Solve linear system A^T x = b*/
93: PetscCall(MatMultTranspose(A, u, b));
94: PetscCall(KSPSolveTranspose(ksp, b, x2));
96: /* Check the error */
97: PetscCall(VecAXPY(x2, -1.0, u));
98: PetscCall(VecNorm(x2, NORM_2, &norm));
99: PetscCall(KSPGetIterationNumber(ksp, &its));
100: if (norm > tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "2. Norm of error for A^T x=b: %g, Iterations %" PetscInt_FMT "\n", (double)norm, its));
102: /* 3. Change A and solve A x = b with an iterative solver using A=LU as a preconditioner*/
103: if (rank == 0) {
104: i = 0;
105: col[0] = n - 1;
106: value[0] = 1.e-2;
107: PetscCall(MatSetValues(A, 1, &i, 1, col, value, ADD_VALUES));
108: }
109: PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
110: PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
112: PetscCall(MatMult(A, u, b));
113: PetscCall(KSPSolve(ksp, b, x));
115: /* Check the error */
116: PetscCall(VecAXPY(x, -1.0, u));
117: PetscCall(VecNorm(x, NORM_2, &norm));
118: PetscCall(KSPGetIterationNumber(ksp, &its));
119: if (norm > tol) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "3. Norm of error for (A+Delta) x=b: %g, Iterations %" PetscInt_FMT "\n", (double)norm, its));
121: /* Free work space. */
122: PetscCall(VecDestroy(&x));
123: PetscCall(VecDestroy(&u));
124: PetscCall(VecDestroy(&x2));
125: PetscCall(VecDestroy(&b));
126: PetscCall(MatDestroy(&A));
127: PetscCall(KSPDestroy(&ksp));
129: PetscCall(PetscFinalize());
130: return 0;
131: }
133: /*TEST
135: test:
136: requires: mumps
138: test:
139: suffix: 2
140: nsize: 2
141: requires: mumps
142: output_file: output/ex53.out
144: TEST*/