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