1! --------------------------------------------------------------------- 2! 3! Solid Fuel Ignition (SFI) problem. This problem is modeled by 4! the partial differential equation 5! 6! -Laplacian(u) - lambda * exp(u) = 0, 0 < x,y < 1, 7! 8! with boundary conditions 9! 10! u = 0 for x = 0, x = 1, y = 0, y = 1, 11! 12! A finite difference approximation with the usual 5-point stencil 13! is used to discretize the boundary value problem to obtain a 14! nonlinear system of equations. The problem is solved in a 2D 15! rectangular domain, using distributed arrays (DAs) to partition 16! the parallel grid. 17! 18! -------------------------------------------------------------------- 19 20#include <petsc/finclude/petscdm.h> 21 22module Bratu2D 23 24 use petsc 25 implicit none 26 27 type gridinfo 28 PetscInt mx, xs, xe, xm, gxs, gxe, gxm 29 PetscInt my, ys, ye, ym, gys, gye, gym 30 end type gridinfo 31 32contains 33 34 subroutine GetGridInfo(da, grd, ierr) 35 implicit none 36 DM da 37 type(gridinfo) grd 38 PetscErrorCode ierr 39 ! 40 PetscCall(DMDAGetInfo(da, PETSC_NULL_INTEGER, grd%mx, grd%my, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, ierr)) 41 PetscCall(DMDAGetCorners(da, grd%xs, grd%ys, PETSC_NULL_INTEGER, grd%xm, grd%ym, PETSC_NULL_INTEGER, ierr)) 42 PetscCall(DMDAGetGhostCorners(da, grd%gxs, grd%gys, PETSC_NULL_INTEGER, grd%gxm, grd%gym, PETSC_NULL_INTEGER, ierr)) 43 44 grd%xs = grd%xs + 1 45 grd%ys = grd%ys + 1 46 grd%gxs = grd%gxs + 1 47 grd%gys = grd%gys + 1 48 49 grd%ye = grd%ys + grd%ym - 1 50 grd%xe = grd%xs + grd%xm - 1 51 grd%gye = grd%gys + grd%gym - 1 52 grd%gxe = grd%gxs + grd%gxm - 1 53 54 end subroutine GetGridInfo 55 56 subroutine InitGuessLocal(grd, x, lambda, ierr) 57 implicit none 58 type(gridinfo) grd 59 PetscScalar x(grd%xs:grd%xe, grd%ys:grd%ye) 60 PetscReal lambda 61 PetscErrorCode ierr 62 ! 63 PetscInt i, j 64 PetscReal hx, hy, temp, temp1, one 65 66 one = 1.0 67 hx = one/(dble(grd%mx - 1)) 68 hy = one/(dble(grd%my - 1)) 69 temp1 = lambda/(lambda + one) 70 71 do j = grd%ys, grd%ye 72 temp = dble(min(j - 1, grd%my - j))*hy 73 do i = grd%xs, grd%xe 74 if (i == 1 .or. j == 1 .or. i == grd%mx .or. j == grd%my) then 75 ! boundary points 76 x(i, j) = 0.0 77 else 78 ! interior grid points 79 x(i, j) = temp1*sqrt(min(dble(min(i - 1, grd%mx - i)*hx), dble(temp))) 80 end if 81 end do 82 end do 83 ierr = 0 84 85 end subroutine InitGuessLocal 86 87 subroutine FunctionLocal(grd, x, f, lambda, ierr) 88 implicit none 89 type(gridinfo) grd 90 PetscScalar x(grd%gxs:grd%gxe, grd%gys:grd%gye) 91 PetscScalar f(grd%xs:grd%xe, grd%ys:grd%ye) 92 PetscReal lambda 93 PetscErrorCode ierr 94 ! 95 PetscInt i, j 96 PetscReal hx, hy, hxdhy, hydhx, sc, one, two 97 PetscScalar u, uxx, uyy 98 99 one = 1.0 100 two = 2.0 101 hx = one/dble(grd%mx - 1) 102 hy = one/dble(grd%my - 1) 103 sc = hx*hy 104 hxdhy = hx/hy 105 hydhx = hy/hx 106 107 do j = grd%ys, grd%ye 108 do i = grd%xs, grd%xe 109 if (i == 1 .or. j == 1 .or. i == grd%mx .or. j == grd%my) then 110 ! boundary points 111 f(i, j) = x(i, j) - 0.0 112 else 113 ! interior grid points 114 u = x(i, j) 115 uxx = (two*u - x(i - 1, j) - x(i + 1, j))*hydhx 116 uyy = (two*u - x(i, j - 1) - x(i, j + 1))*hxdhy 117 f(i, j) = uxx + uyy - lambda*exp(u)*sc 118 end if 119 end do 120 end do 121 ierr = 0 122 123 end subroutine FunctionLocal 124 125 subroutine JacobianLocal(grd, x, Jac, lambda, ierr) 126 implicit none 127 type(gridinfo) grd 128 PetscScalar x(grd%gxs:grd%gxe, grd%gys:grd%gye) 129 Mat Jac 130 PetscReal lambda 131 PetscErrorCode ierr 132 ! 133 PetscInt i, j, row(1), col(5) 134 PetscInt ione, ifive 135 PetscReal hx, hy, hxdhy, hydhx, sc, v(5), one, two 136 137 ione = 1 138 ifive = 5 139 one = 1.0 140 two = 2.0 141 hx = one/dble(grd%mx - 1) 142 hy = one/dble(grd%my - 1) 143 sc = hx*hy 144 hxdhy = hx/hy 145 hydhx = hy/hx 146 147 do j = grd%ys, grd%ye 148 row = (j - grd%gys)*grd%gxm + grd%xs - grd%gxs - 1 149 do i = grd%xs, grd%xe 150 row = row + 1 151 if (i == 1 .or. j == 1 .or. i == grd%mx .or. j == grd%my) then 152 ! boundary points 153 col(1) = row(1) 154 v(1) = one 155 PetscCall(MatSetValuesLocal(Jac, ione, row, ione, col, v, INSERT_VALUES, ierr)) 156 else 157 ! interior grid points 158 v(1) = -hxdhy 159 v(2) = -hydhx 160 v(3) = two*(hydhx + hxdhy) - lambda*exp(x(i, j))*sc 161 v(4) = -hydhx 162 v(5) = -hxdhy 163 col(1) = row(1) - grd%gxm 164 col(2) = row(1) - 1 165 col(3) = row(1) 166 col(4) = row(1) + 1 167 col(5) = row(1) + grd%gxm 168 PetscCall(MatSetValuesLocal(Jac, ione, row, ifive, col, v, INSERT_VALUES, ierr)) 169 end if 170 end do 171 end do 172 173 end subroutine JacobianLocal 174 175end module Bratu2D 176 177! -------------------------------------------------------------------- 178 179subroutine FormInitGuess(da, X, lambda, ierr) 180 use Bratu2D 181 implicit none 182 DM da 183 Vec X 184 PetscReal lambda 185 PetscErrorCode ierr 186 ! 187 type(gridinfo) :: grd 188 PetscScalar, pointer :: xx(:) 189 190 PetscCall(VecGetArray(X, xx, ierr)) 191 PetscCall(GetGridInfo(da, grd, ierr)) 192 PetscCall(InitGuessLocal(grd, xx, lambda, ierr)) 193 PetscCall(VecRestoreArray(X, xx, ierr)) 194 195end subroutine FormInitGuess 196 197subroutine FormFunction(da, X, F, lambda, ierr) 198 use Bratu2D 199 implicit none 200 DM da 201 Vec X 202 Vec F 203 PetscReal lambda 204 PetscErrorCode ierr 205 ! 206 type(gridinfo) :: grd 207 Vec :: localX 208 PetscScalar, pointer :: xx(:) 209 PetscScalar, pointer :: ff(:) 210 211 PetscCall(DMGetLocalVector(da, localX, ierr)) 212 PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, localX, ierr)) 213 PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, localX, ierr)) 214 215 PetscCall(VecGetArray(localX, xx, ierr)) 216 PetscCall(VecGetArray(F, ff, ierr)) 217 218 PetscCall(GetGridInfo(da, grd, ierr)) 219 PetscCall(FunctionLocal(grd, xx, ff, lambda, ierr)) 220 221 PetscCall(VecRestoreArray(F, ff, ierr)) 222 PetscCall(VecRestoreArray(localX, xx, ierr)) 223 PetscCall(DMRestoreLocalVector(da, localX, ierr)) 224 225end subroutine FormFunction 226 227subroutine FormJacobian(da, X, J, lambda, ierr) 228 use Bratu2D 229 implicit none 230 DM da 231 Vec X 232 Mat J 233 PetscReal lambda 234 PetscErrorCode ierr 235 ! 236 type(gridinfo) :: grd 237 Vec :: localX 238 PetscScalar, pointer :: xx(:) 239 240 PetscCall(DMGetLocalVector(da, localX, ierr)) 241 PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, localX, ierr)) 242 PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, localX, ierr)) 243 PetscCall(VecGetArray(localX, xx, ierr)) 244 245 PetscCall(GetGridInfo(da, grd, ierr)) 246 PetscCall(JacobianLocal(grd, xx, J, lambda, ierr)) 247 248 PetscCall(VecRestoreArray(localX, xx, ierr)) 249 PetscCall(DMRestoreLocalVector(da, localX, ierr)) 250 251 PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY, ierr)) 252 PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY, ierr)) 253 254end subroutine FormJacobian 255 256! -------------------------------------------------------------------- 257 258! Local Variables: 259! mode: f90 260! End: 261