Actual source code: ex8.c
1: static char help[] = "Solves the Poisson equation using DMStag, with a single field in 1D,\n"
2: "intended to demonstrate the simplest use of geometric multigrid\n\n";
4: #include <petscdm.h>
5: #include <petscksp.h>
6: #include <petscdmstag.h>
8: static PetscErrorCode AssembleSystem(DM, Mat *, Vec *);
10: int main(int argc, char **argv)
11: {
12: Mat A;
13: Vec x, b;
14: KSP ksp;
15: DM dm;
16: PetscInt dim;
19: PetscInitialize(&argc, &argv, (char *)0, help);
21: dim = 1;
23: /* Create a DMStag object with a single degree of freedom for each point
24: on a single stratum, either vertices (0-cells) or elements (d-cells in d dimensions) */
25: if (dim == 1) {
26: PetscCall(DMStagCreate1d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, 8, /* Global element count */
27: 1, /* Unknowns per vertex */
28: 0, /* Unknowns per element */
29: DMSTAG_STENCIL_BOX, 1, /* Elementwise stencil width */
30: NULL, &dm));
31: } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Unsupported dimension: %" PetscInt_FMT, dim);
32: DMSetFromOptions(dm);
33: DMSetUp(dm);
35: /* Assemble the discrete system */
36: AssembleSystem(dm, &A, &b);
38: /* Solve */
39: KSPCreate(PetscObjectComm((PetscObject)dm), &ksp);
40: KSPSetType(ksp, KSPFGMRES);
41: KSPSetOperators(ksp, A, A);
42: KSPSetDM(ksp, dm);
43: KSPSetDMActive(ksp, PETSC_FALSE);
44: KSPSetFromOptions(ksp);
45: VecDuplicate(b, &x);
46: KSPSolve(ksp, b, x);
47: {
48: KSPConvergedReason reason;
50: KSPGetConvergedReason(ksp, &reason);
52: }
54: /* Destroy PETSc objects and finalize */
55: MatDestroy(&A);
56: VecDestroy(&x);
57: VecDestroy(&b);
58: KSPDestroy(&ksp);
59: DMDestroy(&dm);
60: PetscFinalize();
61: return 0;
62: }
64: static PetscErrorCode AssembleSystem1DVertexCentered(DM dm, Mat *pA, Vec *pb)
65: {
66: Mat A;
67: Vec b;
68: PetscInt start, n, n_extra, N;
72: DMCreateMatrix(dm, pA);
73: A = *pA;
74: DMCreateGlobalVector(dm, pb);
75: b = *pb;
76: DMStagGetCorners(dm, &start, NULL, NULL, &n, NULL, NULL, &n_extra, NULL, NULL);
77: DMStagGetGlobalSizes(dm, &N, NULL, NULL);
79: /* Loop over all elements, including the non-physical, extra one past the right boundary */
80: for (PetscInt e = start; e < start + n + n_extra; ++e) {
81: DMStagStencil row;
83: row.i = e;
84: row.c = 0;
85: row.loc = DMSTAG_LEFT;
87: if (e == 0) {
88: /* Left bondary conditions (Dirichlet) */
89: PetscScalar val;
91: val = 1.0;
92: DMStagMatSetValuesStencil(dm, A, 1, &row, 1, &row, &val, INSERT_VALUES);
93: } else if (e == N) {
94: /* Right boundary (Dirichlet Boundary conditions)*/
95: DMStagStencil row_extra;
96: PetscScalar val;
98: row_extra.i = e;
99: row_extra.c = 0;
100: row_extra.loc = DMSTAG_LEFT;
101: val = 1.0;
103: DMStagMatSetValuesStencil(dm, A, 1, &row_extra, 1, &row_extra, &val, INSERT_VALUES);
104: } else {
105: /* Interior */
106: DMStagStencil col[3];
107: PetscScalar val[3];
109: col[0].i = e - 1;
110: col[0].c = 0;
111: col[0].loc = DMSTAG_LEFT;
112: val[0] = 1.0;
113: col[1].i = e;
114: col[1].c = 0;
115: col[1].loc = DMSTAG_LEFT;
116: val[1] = -2.0;
117: col[2].i = e + 1;
118: col[2].c = 0;
119: col[2].loc = DMSTAG_LEFT;
120: val[2] = 1.0;
122: DMStagMatSetValuesStencil(dm, A, 1, &row, 3, col, val, INSERT_VALUES);
123: }
125: /* Forcing */
126: {
127: PetscScalar x, f, h;
129: h = 1.0 / N; /* Assume a constant spacing instead of accessing coordinates */
130: x = e / ((PetscScalar)N); // 0 - 1
131: f = (x - 0.5) * h * h; // Scale by h^2
132: DMStagVecSetValuesStencil(dm, b, 1, &row, &f, INSERT_VALUES);
133: }
134: }
136: MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);
137: MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);
138: VecAssemblyBegin(b);
139: VecAssemblyEnd(b);
141: return 0;
142: }
144: PetscErrorCode AssembleSystem(DM dm, Mat *pA, Vec *pb)
145: {
146: PetscInt dim;
149: DMSetMatrixPreallocateOnly(dm, PETSC_TRUE);
150: DMGetDimension(dm, &dim);
151: switch (dim) {
152: case 1:
153: AssembleSystem1DVertexCentered(dm, pA, pb);
154: break;
155: default:
156: SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Unsupported dimension: %" PetscInt_FMT, dim);
157: }
158: return 0;
159: }
161: /*TEST
162: test:
163: args: -pc_type mg -pc_mg_galerkin -pc_mg_levels 7 -stag_grid_x 512 -ksp_converged_reason
165: TEST*/