xref: /petsc/src/snes/tutorials/ex73f90t.F90 (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
1*c4762a1bSJed Brown!
2*c4762a1bSJed Brown!  Description: Solves a nonlinear system in parallel with SNES.
3*c4762a1bSJed Brown!  We solve the  Bratu (SFI - solid fuel ignition) problem in a 2D rectangular
4*c4762a1bSJed Brown!  domain, using distributed arrays (DMDAs) to partition the parallel grid.
5*c4762a1bSJed Brown!  The command line options include:
6*c4762a1bSJed Brown!    -par <parameter>, where <parameter> indicates the nonlinearity of the problem
7*c4762a1bSJed Brown!       problem SFI:  <parameter> = Bratu parameter (0 <= par <= 6.81)
8*c4762a1bSJed Brown!
9*c4762a1bSJed Brown!  This system (A) is augmented with constraints:
10*c4762a1bSJed Brown!
11*c4762a1bSJed Brown!    A -B   *  phi  =  rho
12*c4762a1bSJed Brown!   -C  I      lam  = 0
13*c4762a1bSJed Brown!
14*c4762a1bSJed Brown!  where I is the identity, A is the "normal" Poisson equation, B is the "distributor" of the
15*c4762a1bSJed Brown!  total flux (the first block equation is the flux surface averaging equation).  The second
16*c4762a1bSJed Brown!  equation  lambda = C * x enforces the surface flux auxiliary equation.  B and C have all
17*c4762a1bSJed Brown!  positive entries, areas in C and fraction of area in B.
18*c4762a1bSJed Brown!
19*c4762a1bSJed Brown!!/*T
20*c4762a1bSJed Brown!  Concepts: SNES^parallel Bratu example
21*c4762a1bSJed Brown!  Concepts: MatNest
22*c4762a1bSJed Brown!  Processors: n
23*c4762a1bSJed Brown!T*/
24*c4762a1bSJed Brown
25*c4762a1bSJed Brown
26*c4762a1bSJed Brown!
27*c4762a1bSJed Brown!  --------------------------------------------------------------------------
28*c4762a1bSJed Brown!
29*c4762a1bSJed Brown!  Solid Fuel Ignition (SFI) problem.  This problem is modeled by
30*c4762a1bSJed Brown!  the partial differential equation
31*c4762a1bSJed Brown!
32*c4762a1bSJed Brown!          -Laplacian u - lambda*exp(u) = 0,  0 < x,y < 1,
33*c4762a1bSJed Brown!
34*c4762a1bSJed Brown!  with boundary conditions
35*c4762a1bSJed Brown!
36*c4762a1bSJed Brown!           u = 0  for  x = 0, x = 1, y = 0, y = 1.
37*c4762a1bSJed Brown!
38*c4762a1bSJed Brown!  A finite difference approximation with the usual 5-point stencil
39*c4762a1bSJed Brown!  is used to discretize the boundary value problem to obtain a nonlinear
40*c4762a1bSJed Brown!  system of equations.
41*c4762a1bSJed Brown!
42*c4762a1bSJed Brown!  --------------------------------------------------------------------------
43*c4762a1bSJed Brown!  The following define must be used before including any PETSc include files
44*c4762a1bSJed Brown!  into a module or interface. This is because they can't handle declarations
45*c4762a1bSJed Brown!  in them
46*c4762a1bSJed Brown!
47*c4762a1bSJed Brown      module petsc_kkt_solver
48*c4762a1bSJed Brown#include <petsc/finclude/petscdm.h>
49*c4762a1bSJed Brown#include <petsc/finclude/petscmat.h>
50*c4762a1bSJed Brown      use petscdm
51*c4762a1bSJed Brown      use petscmat
52*c4762a1bSJed Brown      type petsc_kkt_solver_type
53*c4762a1bSJed Brown        DM::da
54*c4762a1bSJed Brown!     temp A block stuff
55*c4762a1bSJed Brown        PetscInt mx,my
56*c4762a1bSJed Brown        PetscMPIInt rank
57*c4762a1bSJed Brown        PetscReal lambda
58*c4762a1bSJed Brown!     Mats
59*c4762a1bSJed Brown        Mat::Amat,AmatLin,Bmat,CMat,Dmat
60*c4762a1bSJed Brown        IS::isPhi,isLambda
61*c4762a1bSJed Brown      end type petsc_kkt_solver_type
62*c4762a1bSJed Brown
63*c4762a1bSJed Brown      end module petsc_kkt_solver
64*c4762a1bSJed Brown
65*c4762a1bSJed Brown      module petsc_kkt_solver_interfaces
66*c4762a1bSJed Brown        use petsc_kkt_solver
67*c4762a1bSJed Brown
68*c4762a1bSJed Brown      Interface SNESSetApplicationContext
69*c4762a1bSJed Brown        Subroutine SNESSetApplicationContext(snesIn,ctx,ierr)
70*c4762a1bSJed Brown#include <petsc/finclude/petscsnes.h>
71*c4762a1bSJed Brown        use petscsnes
72*c4762a1bSJed Brown        use petsc_kkt_solver
73*c4762a1bSJed Brown          SNES::    snesIn
74*c4762a1bSJed Brown          type(petsc_kkt_solver_type) ctx
75*c4762a1bSJed Brown          PetscErrorCode ierr
76*c4762a1bSJed Brown        End Subroutine
77*c4762a1bSJed Brown      End Interface SNESSetApplicationContext
78*c4762a1bSJed Brown
79*c4762a1bSJed Brown      Interface SNESGetApplicationContext
80*c4762a1bSJed Brown        Subroutine SNESGetApplicationContext(snesIn,ctx,ierr)
81*c4762a1bSJed Brown#include <petsc/finclude/petscsnes.h>
82*c4762a1bSJed Brown        use petscsnes
83*c4762a1bSJed Brown        use petsc_kkt_solver
84*c4762a1bSJed Brown          SNES::     snesIn
85*c4762a1bSJed Brown          type(petsc_kkt_solver_type), pointer :: ctx
86*c4762a1bSJed Brown          PetscErrorCode ierr
87*c4762a1bSJed Brown        End Subroutine
88*c4762a1bSJed Brown      End Interface SNESGetApplicationContext
89*c4762a1bSJed Brown      end module petsc_kkt_solver_interfaces
90*c4762a1bSJed Brown
91*c4762a1bSJed Brown      program main
92*c4762a1bSJed Brown#include <petsc/finclude/petscdm.h>
93*c4762a1bSJed Brown#include <petsc/finclude/petscsnes.h>
94*c4762a1bSJed Brown      use petscdm
95*c4762a1bSJed Brown      use petscdmda
96*c4762a1bSJed Brown      use petscsnes
97*c4762a1bSJed Brown      use petsc_kkt_solver
98*c4762a1bSJed Brown      use petsc_kkt_solver_interfaces
99*c4762a1bSJed Brown      implicit none
100*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
101*c4762a1bSJed Brown!                   Variable declarations
102*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
103*c4762a1bSJed Brown!
104*c4762a1bSJed Brown!  Variables:
105*c4762a1bSJed Brown!     mysnes      - nonlinear solver
106*c4762a1bSJed Brown!     x, r        - solution, residual vectors
107*c4762a1bSJed Brown!     J           - Jacobian matrix
108*c4762a1bSJed Brown!     its         - iterations for convergence
109*c4762a1bSJed Brown!     Nx, Ny      - number of preocessors in x- and y- directions
110*c4762a1bSJed Brown!
111*c4762a1bSJed Brown      SNES::       mysnes
112*c4762a1bSJed Brown      Vec::        x,r,x2,x1,x1loc,x2loc
113*c4762a1bSJed Brown      Mat::       Amat,Bmat,Cmat,Dmat,KKTMat,matArray(4)
114*c4762a1bSJed Brown!      Mat::       tmat
115*c4762a1bSJed Brown      DM::       daphi,dalam
116*c4762a1bSJed Brown      IS::        isglobal(2)
117*c4762a1bSJed Brown      PetscErrorCode   ierr
118*c4762a1bSJed Brown      PetscInt         its,N1,N2,i,j,irow,row(1)
119*c4762a1bSJed Brown      PetscInt         col(1),low,high,lamlow,lamhigh
120*c4762a1bSJed Brown      PetscBool        flg
121*c4762a1bSJed Brown      PetscInt         ione,nfour,itwo,nloc,nloclam
122*c4762a1bSJed Brown      PetscReal lambda_max,lambda_min
123*c4762a1bSJed Brown      type(petsc_kkt_solver_type)  solver
124*c4762a1bSJed Brown      PetscScalar      bval(1),cval(1),one
125*c4762a1bSJed Brown
126*c4762a1bSJed Brown!  Note: Any user-defined Fortran routines (such as FormJacobian)
127*c4762a1bSJed Brown!  MUST be declared as external.
128*c4762a1bSJed Brown      external FormInitialGuess,FormJacobian,FormFunction
129*c4762a1bSJed Brown
130*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
131*c4762a1bSJed Brown!  Initialize program
132*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
133*c4762a1bSJed Brown      call PetscInitialize(PETSC_NULL_CHARACTER,ierr)
134*c4762a1bSJed Brown     if (ierr .ne. 0) then
135*c4762a1bSJed Brown         print*,'PetscInitialize failed'
136*c4762a1bSJed Brown         stop
137*c4762a1bSJed Brown      endif
138*c4762a1bSJed Brown      call MPI_Comm_rank(PETSC_COMM_WORLD,solver%rank,ierr);CHKERRA(ierr)
139*c4762a1bSJed Brown
140*c4762a1bSJed Brown!  Initialize problem parameters
141*c4762a1bSJed Brown      lambda_max  = 6.81_PETSC_REAL_KIND
142*c4762a1bSJed Brown      lambda_min  = 0.0
143*c4762a1bSJed Brown      solver%lambda = 6.0
144*c4762a1bSJed Brown      ione = 1
145*c4762a1bSJed Brown      nfour = 4
146*c4762a1bSJed Brown      itwo = 2
147*c4762a1bSJed Brown      call PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-par', solver%lambda,flg,ierr);CHKERRA(ierr)
148*c4762a1bSJed Brown      if (solver%lambda .ge. lambda_max .or. solver%lambda .lt. lambda_min) then; SETERRA(PETSC_COMM_SELF,PETSC_ERR_USER,'Lambda provided with -par is out of range'); endif
149*c4762a1bSJed Brown
150*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
151*c4762a1bSJed Brown!  Create vector data structures; set function evaluation routine
152*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
153*c4762a1bSJed Brown
154*c4762a1bSJed Brown!     just get size
155*c4762a1bSJed Brown      call DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE, DM_BOUNDARY_NONE,DMDA_STENCIL_BOX,nfour,nfour,PETSC_DECIDE,PETSC_DECIDE,ione,ione, &
156*c4762a1bSJed Brown     &     PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,daphi,ierr);CHKERRA(ierr)
157*c4762a1bSJed Brown      call DMSetFromOptions(daphi,ierr);CHKERRA(ierr)
158*c4762a1bSJed Brown      call DMSetUp(daphi,ierr);CHKERRA(ierr)
159*c4762a1bSJed Brown      call DMDAGetInfo(daphi,PETSC_NULL_INTEGER,solver%mx,solver%my,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,                        &
160*c4762a1bSJed Brown     &                 PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,ierr);CHKERRA(ierr)
161*c4762a1bSJed Brown      N1 = solver%my*solver%mx
162*c4762a1bSJed Brown      N2 = solver%my
163*c4762a1bSJed Brown      flg = .false.
164*c4762a1bSJed Brown      call PetscOptionsGetBool(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-no_constraints',flg,flg,ierr);CHKERRA(ierr)
165*c4762a1bSJed Brown      if (flg) then
166*c4762a1bSJed Brown         N2 = 0
167*c4762a1bSJed Brown      endif
168*c4762a1bSJed Brown
169*c4762a1bSJed Brown      call DMDestroy(daphi,ierr);CHKERRA(ierr)
170*c4762a1bSJed Brown
171*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
172*c4762a1bSJed Brown!  Create matrix data structure; set Jacobian evaluation routine
173*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
174*c4762a1bSJed Brown      call DMShellCreate(PETSC_COMM_WORLD,daphi,ierr);CHKERRA(ierr)
175*c4762a1bSJed Brown      call DMSetOptionsPrefix(daphi,'phi_',ierr);CHKERRA(ierr)
176*c4762a1bSJed Brown      call DMSetFromOptions(daphi,ierr);CHKERRA(ierr)
177*c4762a1bSJed Brown
178*c4762a1bSJed Brown      call VecCreate(PETSC_COMM_WORLD,x1,ierr);CHKERRA(ierr)
179*c4762a1bSJed Brown      call VecSetSizes(x1,PETSC_DECIDE,N1,ierr);CHKERRA(ierr)
180*c4762a1bSJed Brown      call VecSetFromOptions(x1,ierr);CHKERRA(ierr)
181*c4762a1bSJed Brown
182*c4762a1bSJed Brown      call VecGetOwnershipRange(x1,low,high,ierr);CHKERRA(ierr)
183*c4762a1bSJed Brown      nloc = high - low
184*c4762a1bSJed Brown
185*c4762a1bSJed Brown      call MatCreate(PETSC_COMM_WORLD,Amat,ierr);CHKERRA(ierr)
186*c4762a1bSJed Brown      call MatSetSizes(Amat,PETSC_DECIDE,PETSC_DECIDE,N1,N1,ierr);CHKERRA(ierr)
187*c4762a1bSJed Brown      call MatSetUp(Amat,ierr);CHKERRA(ierr)
188*c4762a1bSJed Brown
189*c4762a1bSJed Brown      call MatCreate(PETSC_COMM_WORLD,solver%AmatLin,ierr);CHKERRA(ierr)
190*c4762a1bSJed Brown      call MatSetSizes(solver%AmatLin,PETSC_DECIDE,PETSC_DECIDE,N1,N1,ierr);CHKERRA(ierr)
191*c4762a1bSJed Brown      call MatSetUp(solver%AmatLin,ierr);CHKERRA(ierr)
192*c4762a1bSJed Brown
193*c4762a1bSJed Brown      call FormJacobianLocal(x1,solver%AmatLin,solver,.false.,ierr);CHKERRA(ierr)
194*c4762a1bSJed Brown      call MatAssemblyBegin(solver%AmatLin,MAT_FINAL_ASSEMBLY,ierr);CHKERRA(ierr)
195*c4762a1bSJed Brown      call MatAssemblyEnd(solver%AmatLin,MAT_FINAL_ASSEMBLY,ierr);CHKERRA(ierr)
196*c4762a1bSJed Brown
197*c4762a1bSJed Brown      call DMShellSetGlobalVector(daphi,x1,ierr);CHKERRA(ierr)
198*c4762a1bSJed Brown      call DMShellSetMatrix(daphi,Amat,ierr);CHKERRA(ierr)
199*c4762a1bSJed Brown
200*c4762a1bSJed Brown      call VecCreate(PETSC_COMM_SELF,x1loc,ierr);CHKERRA(ierr)
201*c4762a1bSJed Brown      call VecSetSizes(x1loc,nloc,nloc,ierr);CHKERRA(ierr)
202*c4762a1bSJed Brown      call VecSetFromOptions(x1loc,ierr);CHKERRA(ierr)
203*c4762a1bSJed Brown      call DMShellSetLocalVector(daphi,x1loc,ierr);CHKERRA(ierr)
204*c4762a1bSJed Brown
205*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
206*c4762a1bSJed Brown!  Create B, C, & D matrices
207*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
208*c4762a1bSJed Brown      call MatCreate(PETSC_COMM_WORLD,Cmat,ierr);CHKERRA(ierr)
209*c4762a1bSJed Brown      call MatSetSizes(Cmat,PETSC_DECIDE,PETSC_DECIDE,N2,N1,ierr);CHKERRA(ierr)
210*c4762a1bSJed Brown      call MatSetUp(Cmat,ierr);CHKERRA(ierr)
211*c4762a1bSJed Brown!      create data for C and B
212*c4762a1bSJed Brown      call MatCreate(PETSC_COMM_WORLD,Bmat,ierr);CHKERRA(ierr)
213*c4762a1bSJed Brown      call MatSetSizes(Bmat,PETSC_DECIDE,PETSC_DECIDE,N1,N2,ierr);CHKERRA(ierr)
214*c4762a1bSJed Brown      call MatSetUp(Bmat,ierr);CHKERRA(ierr)
215*c4762a1bSJed Brown!     create data for D
216*c4762a1bSJed Brown      call MatCreate(PETSC_COMM_WORLD,Dmat,ierr);CHKERRA(ierr)
217*c4762a1bSJed Brown      call MatSetSizes(Dmat,PETSC_DECIDE,PETSC_DECIDE,N2,N2,ierr);CHKERRA(ierr)
218*c4762a1bSJed Brown      call MatSetUp(Dmat,ierr);CHKERRA(ierr)
219*c4762a1bSJed Brown
220*c4762a1bSJed Brown      call VecCreate(PETSC_COMM_WORLD,x2,ierr);CHKERRA(ierr)
221*c4762a1bSJed Brown      call VecSetSizes(x2,PETSC_DECIDE,N2,ierr);CHKERRA(ierr)
222*c4762a1bSJed Brown      call VecSetFromOptions(x2,ierr);CHKERRA(ierr)
223*c4762a1bSJed Brown
224*c4762a1bSJed Brown      call VecGetOwnershipRange(x2,lamlow,lamhigh,ierr);CHKERRA(ierr)
225*c4762a1bSJed Brown      nloclam = lamhigh-lamlow
226*c4762a1bSJed Brown
227*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
228*c4762a1bSJed Brown!  Set fake B and C
229*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
230*c4762a1bSJed Brown      one    = 1.0
231*c4762a1bSJed Brown      if( N2 .gt. 0 ) then
232*c4762a1bSJed Brown         bval(1) = -one/(solver%mx-2)
233*c4762a1bSJed Brown!     cval = -one/(solver%my*solver%mx)
234*c4762a1bSJed Brown         cval(1) = -one
235*c4762a1bSJed Brown         do 20 irow=low,high-1
236*c4762a1bSJed Brown            j = irow/solver%mx   ! row in domain
237*c4762a1bSJed Brown            i = mod(irow,solver%mx)
238*c4762a1bSJed Brown            row(1) = irow
239*c4762a1bSJed Brown            col(1) = j
240*c4762a1bSJed Brown            if (i .eq. 0 .or. j .eq. 0 .or. i .eq. solver%mx-1 .or. j .eq. solver%my-1 ) then
241*c4762a1bSJed Brown               !     no op
242*c4762a1bSJed Brown            else
243*c4762a1bSJed Brown               call MatSetValues(Bmat,ione,row,ione,col,bval,INSERT_VALUES,ierr);CHKERRA(ierr)
244*c4762a1bSJed Brown            endif
245*c4762a1bSJed Brown            row(1) = j
246*c4762a1bSJed Brown            call MatSetValues(Cmat,ione,row,ione,row,cval,INSERT_VALUES,ierr);CHKERRA(ierr)
247*c4762a1bSJed Brown 20   continue
248*c4762a1bSJed Brown      endif
249*c4762a1bSJed Brown      call MatAssemblyBegin(Bmat,MAT_FINAL_ASSEMBLY,ierr);CHKERRA(ierr)
250*c4762a1bSJed Brown      call MatAssemblyEnd(Bmat,MAT_FINAL_ASSEMBLY,ierr);CHKERRA(ierr)
251*c4762a1bSJed Brown      call MatAssemblyBegin(Cmat,MAT_FINAL_ASSEMBLY,ierr);CHKERRA(ierr)
252*c4762a1bSJed Brown      call MatAssemblyEnd(Cmat,MAT_FINAL_ASSEMBLY,ierr);CHKERRA(ierr)
253*c4762a1bSJed Brown
254*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
255*c4762a1bSJed Brown!  Set D (indentity)
256*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
257*c4762a1bSJed Brown      do 30 j=lamlow,lamhigh-1
258*c4762a1bSJed Brown         row(1) = j
259*c4762a1bSJed Brown         cval(1) = one
260*c4762a1bSJed Brown         call MatSetValues(Dmat,ione,row,ione,row,cval,INSERT_VALUES,ierr);CHKERRA(ierr)
261*c4762a1bSJed Brown 30   continue
262*c4762a1bSJed Brown      call MatAssemblyBegin(Dmat,MAT_FINAL_ASSEMBLY,ierr);CHKERRA(ierr)
263*c4762a1bSJed Brown      call MatAssemblyEnd(Dmat,MAT_FINAL_ASSEMBLY,ierr);CHKERRA(ierr)
264*c4762a1bSJed Brown
265*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
266*c4762a1bSJed Brown!  DM for lambda (dalam) : temp driver for A block, setup A block solver data
267*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
268*c4762a1bSJed Brown      call DMShellCreate(PETSC_COMM_WORLD,dalam,ierr);CHKERRA(ierr)
269*c4762a1bSJed Brown      call DMShellSetGlobalVector(dalam,x2,ierr);CHKERRA(ierr)
270*c4762a1bSJed Brown      call DMShellSetMatrix(dalam,Dmat,ierr);CHKERRA(ierr)
271*c4762a1bSJed Brown
272*c4762a1bSJed Brown      call VecCreate(PETSC_COMM_SELF,x2loc,ierr);CHKERRA(ierr)
273*c4762a1bSJed Brown      call VecSetSizes(x2loc,nloclam,nloclam,ierr);CHKERRA(ierr)
274*c4762a1bSJed Brown      call VecSetFromOptions(x2loc,ierr);CHKERRA(ierr)
275*c4762a1bSJed Brown      call DMShellSetLocalVector(dalam,x2loc,ierr);CHKERRA(ierr)
276*c4762a1bSJed Brown
277*c4762a1bSJed Brown      call DMSetOptionsPrefix(dalam,'lambda_',ierr);CHKERRA(ierr)
278*c4762a1bSJed Brown      call DMSetFromOptions(dalam,ierr);CHKERRA(ierr)
279*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
280*c4762a1bSJed Brown!  Create field split DA
281*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
282*c4762a1bSJed Brown      call DMCompositeCreate(PETSC_COMM_WORLD,solver%da,ierr);CHKERRA(ierr)
283*c4762a1bSJed Brown      call DMCompositeAddDM(solver%da,daphi,ierr);CHKERRA(ierr)
284*c4762a1bSJed Brown      call DMCompositeAddDM(solver%da,dalam,ierr);CHKERRA(ierr)
285*c4762a1bSJed Brown      call DMSetFromOptions(solver%da,ierr);CHKERRA(ierr)
286*c4762a1bSJed Brown      call DMSetUp(solver%da,ierr);CHKERRA(ierr)
287*c4762a1bSJed Brown      call DMCompositeGetGlobalISs(solver%da,isglobal,ierr);CHKERRA(ierr)
288*c4762a1bSJed Brown      solver%isPhi = isglobal(1)
289*c4762a1bSJed Brown      solver%isLambda = isglobal(2)
290*c4762a1bSJed Brown
291*c4762a1bSJed Brown!     cache matrices
292*c4762a1bSJed Brown      solver%Amat = Amat
293*c4762a1bSJed Brown      solver%Bmat = Bmat
294*c4762a1bSJed Brown      solver%Cmat = Cmat
295*c4762a1bSJed Brown      solver%Dmat = Dmat
296*c4762a1bSJed Brown
297*c4762a1bSJed Brown      matArray(1) = Amat
298*c4762a1bSJed Brown      matArray(2) = Bmat
299*c4762a1bSJed Brown      matArray(3) = Cmat
300*c4762a1bSJed Brown      matArray(4) = Dmat
301*c4762a1bSJed Brown
302*c4762a1bSJed Brown      call MatCreateNest(PETSC_COMM_WORLD,itwo,isglobal,itwo,isglobal,matArray,KKTmat,ierr);CHKERRA(ierr)
303*c4762a1bSJed Brown      call MatSetFromOptions(KKTmat,ierr);CHKERRA(ierr)
304*c4762a1bSJed Brown
305*c4762a1bSJed Brown!  Extract global and local vectors from DMDA; then duplicate for remaining
306*c4762a1bSJed Brown!     vectors that are the same types
307*c4762a1bSJed Brown      call MatCreateVecs(KKTmat,x,PETSC_NULL_VEC,ierr);CHKERRA(ierr)
308*c4762a1bSJed Brown      call VecDuplicate(x,r,ierr);CHKERRA(ierr)
309*c4762a1bSJed Brown
310*c4762a1bSJed Brown      call SNESCreate(PETSC_COMM_WORLD,mysnes,ierr);CHKERRA(ierr)
311*c4762a1bSJed Brown
312*c4762a1bSJed Brown      call SNESSetDM(mysnes,solver%da,ierr);CHKERRA(ierr)
313*c4762a1bSJed Brown
314*c4762a1bSJed Brown      call SNESSetApplicationContext(mysnes,solver,ierr);CHKERRA(ierr)
315*c4762a1bSJed Brown
316*c4762a1bSJed Brown      call SNESSetDM(mysnes,solver%da,ierr);CHKERRA(ierr)
317*c4762a1bSJed Brown
318*c4762a1bSJed Brown!  Set function evaluation routine and vector
319*c4762a1bSJed Brown      call SNESSetFunction(mysnes,r,FormFunction,solver,ierr);CHKERRA(ierr)
320*c4762a1bSJed Brown
321*c4762a1bSJed Brown      call SNESSetJacobian(mysnes,KKTmat,KKTmat,FormJacobian,solver,ierr);CHKERRA(ierr)
322*c4762a1bSJed Brown
323*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
324*c4762a1bSJed Brown!  Customize nonlinear solver; set runtime options
325*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
326*c4762a1bSJed Brown!  Set runtime options (e.g., -snes_monitor -snes_rtol <rtol> -ksp_type <type>)
327*c4762a1bSJed Brown      call SNESSetFromOptions(mysnes,ierr);CHKERRA(ierr)
328*c4762a1bSJed Brown
329*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
330*c4762a1bSJed Brown!  Evaluate initial guess; then solve nonlinear system.
331*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
332*c4762a1bSJed Brown!  Note: The user should initialize the vector, x, with the initial guess
333*c4762a1bSJed Brown!  for the nonlinear solver prior to calling SNESSolve().  In particular,
334*c4762a1bSJed Brown!  to employ an initial guess of zero, the user should explicitly set
335*c4762a1bSJed Brown!  this vector to zero by calling VecSet().
336*c4762a1bSJed Brown
337*c4762a1bSJed Brown      call FormInitialGuess(mysnes,x,ierr);CHKERRA(ierr)
338*c4762a1bSJed Brown      call SNESSolve(mysnes,PETSC_NULL_VEC,x,ierr);CHKERRA(ierr)
339*c4762a1bSJed Brown      call SNESGetIterationNumber(mysnes,its,ierr);CHKERRA(ierr)
340*c4762a1bSJed Brown      if (solver%rank .eq. 0) then
341*c4762a1bSJed Brown         write(6,100) its
342*c4762a1bSJed Brown      endif
343*c4762a1bSJed Brown  100 format('Number of SNES iterations = ',i5)
344*c4762a1bSJed Brown
345*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
346*c4762a1bSJed Brown!  Free work space.  All PETSc objects should be destroyed when they
347*c4762a1bSJed Brown!  are no longer needed.
348*c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
349*c4762a1bSJed Brown      call MatDestroy(KKTmat,ierr);CHKERRA(ierr)
350*c4762a1bSJed Brown      call MatDestroy(Amat,ierr);CHKERRA(ierr)
351*c4762a1bSJed Brown      call MatDestroy(Dmat,ierr);CHKERRA(ierr)
352*c4762a1bSJed Brown      call MatDestroy(Bmat,ierr);CHKERRA(ierr)
353*c4762a1bSJed Brown      call MatDestroy(Cmat,ierr);CHKERRA(ierr)
354*c4762a1bSJed Brown      call MatDestroy(solver%AmatLin,ierr);CHKERRA(ierr)
355*c4762a1bSJed Brown      call ISDestroy(solver%isPhi,ierr);CHKERRA(ierr)
356*c4762a1bSJed Brown      call ISDestroy(solver%isLambda,ierr);CHKERRA(ierr)
357*c4762a1bSJed Brown      call VecDestroy(x,ierr);CHKERRA(ierr)
358*c4762a1bSJed Brown      call VecDestroy(x2,ierr);CHKERRA(ierr)
359*c4762a1bSJed Brown      call VecDestroy(x1,ierr);CHKERRA(ierr)
360*c4762a1bSJed Brown      call VecDestroy(x1loc,ierr);CHKERRA(ierr)
361*c4762a1bSJed Brown      call VecDestroy(x2loc,ierr);CHKERRA(ierr)
362*c4762a1bSJed Brown      call VecDestroy(r,ierr);CHKERRA(ierr)
363*c4762a1bSJed Brown      call SNESDestroy(mysnes,ierr);CHKERRA(ierr)
364*c4762a1bSJed Brown      call DMDestroy(solver%da,ierr);CHKERRA(ierr)
365*c4762a1bSJed Brown      call DMDestroy(daphi,ierr);CHKERRA(ierr)
366*c4762a1bSJed Brown      call DMDestroy(dalam,ierr);CHKERRA(ierr)
367*c4762a1bSJed Brown
368*c4762a1bSJed Brown      call PetscFinalize(ierr)
369*c4762a1bSJed Brown      end
370*c4762a1bSJed Brown
371*c4762a1bSJed Brown! ---------------------------------------------------------------------
372*c4762a1bSJed Brown!
373*c4762a1bSJed Brown!  FormInitialGuess - Forms initial approximation.
374*c4762a1bSJed Brown!
375*c4762a1bSJed Brown!  Input Parameters:
376*c4762a1bSJed Brown!  X - vector
377*c4762a1bSJed Brown!
378*c4762a1bSJed Brown!  Output Parameter:
379*c4762a1bSJed Brown!  X - vector
380*c4762a1bSJed Brown!
381*c4762a1bSJed Brown!  Notes:
382*c4762a1bSJed Brown!  This routine serves as a wrapper for the lower-level routine
383*c4762a1bSJed Brown!  "InitialGuessLocal", where the actual computations are
384*c4762a1bSJed Brown!  done using the standard Fortran style of treating the local
385*c4762a1bSJed Brown!  vector data as a multidimensional array over the local mesh.
386*c4762a1bSJed Brown!  This routine merely handles ghost point scatters and accesses
387*c4762a1bSJed Brown!  the local vector data via VecGetArrayF90() and VecRestoreArrayF90().
388*c4762a1bSJed Brown!
389*c4762a1bSJed Brown      subroutine FormInitialGuess(mysnes,Xnest,ierr)
390*c4762a1bSJed Brown#include <petsc/finclude/petscsnes.h>
391*c4762a1bSJed Brown      use petscsnes
392*c4762a1bSJed Brown      use petsc_kkt_solver
393*c4762a1bSJed Brown      use petsc_kkt_solver_interfaces
394*c4762a1bSJed Brown      implicit none
395*c4762a1bSJed Brown!  Input/output variables:
396*c4762a1bSJed Brown      SNES::     mysnes
397*c4762a1bSJed Brown      Vec::      Xnest
398*c4762a1bSJed Brown      PetscErrorCode ierr
399*c4762a1bSJed Brown
400*c4762a1bSJed Brown!  Declarations for use with local arrays:
401*c4762a1bSJed Brown      type(petsc_kkt_solver_type), pointer:: solver
402*c4762a1bSJed Brown      Vec::      Xsub(2)
403*c4762a1bSJed Brown      PetscInt::  izero,ione,itwo
404*c4762a1bSJed Brown
405*c4762a1bSJed Brown      izero = 0
406*c4762a1bSJed Brown      ione = 1
407*c4762a1bSJed Brown      itwo = 2
408*c4762a1bSJed Brown      ierr = 0
409*c4762a1bSJed Brown      call SNESGetApplicationContext(mysnes,solver,ierr);CHKERRQ(ierr)
410*c4762a1bSJed Brown      call DMCompositeGetAccessArray(solver%da,Xnest,itwo,PETSC_NULL_INTEGER,Xsub,ierr);CHKERRQ(ierr)
411*c4762a1bSJed Brown
412*c4762a1bSJed Brown      call InitialGuessLocal(solver,Xsub(1),ierr);CHKERRQ(ierr)
413*c4762a1bSJed Brown      call VecAssemblyBegin(Xsub(1),ierr);CHKERRQ(ierr)
414*c4762a1bSJed Brown      call VecAssemblyEnd(Xsub(1),ierr);CHKERRQ(ierr)
415*c4762a1bSJed Brown
416*c4762a1bSJed Brown!     zero out lambda
417*c4762a1bSJed Brown      call VecZeroEntries(Xsub(2),ierr);CHKERRQ(ierr)
418*c4762a1bSJed Brown      call DMCompositeRestoreAccessArray(solver%da,Xnest,itwo,PETSC_NULL_INTEGER,Xsub,ierr);CHKERRQ(ierr)
419*c4762a1bSJed Brown
420*c4762a1bSJed Brown      return
421*c4762a1bSJed Brown      end subroutine FormInitialGuess
422*c4762a1bSJed Brown
423*c4762a1bSJed Brown! ---------------------------------------------------------------------
424*c4762a1bSJed Brown!
425*c4762a1bSJed Brown!  InitialGuessLocal - Computes initial approximation, called by
426*c4762a1bSJed Brown!  the higher level routine FormInitialGuess().
427*c4762a1bSJed Brown!
428*c4762a1bSJed Brown!  Input Parameter:
429*c4762a1bSJed Brown!  X1 - local vector data
430*c4762a1bSJed Brown!
431*c4762a1bSJed Brown!  Output Parameters:
432*c4762a1bSJed Brown!  x - local vector data
433*c4762a1bSJed Brown!  ierr - error code
434*c4762a1bSJed Brown!
435*c4762a1bSJed Brown!  Notes:
436*c4762a1bSJed Brown!  This routine uses standard Fortran-style computations over a 2-dim array.
437*c4762a1bSJed Brown!
438*c4762a1bSJed Brown      subroutine InitialGuessLocal(solver,X1,ierr)
439*c4762a1bSJed Brown#include <petsc/finclude/petscsys.h>
440*c4762a1bSJed Brown      use petscsys
441*c4762a1bSJed Brown      use petsc_kkt_solver
442*c4762a1bSJed Brown      implicit none
443*c4762a1bSJed Brown!  Input/output variables:
444*c4762a1bSJed Brown      type (petsc_kkt_solver_type)         solver
445*c4762a1bSJed Brown      Vec::      X1
446*c4762a1bSJed Brown      PetscErrorCode ierr
447*c4762a1bSJed Brown
448*c4762a1bSJed Brown!  Local variables:
449*c4762a1bSJed Brown      PetscInt      row,i,j,ione,low,high
450*c4762a1bSJed Brown      PetscReal   temp1,temp,hx,hy,v
451*c4762a1bSJed Brown      PetscReal   one
452*c4762a1bSJed Brown
453*c4762a1bSJed Brown!  Set parameters
454*c4762a1bSJed Brown      ione = 1
455*c4762a1bSJed Brown      ierr   = 0
456*c4762a1bSJed Brown      one    = 1.0
457*c4762a1bSJed Brown      hx     = one/(solver%mx-1)
458*c4762a1bSJed Brown      hy     = one/(solver%my-1)
459*c4762a1bSJed Brown      temp1  = solver%lambda/(solver%lambda + one) + one
460*c4762a1bSJed Brown
461*c4762a1bSJed Brown      call VecGetOwnershipRange(X1,low,high,ierr);CHKERRQ(ierr)
462*c4762a1bSJed Brown
463*c4762a1bSJed Brown      do 20 row=low,high-1
464*c4762a1bSJed Brown         j = row/solver%mx
465*c4762a1bSJed Brown         i = mod(row,solver%mx)
466*c4762a1bSJed Brown         temp = min(j,solver%my-j+1)*hy
467*c4762a1bSJed Brown         if (i .eq. 0 .or. j .eq. 0  .or. i .eq. solver%mx-1 .or. j .eq. solver%my-1 ) then
468*c4762a1bSJed Brown            v = 0.0
469*c4762a1bSJed Brown         else
470*c4762a1bSJed Brown            v = temp1 * sqrt(min(min(i,solver%mx-i+1)*hx,temp))
471*c4762a1bSJed Brown         endif
472*c4762a1bSJed Brown         call VecSetValues(X1,ione,row,v,INSERT_VALUES,ierr);CHKERRQ(ierr)
473*c4762a1bSJed Brown 20   continue
474*c4762a1bSJed Brown
475*c4762a1bSJed Brown      return
476*c4762a1bSJed Brown      end subroutine InitialGuessLocal
477*c4762a1bSJed Brown
478*c4762a1bSJed Brown
479*c4762a1bSJed Brown! ---------------------------------------------------------------------
480*c4762a1bSJed Brown!
481*c4762a1bSJed Brown!  FormJacobian - Evaluates Jacobian matrix.
482*c4762a1bSJed Brown!
483*c4762a1bSJed Brown!  Input Parameters:
484*c4762a1bSJed Brown!  dummy     - the SNES context
485*c4762a1bSJed Brown!  x         - input vector
486*c4762a1bSJed Brown!  solver    - solver data
487*c4762a1bSJed Brown!
488*c4762a1bSJed Brown!  Output Parameters:
489*c4762a1bSJed Brown!  jac      - Jacobian matrix
490*c4762a1bSJed Brown!  jac_prec - optionally different preconditioning matrix (not used here)
491*c4762a1bSJed Brown!  flag     - flag indicating matrix structure
492*c4762a1bSJed Brown!
493*c4762a1bSJed Brown      subroutine FormJacobian(dummy,X,jac,jac_prec,solver,ierr)
494*c4762a1bSJed Brown#include <petsc/finclude/petscsnes.h>
495*c4762a1bSJed Brown      use petscsnes
496*c4762a1bSJed Brown      use petsc_kkt_solver
497*c4762a1bSJed Brown      implicit none
498*c4762a1bSJed Brown!  Input/output variables:
499*c4762a1bSJed Brown      SNES::     dummy
500*c4762a1bSJed Brown      Vec::      X
501*c4762a1bSJed Brown     Mat::     jac,jac_prec
502*c4762a1bSJed Brown      type(petsc_kkt_solver_type)  solver
503*c4762a1bSJed Brown      PetscErrorCode ierr
504*c4762a1bSJed Brown
505*c4762a1bSJed Brown!  Declarations for use with local arrays:
506*c4762a1bSJed Brown      Vec::      Xsub(1)
507*c4762a1bSJed Brown     Mat::     Amat
508*c4762a1bSJed Brown      PetscInt       izero,ione
509*c4762a1bSJed Brown
510*c4762a1bSJed Brown      izero = 0
511*c4762a1bSJed Brown      ione = 1
512*c4762a1bSJed Brown
513*c4762a1bSJed Brown      call DMCompositeGetAccessArray(solver%da,X,ione,PETSC_NULL_INTEGER,Xsub,ierr);CHKERRQ(ierr)
514*c4762a1bSJed Brown
515*c4762a1bSJed Brown!     Compute entries for the locally owned part of the Jacobian preconditioner.
516*c4762a1bSJed Brown      call MatCreateSubMatrix(jac_prec,solver%isPhi,solver%isPhi,MAT_INITIAL_MATRIX,Amat,ierr);CHKERRQ(ierr)
517*c4762a1bSJed Brown
518*c4762a1bSJed Brown      call FormJacobianLocal(Xsub(1),Amat,solver,.true.,ierr);CHKERRQ(ierr)
519*c4762a1bSJed Brown      call MatDestroy(Amat,ierr);CHKERRQ(ierr) ! discard our reference
520*c4762a1bSJed Brown      call DMCompositeRestoreAccessArray(solver%da,X,ione,PETSC_NULL_INTEGER,Xsub,ierr);CHKERRQ(ierr)
521*c4762a1bSJed Brown
522*c4762a1bSJed Brown      ! the rest of the matrix is not touched
523*c4762a1bSJed Brown      call MatAssemblyBegin(jac_prec,MAT_FINAL_ASSEMBLY,ierr);CHKERRQ(ierr)
524*c4762a1bSJed Brown      call MatAssemblyEnd(jac_prec,MAT_FINAL_ASSEMBLY,ierr);CHKERRQ(ierr)
525*c4762a1bSJed Brown      if (jac .ne. jac_prec) then
526*c4762a1bSJed Brown         call MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY,ierr);CHKERRQ(ierr)
527*c4762a1bSJed Brown         call MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY,ierr);CHKERRQ(ierr)
528*c4762a1bSJed Brown      end if
529*c4762a1bSJed Brown
530*c4762a1bSJed Brown!     Tell the matrix we will never add a new nonzero location to the
531*c4762a1bSJed Brown!     matrix. If we do it will generate an error.
532*c4762a1bSJed Brown      call MatSetOption(jac_prec,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE,ierr);CHKERRQ(ierr)
533*c4762a1bSJed Brown
534*c4762a1bSJed Brown      return
535*c4762a1bSJed Brown      end subroutine FormJacobian
536*c4762a1bSJed Brown
537*c4762a1bSJed Brown! ---------------------------------------------------------------------
538*c4762a1bSJed Brown!
539*c4762a1bSJed Brown!  FormJacobianLocal - Computes Jacobian preconditioner matrix,
540*c4762a1bSJed Brown!  called by the higher level routine FormJacobian().
541*c4762a1bSJed Brown!
542*c4762a1bSJed Brown!  Input Parameters:
543*c4762a1bSJed Brown!  x        - local vector data
544*c4762a1bSJed Brown!
545*c4762a1bSJed Brown!  Output Parameters:
546*c4762a1bSJed Brown!  jac - Jacobian preconditioner matrix
547*c4762a1bSJed Brown!  ierr     - error code
548*c4762a1bSJed Brown!
549*c4762a1bSJed Brown!  Notes:
550*c4762a1bSJed Brown!  This routine uses standard Fortran-style computations over a 2-dim array.
551*c4762a1bSJed Brown!
552*c4762a1bSJed Brown      subroutine FormJacobianLocal(X1,jac,solver,add_nl_term,ierr)
553*c4762a1bSJed Brown#include <petsc/finclude/petscmat.h>
554*c4762a1bSJed Brown      use petscmat
555*c4762a1bSJed Brown      use petsc_kkt_solver
556*c4762a1bSJed Brown      implicit none
557*c4762a1bSJed Brown!  Input/output variables:
558*c4762a1bSJed Brown      type (petsc_kkt_solver_type) solver
559*c4762a1bSJed Brown      Vec::      X1
560*c4762a1bSJed Brown     Mat::     jac
561*c4762a1bSJed Brown      logical        add_nl_term
562*c4762a1bSJed Brown      PetscErrorCode ierr
563*c4762a1bSJed Brown
564*c4762a1bSJed Brown!  Local variables:
565*c4762a1bSJed Brown      PetscInt    irow,row(1),col(5),i,j
566*c4762a1bSJed Brown      PetscInt    ione,ifive,low,high,ii
567*c4762a1bSJed Brown      PetscScalar two,one,hx,hy,hy2inv
568*c4762a1bSJed Brown      PetscScalar hx2inv,sc,v(5)
569*c4762a1bSJed Brown      PetscScalar,pointer :: lx_v(:)
570*c4762a1bSJed Brown
571*c4762a1bSJed Brown!  Set parameters
572*c4762a1bSJed Brown      ione   = 1
573*c4762a1bSJed Brown      ifive  = 5
574*c4762a1bSJed Brown      one    = 1.0
575*c4762a1bSJed Brown      two    = 2.0
576*c4762a1bSJed Brown      hx     = one/(solver%mx-1)
577*c4762a1bSJed Brown      hy     = one/(solver%my-1)
578*c4762a1bSJed Brown      sc     = solver%lambda
579*c4762a1bSJed Brown      hx2inv = one/(hx*hx)
580*c4762a1bSJed Brown      hy2inv = one/(hy*hy)
581*c4762a1bSJed Brown
582*c4762a1bSJed Brown      call VecGetOwnershipRange(X1,low,high,ierr);CHKERRQ(ierr)
583*c4762a1bSJed Brown      call VecGetArrayReadF90(X1,lx_v,ierr);CHKERRQ(ierr)
584*c4762a1bSJed Brown
585*c4762a1bSJed Brown      ii = 0
586*c4762a1bSJed Brown      do 20 irow=low,high-1
587*c4762a1bSJed Brown         j = irow/solver%mx
588*c4762a1bSJed Brown         i = mod(irow,solver%mx)
589*c4762a1bSJed Brown         ii = ii + 1            ! one based local index
590*c4762a1bSJed Brown!     boundary points
591*c4762a1bSJed Brown         if (i .eq. 0 .or. j .eq. 0 .or. i .eq. solver%mx-1 .or. j .eq. solver%my-1) then
592*c4762a1bSJed Brown            col(1) = irow
593*c4762a1bSJed Brown            row(1) = irow
594*c4762a1bSJed Brown            v(1)   = one
595*c4762a1bSJed Brown            call MatSetValues(jac,ione,row,ione,col,v,INSERT_VALUES,ierr);CHKERRQ(ierr)
596*c4762a1bSJed Brown!     interior grid points
597*c4762a1bSJed Brown         else
598*c4762a1bSJed Brown            v(1) = -hy2inv
599*c4762a1bSJed Brown            if(j-1==0) v(1) = 0.0
600*c4762a1bSJed Brown            v(2) = -hx2inv
601*c4762a1bSJed Brown            if(i-1==0) v(2) = 0.0
602*c4762a1bSJed Brown            v(3) = two*(hx2inv + hy2inv)
603*c4762a1bSJed Brown            if(add_nl_term) v(3) = v(3) - sc*exp(lx_v(ii))
604*c4762a1bSJed Brown            v(4) = -hx2inv
605*c4762a1bSJed Brown            if(i+1==solver%mx-1) v(4) = 0.0
606*c4762a1bSJed Brown            v(5) = -hy2inv
607*c4762a1bSJed Brown            if(j+1==solver%my-1) v(5) = 0.0
608*c4762a1bSJed Brown            col(1) = irow - solver%mx
609*c4762a1bSJed Brown            col(2) = irow - 1
610*c4762a1bSJed Brown            col(3) = irow
611*c4762a1bSJed Brown            col(4) = irow + 1
612*c4762a1bSJed Brown            col(5) = irow + solver%mx
613*c4762a1bSJed Brown            row(1) = irow
614*c4762a1bSJed Brown            call MatSetValues(jac,ione,row,ifive,col,v,INSERT_VALUES,ierr);CHKERRQ(ierr)
615*c4762a1bSJed Brown         endif
616*c4762a1bSJed Brown 20   continue
617*c4762a1bSJed Brown
618*c4762a1bSJed Brown      call VecRestoreArrayReadF90(X1,lx_v,ierr);CHKERRQ(ierr)
619*c4762a1bSJed Brown
620*c4762a1bSJed Brown      return
621*c4762a1bSJed Brown      end subroutine FormJacobianLocal
622*c4762a1bSJed Brown
623*c4762a1bSJed Brown
624*c4762a1bSJed Brown! ---------------------------------------------------------------------
625*c4762a1bSJed Brown!
626*c4762a1bSJed Brown!  FormFunction - Evaluates nonlinear function, F(x).
627*c4762a1bSJed Brown!
628*c4762a1bSJed Brown!  Input Parameters:
629*c4762a1bSJed Brown!  snes - the SNES context
630*c4762a1bSJed Brown!  X - input vector
631*c4762a1bSJed Brown!  dummy - optional user-defined context, as set by SNESSetFunction()
632*c4762a1bSJed Brown!          (not used here)
633*c4762a1bSJed Brown!
634*c4762a1bSJed Brown!  Output Parameter:
635*c4762a1bSJed Brown!  F - function vector
636*c4762a1bSJed Brown!
637*c4762a1bSJed Brown      subroutine FormFunction(snesIn,X,F,solver,ierr)
638*c4762a1bSJed Brown#include <petsc/finclude/petscsnes.h>
639*c4762a1bSJed Brown      use petscsnes
640*c4762a1bSJed Brown      use petsc_kkt_solver
641*c4762a1bSJed Brown      implicit none
642*c4762a1bSJed Brown!  Input/output variables:
643*c4762a1bSJed Brown      SNES::     snesIn
644*c4762a1bSJed Brown     Vec::      X,F
645*c4762a1bSJed Brown      PetscErrorCode ierr
646*c4762a1bSJed Brown      type (petsc_kkt_solver_type) solver
647*c4762a1bSJed Brown
648*c4762a1bSJed Brown!  Declarations for use with local arrays:
649*c4762a1bSJed Brown     Vec::              Xsub(2),Fsub(2)
650*c4762a1bSJed Brown      PetscInt               izero,ione,itwo
651*c4762a1bSJed Brown
652*c4762a1bSJed Brown!  Scatter ghost points to local vector, using the 2-step process
653*c4762a1bSJed Brown!     DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
654*c4762a1bSJed Brown!  By placing code between these two statements, computations can
655*c4762a1bSJed Brown!  be done while messages are in transition.
656*c4762a1bSJed Brown
657*c4762a1bSJed Brown      izero = 0
658*c4762a1bSJed Brown      ione = 1
659*c4762a1bSJed Brown      itwo = 2
660*c4762a1bSJed Brown      call DMCompositeGetAccessArray(solver%da,X,itwo,PETSC_NULL_INTEGER,Xsub,ierr);CHKERRQ(ierr)
661*c4762a1bSJed Brown      call DMCompositeGetAccessArray(solver%da,F,itwo,PETSC_NULL_INTEGER,Fsub,ierr);CHKERRQ(ierr)
662*c4762a1bSJed Brown
663*c4762a1bSJed Brown      call FormFunctionNLTerm( Xsub(1), Fsub(1), solver, ierr );CHKERRQ(ierr)
664*c4762a1bSJed Brown      call MatMultAdd( solver%AmatLin, Xsub(1), Fsub(1), Fsub(1), ierr);CHKERRQ(ierr)
665*c4762a1bSJed Brown
666*c4762a1bSJed Brown!     do rest of operator (linear)
667*c4762a1bSJed Brown      call MatMult(    solver%Cmat, Xsub(1),      Fsub(2), ierr);CHKERRQ(ierr)
668*c4762a1bSJed Brown      call MatMultAdd( solver%Bmat, Xsub(2), Fsub(1), Fsub(1), ierr);CHKERRQ(ierr)
669*c4762a1bSJed Brown      call MatMultAdd( solver%Dmat, Xsub(2), Fsub(2), Fsub(2), ierr);CHKERRQ(ierr)
670*c4762a1bSJed Brown
671*c4762a1bSJed Brown      call DMCompositeRestoreAccessArray(solver%da,X,itwo,PETSC_NULL_INTEGER,Xsub,ierr);CHKERRQ(ierr)
672*c4762a1bSJed Brown      call DMCompositeRestoreAccessArray(solver%da,F,itwo,PETSC_NULL_INTEGER,Fsub,ierr);CHKERRQ(ierr)
673*c4762a1bSJed Brown      return
674*c4762a1bSJed Brown      end subroutine formfunction
675*c4762a1bSJed Brown
676*c4762a1bSJed Brown
677*c4762a1bSJed Brown! ---------------------------------------------------------------------
678*c4762a1bSJed Brown!
679*c4762a1bSJed Brown!  FormFunctionNLTerm - Computes nonlinear function, called by
680*c4762a1bSJed Brown!  the higher level routine FormFunction().
681*c4762a1bSJed Brown!
682*c4762a1bSJed Brown!  Input Parameter:
683*c4762a1bSJed Brown!  x - local vector data
684*c4762a1bSJed Brown!
685*c4762a1bSJed Brown!  Output Parameters:
686*c4762a1bSJed Brown!  f - local vector data, f(x)
687*c4762a1bSJed Brown!  ierr - error code
688*c4762a1bSJed Brown!
689*c4762a1bSJed Brown!  Notes:
690*c4762a1bSJed Brown!  This routine uses standard Fortran-style computations over a 2-dim array.
691*c4762a1bSJed Brown!
692*c4762a1bSJed Brown      subroutine FormFunctionNLTerm(X1,F1,solver,ierr)
693*c4762a1bSJed Brown#include <petsc/finclude/petscvec.h>
694*c4762a1bSJed Brown      use petscvec
695*c4762a1bSJed Brown      use petsc_kkt_solver
696*c4762a1bSJed Brown      implicit none
697*c4762a1bSJed Brown!  Input/output variables:
698*c4762a1bSJed Brown      type (petsc_kkt_solver_type) solver
699*c4762a1bSJed Brown     Vec::      X1,F1
700*c4762a1bSJed Brown      PetscErrorCode ierr
701*c4762a1bSJed Brown!  Local variables:
702*c4762a1bSJed Brown      PetscScalar one,sc
703*c4762a1bSJed Brown      PetscScalar u,v(1)
704*c4762a1bSJed Brown      PetscInt  i,j,low,high,ii,ione,irow,row(1)
705*c4762a1bSJed Brown      PetscScalar,pointer :: lx_v(:)
706*c4762a1bSJed Brown
707*c4762a1bSJed Brown      one    = 1.0
708*c4762a1bSJed Brown      sc     = solver%lambda
709*c4762a1bSJed Brown      ione   = 1
710*c4762a1bSJed Brown
711*c4762a1bSJed Brown      call VecGetArrayReadF90(X1,lx_v,ierr);CHKERRQ(ierr)
712*c4762a1bSJed Brown      call VecGetOwnershipRange(X1,low,high,ierr);CHKERRQ(ierr)
713*c4762a1bSJed Brown
714*c4762a1bSJed Brown!     Compute function over the locally owned part of the grid
715*c4762a1bSJed Brown      ii = 0
716*c4762a1bSJed Brown      do 20 irow=low,high-1
717*c4762a1bSJed Brown         j = irow/solver%mx
718*c4762a1bSJed Brown         i = mod(irow,solver%mx)
719*c4762a1bSJed Brown         ii = ii + 1            ! one based local index
720*c4762a1bSJed Brown         row(1) = irow
721*c4762a1bSJed Brown         if (i .eq. 0 .or. j .eq. 0 .or. i .eq. solver%mx-1 .or. j .eq. solver%my-1 ) then
722*c4762a1bSJed Brown            v(1) = 0.0
723*c4762a1bSJed Brown         else
724*c4762a1bSJed Brown            u = lx_v(ii)
725*c4762a1bSJed Brown            v(1) = -sc*exp(u)
726*c4762a1bSJed Brown         endif
727*c4762a1bSJed Brown         call VecSetValues(F1,ione,row,v,INSERT_VALUES,ierr);CHKERRQ(ierr)
728*c4762a1bSJed Brown 20   continue
729*c4762a1bSJed Brown
730*c4762a1bSJed Brown      call VecRestoreArrayReadF90(X1,lx_v,ierr);CHKERRQ(ierr)
731*c4762a1bSJed Brown
732*c4762a1bSJed Brown      call VecAssemblyBegin(F1,ierr);CHKERRQ(ierr)
733*c4762a1bSJed Brown      call VecAssemblyEnd(F1,ierr);CHKERRQ(ierr)
734*c4762a1bSJed Brown
735*c4762a1bSJed Brown      ierr = 0
736*c4762a1bSJed Brown      return
737*c4762a1bSJed Brown      end subroutine FormFunctionNLTerm
738*c4762a1bSJed Brown
739*c4762a1bSJed Brown!/*TEST
740*c4762a1bSJed Brown!
741*c4762a1bSJed Brown!   build:
742*c4762a1bSJed Brown!      requires: !single !pgf90_compiler !complex
743*c4762a1bSJed Brown!
744*c4762a1bSJed Brown!   test:
745*c4762a1bSJed Brown!      nsize: 4
746*c4762a1bSJed Brown!      args: -par 5.0 -da_grid_x 10 -da_grid_y 10 -snes_monitor_short -snes_linesearch_type basic -snes_converged_reason -ksp_type fgmres -ksp_norm_type unpreconditioned -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_fact_type upper -ksp_monitor_short -fieldsplit_lambda_ksp_type preonly -fieldsplit_lambda_pc_type jacobi -fieldsplit_phi_pc_type gamg -fieldsplit_phi_pc_gamg_agg_nsmooths 1 -fieldsplit_phi_pc_gamg_threshold 0. -fieldsplit_phi_pc_gamg_esteig_ksp_type cg
747*c4762a1bSJed Brown!
748*c4762a1bSJed Brown!TEST*/
749