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