Actual source code: ex45f.F90
1: program main
2: #include <petsc/finclude/petscdmda.h>
3: #include <petsc/finclude/petscksp.h>
4: use petscdm
5: use petscdmda
6: use petscksp
7: implicit none
9: PetscInt is, js, iw, jw
10: PetscInt one, three
11: PetscErrorCode ierr
12: KSP ksp
13: DM dm
14: external ComputeRHS, ComputeMatrix, ComputeInitialGuess
16: one = 1
17: three = 3
19: PetscCallA(PetscInitialize(ierr))
20: PetscCallA(KSPCreate(PETSC_COMM_WORLD, ksp, ierr))
21: PetscCallA(DMDACreate2D(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DMDA_STENCIL_STAR, three, three, PETSC_DECIDE, PETSC_DECIDE, one, one, PETSC_NULL_INTEGER_ARRAY, PETSC_NULL_INTEGER_ARRAY, dm, ierr))
22: PetscCallA(DMSetFromOptions(dm, ierr))
23: PetscCallA(DMSetUp(dm, ierr))
24: PetscCallA(KSPSetDM(ksp, dm, ierr))
25: PetscCallA(KSPSetComputeInitialGuess(ksp, ComputeInitialGuess, 0, ierr))
26: PetscCallA(KSPSetComputeRHS(ksp, ComputeRHS, 0, ierr))
27: PetscCallA(KSPSetComputeOperators(ksp, ComputeMatrix, 0, ierr))
28: PetscCallA(DMDAGetCorners(dm, is, js, PETSC_NULL_INTEGER, iw, jw, PETSC_NULL_INTEGER, ierr))
29: PetscCallA(KSPSetFromOptions(ksp, ierr))
30: PetscCallA(KSPSetUp(ksp, ierr))
31: PetscCallA(KSPSolve(ksp, PETSC_NULL_VEC, PETSC_NULL_VEC, ierr))
32: PetscCallA(KSPDestroy(ksp, ierr))
33: PetscCallA(DMDestroy(dm, ierr))
34: PetscCallA(PetscFinalize(ierr))
35: end
37: subroutine ComputeInitialGuess(ksp, b, ctx, ierr)
38: use petsckspdef
39: use petscvec
40: implicit none
41: PetscErrorCode ierr
42: KSP ksp
43: PetscInt ctx(*)
44: Vec b
45: PetscScalar h
47: h = 0.0
48: PetscCall(VecSet(b, h, ierr))
49: end subroutine
51: subroutine ComputeRHS(ksp, b, dummy, ierr)
52: use petscksp
53: use petscdmda
54: use petscvec
55: implicit none
57: PetscErrorCode ierr
58: KSP ksp
59: Vec b
60: integer dummy(*)
61: PetscScalar h, Hx, Hy
62: PetscInt mx, my
63: DM dm
65: PetscCall(KSPGetDM(ksp, dm, ierr))
66: PetscCall(DMDAGetInfo(dm, PETSC_NULL_INTEGER, mx, my, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_DMBOUNDARYTYPE, PETSC_NULL_DMBOUNDARYTYPE, PETSC_NULL_DMBOUNDARYTYPE, PETSC_NULL_DMDASTENCILTYPE, ierr))
68: Hx = 1.0/real(mx - 1)
69: Hy = 1.0/real(my - 1)
70: h = Hx*Hy
71: PetscCall(VecSet(b, h, ierr))
72: end subroutine
74: subroutine ComputeMatrix(ksp, A, B, dummy, ierr)
75: use petscmat
76: use petscksp
77: use petscdmda
78: implicit none
79: PetscErrorCode ierr
80: KSP ksp
81: Mat A, B
82: integer dummy(*)
83: DM dm
85: PetscInt i, j, mx, my, xm
86: PetscInt ym, xs, ys, i1, i5
87: PetscScalar v(5), Hx, Hy
88: PetscScalar HxdHy, HydHx
89: MatStencil row(1), col(5)
91: i1 = 1
92: i5 = 5
93: PetscCall(KSPGetDM(ksp, dm, ierr))
94: PetscCall(DMDAGetInfo(dm, PETSC_NULL_INTEGER, mx, my, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_DMBOUNDARYTYPE, PETSC_NULL_DMBOUNDARYTYPE, PETSC_NULL_DMBOUNDARYTYPE, PETSC_NULL_DMDASTENCILTYPE, ierr))
96: Hx = 1.0/real(mx - 1)
97: Hy = 1.0/real(my - 1)
98: HxdHy = Hx/Hy
99: HydHx = Hy/Hx
100: PetscCall(DMDAGetCorners(dm, xs, ys, PETSC_NULL_INTEGER, xm, ym, PETSC_NULL_INTEGER, ierr))
101: do 10, j = ys, ys + ym - 1
102: do 20, i = xs, xs + xm - 1
103: row(1)%i = i
104: row(1)%j = j
105: if (i == 0 .or. j == 0 .or. i == mx - 1 .or. j == my - 1) then
106: v(1) = 2.0*(HxdHy + HydHx)
107: PetscCall(MatSetValuesStencil(B, i1, row, i1, row, v, INSERT_VALUES, ierr))
108: else
109: v(1) = -HxdHy
110: col(1)%i = i
111: col(1)%j = j - 1
112: v(2) = -HydHx
113: col(2)%i = i - 1
114: col(2)%j = j
115: v(3) = 2.0*(HxdHy + HydHx)
116: col(3)%i = i
117: col(3)%j = j
118: v(4) = -HydHx
119: col(4)%i = i + 1
120: col(4)%j = j
121: v(5) = -HxdHy
122: col(5)%i = i
123: col(5)%j = j + 1
124: PetscCall(MatSetValuesStencil(B, i1, row, i5, col, v, INSERT_VALUES, ierr))
125: end if
126: 20 continue
127: 10 continue
128: PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY, ierr))
129: PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY, ierr))
130: if (A /= B) then
131: PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY, ierr))
132: PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY, ierr))
133: end if
134: end subroutine
136: !/*TEST
137: !
138: ! test:
139: ! nsize: 4
140: ! args: -ksp_monitor_short -da_refine 5 -pc_type mg -pc_mg_levels 5 -mg_levels_ksp_type chebyshev -mg_levels_ksp_max_it 2 -mg_levels_pc_type jacobi -ksp_pc_side right
141: !
142: !TEST*/