xref: /petsc/src/ksp/pc/tests/ex5.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
1c4762a1bSJed Brown 
2c4762a1bSJed Brown static char help[] = "Tests the multigrid code.  The input parameters are:\n\
3c4762a1bSJed Brown   -x N              Use a mesh in the x direction of N.  \n\
4c4762a1bSJed Brown   -c N              Use N V-cycles.  \n\
5c4762a1bSJed Brown   -l N              Use N Levels.  \n\
6c4762a1bSJed Brown   -smooths N        Use N pre smooths and N post smooths.  \n\
7c4762a1bSJed Brown   -j                Use Jacobi smoother.  \n\
8c4762a1bSJed Brown   -a use additive multigrid \n\
9c4762a1bSJed Brown   -f use full multigrid (preconditioner variant) \n\
10c4762a1bSJed Brown This example also demonstrates matrix-free methods\n\n";
11c4762a1bSJed Brown 
12c4762a1bSJed Brown /*
13c4762a1bSJed Brown   This is not a good example to understand the use of multigrid with PETSc.
14c4762a1bSJed Brown */
15c4762a1bSJed Brown 
16c4762a1bSJed Brown #include <petscksp.h>
17c4762a1bSJed Brown 
18c4762a1bSJed Brown PetscErrorCode residual(Mat, Vec, Vec, Vec);
19c4762a1bSJed Brown PetscErrorCode gauss_seidel(PC, Vec, Vec, Vec, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *);
20c4762a1bSJed Brown PetscErrorCode jacobi_smoother(PC, Vec, Vec, Vec, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *);
21c4762a1bSJed Brown PetscErrorCode interpolate(Mat, Vec, Vec, Vec);
22c4762a1bSJed Brown PetscErrorCode restrct(Mat, Vec, Vec);
23c4762a1bSJed Brown PetscErrorCode Create1dLaplacian(PetscInt, Mat *);
24c4762a1bSJed Brown PetscErrorCode CalculateRhs(Vec);
25c4762a1bSJed Brown PetscErrorCode CalculateError(Vec, Vec, Vec, PetscReal *);
26c4762a1bSJed Brown PetscErrorCode CalculateSolution(PetscInt, Vec *);
27c4762a1bSJed Brown PetscErrorCode amult(Mat, Vec, Vec);
28f2fddbb2SStefano Zampini PetscErrorCode apply_pc(PC, Vec, Vec);
29c4762a1bSJed Brown 
30d71ae5a4SJacob Faibussowitsch int main(int Argc, char **Args)
31d71ae5a4SJacob Faibussowitsch {
32c4762a1bSJed Brown   PetscInt    x_mesh = 15, levels = 3, cycles = 1, use_jacobi = 0;
33c4762a1bSJed Brown   PetscInt    i, smooths = 1, *N, its;
34c4762a1bSJed Brown   PCMGType    am = PC_MG_MULTIPLICATIVE;
35c4762a1bSJed Brown   Mat         cmat, mat[20], fmat;
36c4762a1bSJed Brown   KSP         cksp, ksp[20], kspmg;
37c4762a1bSJed Brown   PetscReal   e[3]; /* l_2 error,max error, residual */
38c4762a1bSJed Brown   const char *shellname;
39c4762a1bSJed Brown   Vec         x, solution, X[20], R[20], B[20];
40c4762a1bSJed Brown   PC          pcmg, pc;
41c4762a1bSJed Brown   PetscBool   flg;
42c4762a1bSJed Brown 
439566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&Argc, &Args, (char *)0, help));
449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-x", &x_mesh, NULL));
459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-l", &levels, NULL));
469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-c", &cycles, NULL));
479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-smooths", &smooths, NULL));
489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, "-a", &flg));
49c4762a1bSJed Brown 
50c4762a1bSJed Brown   if (flg) am = PC_MG_ADDITIVE;
519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, "-f", &flg));
52c4762a1bSJed Brown   if (flg) am = PC_MG_FULL;
539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, "-j", &flg));
54c4762a1bSJed Brown   if (flg) use_jacobi = 1;
55c4762a1bSJed Brown 
569566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(levels, &N));
57c4762a1bSJed Brown   N[0] = x_mesh;
58c4762a1bSJed Brown   for (i = 1; i < levels; i++) {
59c4762a1bSJed Brown     N[i] = N[i - 1] / 2;
607827d75bSBarry Smith     PetscCheck(N[i] >= 1, PETSC_COMM_WORLD, PETSC_ERR_USER, "Too many levels or N is not large enough");
61c4762a1bSJed Brown   }
62c4762a1bSJed Brown 
639566063dSJacob Faibussowitsch   PetscCall(Create1dLaplacian(N[levels - 1], &cmat));
64c4762a1bSJed Brown 
659566063dSJacob Faibussowitsch   PetscCall(KSPCreate(PETSC_COMM_WORLD, &kspmg));
669566063dSJacob Faibussowitsch   PetscCall(KSPGetPC(kspmg, &pcmg));
679566063dSJacob Faibussowitsch   PetscCall(KSPSetFromOptions(kspmg));
689566063dSJacob Faibussowitsch   PetscCall(PCSetType(pcmg, PCMG));
699566063dSJacob Faibussowitsch   PetscCall(PCMGSetLevels(pcmg, levels, NULL));
709566063dSJacob Faibussowitsch   PetscCall(PCMGSetType(pcmg, am));
71c4762a1bSJed Brown 
729566063dSJacob Faibussowitsch   PetscCall(PCMGGetCoarseSolve(pcmg, &cksp));
739566063dSJacob Faibussowitsch   PetscCall(KSPSetOperators(cksp, cmat, cmat));
749566063dSJacob Faibussowitsch   PetscCall(KSPGetPC(cksp, &pc));
759566063dSJacob Faibussowitsch   PetscCall(PCSetType(pc, PCLU));
769566063dSJacob Faibussowitsch   PetscCall(KSPSetType(cksp, KSPPREONLY));
77c4762a1bSJed Brown 
78c4762a1bSJed Brown   /* zero is finest level */
79c4762a1bSJed Brown   for (i = 0; i < levels - 1; i++) {
80f2fddbb2SStefano Zampini     Mat dummy;
81f2fddbb2SStefano Zampini 
829566063dSJacob Faibussowitsch     PetscCall(PCMGSetResidual(pcmg, levels - 1 - i, residual, NULL));
839566063dSJacob Faibussowitsch     PetscCall(MatCreateShell(PETSC_COMM_WORLD, N[i + 1], N[i], N[i + 1], N[i], NULL, &mat[i]));
849566063dSJacob Faibussowitsch     PetscCall(MatShellSetOperation(mat[i], MATOP_MULT, (void (*)(void))restrct));
859566063dSJacob Faibussowitsch     PetscCall(MatShellSetOperation(mat[i], MATOP_MULT_TRANSPOSE_ADD, (void (*)(void))interpolate));
869566063dSJacob Faibussowitsch     PetscCall(PCMGSetInterpolation(pcmg, levels - 1 - i, mat[i]));
879566063dSJacob Faibussowitsch     PetscCall(PCMGSetRestriction(pcmg, levels - 1 - i, mat[i]));
889566063dSJacob Faibussowitsch     PetscCall(PCMGSetCycleTypeOnLevel(pcmg, levels - 1 - i, (PCMGCycleType)cycles));
89c4762a1bSJed Brown 
90c4762a1bSJed Brown     /* set smoother */
919566063dSJacob Faibussowitsch     PetscCall(PCMGGetSmoother(pcmg, levels - 1 - i, &ksp[i]));
929566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp[i], &pc));
939566063dSJacob Faibussowitsch     PetscCall(PCSetType(pc, PCSHELL));
949566063dSJacob Faibussowitsch     PetscCall(PCShellSetName(pc, "user_precond"));
959566063dSJacob Faibussowitsch     PetscCall(PCShellGetName(pc, &shellname));
9663a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "level=%" PetscInt_FMT ", PCShell name is %s\n", i, shellname));
97c4762a1bSJed Brown 
98f2fddbb2SStefano Zampini     /* this is not used unless different options are passed to the solver */
999566063dSJacob Faibussowitsch     PetscCall(MatCreateShell(PETSC_COMM_WORLD, N[i], N[i], N[i], N[i], NULL, &dummy));
1009566063dSJacob Faibussowitsch     PetscCall(MatShellSetOperation(dummy, MATOP_MULT, (void (*)(void))amult));
1019566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(ksp[i], dummy, dummy));
1029566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&dummy));
103f2fddbb2SStefano Zampini 
104c4762a1bSJed Brown     /*
105c4762a1bSJed Brown         We override the matrix passed in by forcing it to use Richardson with
106c4762a1bSJed Brown         a user provided application. This is non-standard and this practice
107c4762a1bSJed Brown         should be avoided.
108c4762a1bSJed Brown     */
1099566063dSJacob Faibussowitsch     PetscCall(PCShellSetApply(pc, apply_pc));
1109566063dSJacob Faibussowitsch     PetscCall(PCShellSetApplyRichardson(pc, gauss_seidel));
1111baa6e33SBarry Smith     if (use_jacobi) PetscCall(PCShellSetApplyRichardson(pc, jacobi_smoother));
1129566063dSJacob Faibussowitsch     PetscCall(KSPSetType(ksp[i], KSPRICHARDSON));
1139566063dSJacob Faibussowitsch     PetscCall(KSPSetInitialGuessNonzero(ksp[i], PETSC_TRUE));
1149566063dSJacob Faibussowitsch     PetscCall(KSPSetTolerances(ksp[i], PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, smooths));
115c4762a1bSJed Brown 
1169566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, N[i], &x));
117c4762a1bSJed Brown 
118c4762a1bSJed Brown     X[levels - 1 - i] = x;
11948a46eb9SPierre Jolivet     if (i > 0) PetscCall(PCMGSetX(pcmg, levels - 1 - i, x));
1209566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, N[i], &x));
121c4762a1bSJed Brown 
122c4762a1bSJed Brown     B[levels - 1 - i] = x;
12348a46eb9SPierre Jolivet     if (i > 0) PetscCall(PCMGSetRhs(pcmg, levels - 1 - i, x));
1249566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, N[i], &x));
125c4762a1bSJed Brown 
126c4762a1bSJed Brown     R[levels - 1 - i] = x;
127c4762a1bSJed Brown 
1289566063dSJacob Faibussowitsch     PetscCall(PCMGSetR(pcmg, levels - 1 - i, x));
129c4762a1bSJed Brown   }
130c4762a1bSJed Brown   /* create coarse level vectors */
1319566063dSJacob Faibussowitsch   PetscCall(VecCreateSeq(PETSC_COMM_SELF, N[levels - 1], &x));
1329371c9d4SSatish Balay   PetscCall(PCMGSetX(pcmg, 0, x));
1339371c9d4SSatish Balay   X[0] = x;
1349566063dSJacob Faibussowitsch   PetscCall(VecCreateSeq(PETSC_COMM_SELF, N[levels - 1], &x));
1359371c9d4SSatish Balay   PetscCall(PCMGSetRhs(pcmg, 0, x));
1369371c9d4SSatish Balay   B[0] = x;
137c4762a1bSJed Brown 
138c4762a1bSJed Brown   /* create matrix multiply for finest level */
1399566063dSJacob Faibussowitsch   PetscCall(MatCreateShell(PETSC_COMM_WORLD, N[0], N[0], N[0], N[0], NULL, &fmat));
1409566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(fmat, MATOP_MULT, (void (*)(void))amult));
1419566063dSJacob Faibussowitsch   PetscCall(KSPSetOperators(kspmg, fmat, fmat));
142c4762a1bSJed Brown 
1439566063dSJacob Faibussowitsch   PetscCall(CalculateSolution(N[0], &solution));
1449566063dSJacob Faibussowitsch   PetscCall(CalculateRhs(B[levels - 1]));
1459566063dSJacob Faibussowitsch   PetscCall(VecSet(X[levels - 1], 0.0));
146c4762a1bSJed Brown 
1479566063dSJacob Faibussowitsch   PetscCall(residual((Mat)0, B[levels - 1], X[levels - 1], R[levels - 1]));
1489566063dSJacob Faibussowitsch   PetscCall(CalculateError(solution, X[levels - 1], R[levels - 1], e));
1499566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "l_2 error %g max error %g resi %g\n", (double)e[0], (double)e[1], (double)e[2]));
150c4762a1bSJed Brown 
1519566063dSJacob Faibussowitsch   PetscCall(KSPSolve(kspmg, B[levels - 1], X[levels - 1]));
1529566063dSJacob Faibussowitsch   PetscCall(KSPGetIterationNumber(kspmg, &its));
1539566063dSJacob Faibussowitsch   PetscCall(residual((Mat)0, B[levels - 1], X[levels - 1], R[levels - 1]));
1549566063dSJacob Faibussowitsch   PetscCall(CalculateError(solution, X[levels - 1], R[levels - 1], e));
15563a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "its %" PetscInt_FMT " l_2 error %g max error %g resi %g\n", its, (double)e[0], (double)e[1], (double)e[2]));
156c4762a1bSJed Brown 
1579566063dSJacob Faibussowitsch   PetscCall(PetscFree(N));
1589566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&solution));
159c4762a1bSJed Brown 
160c4762a1bSJed Brown   /* note we have to keep a list of all vectors allocated, this is
161c4762a1bSJed Brown      not ideal, but putting it in MGDestroy is not so good either*/
162c4762a1bSJed Brown   for (i = 0; i < levels; i++) {
1639566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&X[i]));
1649566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&B[i]));
1659566063dSJacob Faibussowitsch     if (i) PetscCall(VecDestroy(&R[i]));
166c4762a1bSJed Brown   }
16748a46eb9SPierre Jolivet   for (i = 0; i < levels - 1; i++) PetscCall(MatDestroy(&mat[i]));
1689566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&cmat));
1699566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&fmat));
1709566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&kspmg));
1719566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
172b122ec5aSJacob Faibussowitsch   return 0;
173c4762a1bSJed Brown }
174c4762a1bSJed Brown 
175d71ae5a4SJacob Faibussowitsch PetscErrorCode residual(Mat mat, Vec bb, Vec xx, Vec rr)
176d71ae5a4SJacob Faibussowitsch {
177c4762a1bSJed Brown   PetscInt           i, n1;
178c4762a1bSJed Brown   PetscScalar       *x, *r;
179c4762a1bSJed Brown   const PetscScalar *b;
180c4762a1bSJed Brown 
181c4762a1bSJed Brown   PetscFunctionBegin;
1829566063dSJacob Faibussowitsch   PetscCall(VecGetSize(bb, &n1));
1839566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
1849566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
1859566063dSJacob Faibussowitsch   PetscCall(VecGetArray(rr, &r));
186c4762a1bSJed Brown   n1--;
187c4762a1bSJed Brown   r[0]  = b[0] + x[1] - 2.0 * x[0];
188c4762a1bSJed Brown   r[n1] = b[n1] + x[n1 - 1] - 2.0 * x[n1];
189c4762a1bSJed Brown   for (i = 1; i < n1; i++) r[i] = b[i] + x[i + 1] + x[i - 1] - 2.0 * x[i];
1909566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
1919566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
1929566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(rr, &r));
193*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
194c4762a1bSJed Brown }
195f2fddbb2SStefano Zampini 
196d71ae5a4SJacob Faibussowitsch PetscErrorCode amult(Mat mat, Vec xx, Vec yy)
197d71ae5a4SJacob Faibussowitsch {
198c4762a1bSJed Brown   PetscInt           i, n1;
199c4762a1bSJed Brown   PetscScalar       *y;
200c4762a1bSJed Brown   const PetscScalar *x;
201c4762a1bSJed Brown 
202c4762a1bSJed Brown   PetscFunctionBegin;
2039566063dSJacob Faibussowitsch   PetscCall(VecGetSize(xx, &n1));
2049566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
2059566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
206c4762a1bSJed Brown   n1--;
207c4762a1bSJed Brown   y[0]  = -x[1] + 2.0 * x[0];
208c4762a1bSJed Brown   y[n1] = -x[n1 - 1] + 2.0 * x[n1];
209c4762a1bSJed Brown   for (i = 1; i < n1; i++) y[i] = -x[i + 1] - x[i - 1] + 2.0 * x[i];
2109566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
2119566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
212*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
213c4762a1bSJed Brown }
214f2fddbb2SStefano Zampini 
215d71ae5a4SJacob Faibussowitsch PetscErrorCode apply_pc(PC pc, Vec bb, Vec xx)
216d71ae5a4SJacob Faibussowitsch {
217f2fddbb2SStefano Zampini   PetscFunctionBegin;
218f2fddbb2SStefano Zampini   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Not implemented");
219f2fddbb2SStefano Zampini }
220f2fddbb2SStefano Zampini 
221d71ae5a4SJacob Faibussowitsch PetscErrorCode gauss_seidel(PC pc, Vec bb, Vec xx, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt m, PetscBool guesszero, PetscInt *its, PCRichardsonConvergedReason *reason)
222d71ae5a4SJacob Faibussowitsch {
223c4762a1bSJed Brown   PetscInt           i, n1;
224c4762a1bSJed Brown   PetscScalar       *x;
225c4762a1bSJed Brown   const PetscScalar *b;
226c4762a1bSJed Brown 
227c4762a1bSJed Brown   PetscFunctionBegin;
228c4762a1bSJed Brown   *its    = m;
229c4762a1bSJed Brown   *reason = PCRICHARDSON_CONVERGED_ITS;
2309371c9d4SSatish Balay   PetscCall(VecGetSize(bb, &n1));
2319371c9d4SSatish Balay   n1--;
2329566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
2339566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
234c4762a1bSJed Brown   while (m--) {
235c4762a1bSJed Brown     x[0] = .5 * (x[1] + b[0]);
236c4762a1bSJed Brown     for (i = 1; i < n1; i++) x[i] = .5 * (x[i + 1] + x[i - 1] + b[i]);
237c4762a1bSJed Brown     x[n1] = .5 * (x[n1 - 1] + b[n1]);
238c4762a1bSJed Brown     for (i = n1 - 1; i > 0; i--) x[i] = .5 * (x[i + 1] + x[i - 1] + b[i]);
239c4762a1bSJed Brown     x[0] = .5 * (x[1] + b[0]);
240c4762a1bSJed Brown   }
2419566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
2429566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
243*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
244c4762a1bSJed Brown }
245f1580f4eSBarry Smith 
246d71ae5a4SJacob Faibussowitsch PetscErrorCode jacobi_smoother(PC pc, Vec bb, Vec xx, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt m, PetscBool guesszero, PetscInt *its, PCRichardsonConvergedReason *reason)
247d71ae5a4SJacob Faibussowitsch {
248c4762a1bSJed Brown   PetscInt           i, n, n1;
249c4762a1bSJed Brown   PetscScalar       *r, *x;
250c4762a1bSJed Brown   const PetscScalar *b;
251c4762a1bSJed Brown 
252c4762a1bSJed Brown   PetscFunctionBegin;
253c4762a1bSJed Brown   *its    = m;
254c4762a1bSJed Brown   *reason = PCRICHARDSON_CONVERGED_ITS;
2559371c9d4SSatish Balay   PetscCall(VecGetSize(bb, &n));
2569371c9d4SSatish Balay   n1 = n - 1;
2579566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
2589566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
2599566063dSJacob Faibussowitsch   PetscCall(VecGetArray(w, &r));
260c4762a1bSJed Brown 
261c4762a1bSJed Brown   while (m--) {
262c4762a1bSJed Brown     r[0] = .5 * (x[1] + b[0]);
263c4762a1bSJed Brown     for (i = 1; i < n1; i++) r[i] = .5 * (x[i + 1] + x[i - 1] + b[i]);
264c4762a1bSJed Brown     r[n1] = .5 * (x[n1 - 1] + b[n1]);
265c4762a1bSJed Brown     for (i = 0; i < n; i++) x[i] = (2.0 * r[i] + x[i]) / 3.0;
266c4762a1bSJed Brown   }
2679566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
2689566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
2699566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(w, &r));
270*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
271c4762a1bSJed Brown }
272c4762a1bSJed Brown /*
273c4762a1bSJed Brown    We know for this application that yy  and zz are the same
274c4762a1bSJed Brown */
275f1580f4eSBarry Smith 
276d71ae5a4SJacob Faibussowitsch PetscErrorCode interpolate(Mat mat, Vec xx, Vec yy, Vec zz)
277d71ae5a4SJacob Faibussowitsch {
278c4762a1bSJed Brown   PetscInt           i, n, N, i2;
279c4762a1bSJed Brown   PetscScalar       *y;
280c4762a1bSJed Brown   const PetscScalar *x;
281c4762a1bSJed Brown 
282c4762a1bSJed Brown   PetscFunctionBegin;
2839566063dSJacob Faibussowitsch   PetscCall(VecGetSize(yy, &N));
2849566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
2859566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
286c4762a1bSJed Brown   n = N / 2;
287c4762a1bSJed Brown   for (i = 0; i < n; i++) {
288c4762a1bSJed Brown     i2 = 2 * i;
289c4762a1bSJed Brown     y[i2] += .5 * x[i];
290c4762a1bSJed Brown     y[i2 + 1] += x[i];
291c4762a1bSJed Brown     y[i2 + 2] += .5 * x[i];
292c4762a1bSJed Brown   }
2939566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
2949566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
295*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
296c4762a1bSJed Brown }
297f1580f4eSBarry Smith 
298d71ae5a4SJacob Faibussowitsch PetscErrorCode restrct(Mat mat, Vec rr, Vec bb)
299d71ae5a4SJacob Faibussowitsch {
300c4762a1bSJed Brown   PetscInt           i, n, N, i2;
301c4762a1bSJed Brown   PetscScalar       *b;
302c4762a1bSJed Brown   const PetscScalar *r;
303c4762a1bSJed Brown 
304c4762a1bSJed Brown   PetscFunctionBegin;
3059566063dSJacob Faibussowitsch   PetscCall(VecGetSize(rr, &N));
3069566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(rr, &r));
3079566063dSJacob Faibussowitsch   PetscCall(VecGetArray(bb, &b));
308c4762a1bSJed Brown   n = N / 2;
309c4762a1bSJed Brown 
310c4762a1bSJed Brown   for (i = 0; i < n; i++) {
311c4762a1bSJed Brown     i2   = 2 * i;
312c4762a1bSJed Brown     b[i] = (r[i2] + 2.0 * r[i2 + 1] + r[i2 + 2]);
313c4762a1bSJed Brown   }
3149566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(rr, &r));
3159566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(bb, &b));
316*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
317c4762a1bSJed Brown }
318f1580f4eSBarry Smith 
319d71ae5a4SJacob Faibussowitsch PetscErrorCode Create1dLaplacian(PetscInt n, Mat *mat)
320d71ae5a4SJacob Faibussowitsch {
321c4762a1bSJed Brown   PetscScalar mone = -1.0, two = 2.0;
322c4762a1bSJed Brown   PetscInt    i, idx;
323c4762a1bSJed Brown 
324c4762a1bSJed Brown   PetscFunctionBegin;
3259566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, n, n, 3, NULL, mat));
326c4762a1bSJed Brown 
327c4762a1bSJed Brown   idx = n - 1;
3289566063dSJacob Faibussowitsch   PetscCall(MatSetValues(*mat, 1, &idx, 1, &idx, &two, INSERT_VALUES));
329c4762a1bSJed Brown   for (i = 0; i < n - 1; i++) {
3309566063dSJacob Faibussowitsch     PetscCall(MatSetValues(*mat, 1, &i, 1, &i, &two, INSERT_VALUES));
331c4762a1bSJed Brown     idx = i + 1;
3329566063dSJacob Faibussowitsch     PetscCall(MatSetValues(*mat, 1, &idx, 1, &i, &mone, INSERT_VALUES));
3339566063dSJacob Faibussowitsch     PetscCall(MatSetValues(*mat, 1, &i, 1, &idx, &mone, INSERT_VALUES));
334c4762a1bSJed Brown   }
3359566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY));
3369566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY));
337*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
338c4762a1bSJed Brown }
339f1580f4eSBarry Smith 
340d71ae5a4SJacob Faibussowitsch PetscErrorCode CalculateRhs(Vec u)
341d71ae5a4SJacob Faibussowitsch {
342c4762a1bSJed Brown   PetscInt    i, n;
3435f80ce2aSJacob Faibussowitsch   PetscReal   h;
344c4762a1bSJed Brown   PetscScalar uu;
345c4762a1bSJed Brown 
346c4762a1bSJed Brown   PetscFunctionBegin;
3479566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &n));
348c4762a1bSJed Brown   h = 1.0 / ((PetscReal)(n + 1));
349c4762a1bSJed Brown   for (i = 0; i < n; i++) {
3505f80ce2aSJacob Faibussowitsch     uu = 2.0 * h * h;
3519566063dSJacob Faibussowitsch     PetscCall(VecSetValues(u, 1, &i, &uu, INSERT_VALUES));
352c4762a1bSJed Brown   }
353*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
354c4762a1bSJed Brown }
355f1580f4eSBarry Smith 
356d71ae5a4SJacob Faibussowitsch PetscErrorCode CalculateSolution(PetscInt n, Vec *solution)
357d71ae5a4SJacob Faibussowitsch {
358c4762a1bSJed Brown   PetscInt    i;
359c4762a1bSJed Brown   PetscReal   h, x = 0.0;
360c4762a1bSJed Brown   PetscScalar uu;
361c4762a1bSJed Brown 
362c4762a1bSJed Brown   PetscFunctionBegin;
3639566063dSJacob Faibussowitsch   PetscCall(VecCreateSeq(PETSC_COMM_SELF, n, solution));
364c4762a1bSJed Brown   h = 1.0 / ((PetscReal)(n + 1));
365c4762a1bSJed Brown   for (i = 0; i < n; i++) {
3669371c9d4SSatish Balay     x += h;
3679371c9d4SSatish Balay     uu = x * (1. - x);
3689566063dSJacob Faibussowitsch     PetscCall(VecSetValues(*solution, 1, &i, &uu, INSERT_VALUES));
369c4762a1bSJed Brown   }
370*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
371c4762a1bSJed Brown }
372f1580f4eSBarry Smith 
373d71ae5a4SJacob Faibussowitsch PetscErrorCode CalculateError(Vec solution, Vec u, Vec r, PetscReal *e)
374d71ae5a4SJacob Faibussowitsch {
375c4762a1bSJed Brown   PetscFunctionBegin;
3769566063dSJacob Faibussowitsch   PetscCall(VecNorm(r, NORM_2, e + 2));
3779566063dSJacob Faibussowitsch   PetscCall(VecWAXPY(r, -1.0, u, solution));
3789566063dSJacob Faibussowitsch   PetscCall(VecNorm(r, NORM_2, e));
3799566063dSJacob Faibussowitsch   PetscCall(VecNorm(r, NORM_1, e + 1));
380*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
381c4762a1bSJed Brown }
382c4762a1bSJed Brown 
383c4762a1bSJed Brown /*TEST
384c4762a1bSJed Brown 
385c4762a1bSJed Brown    test:
386c4762a1bSJed Brown 
387c4762a1bSJed Brown TEST*/
388