xref: /petsc/src/binding/petsc4py/demo/legacy/wrap-f2py/Bratu2D.F90 (revision 55a74a43bb44613d95e937906bec3b8c3581b432)
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