1c4762a1bSJed Brown! 2c4762a1bSJed Brown! Description: This example solves a nonlinear system on 1 processor with SNES. 3c4762a1bSJed Brown! We solve the Bratu (SFI - solid fuel ignition) problem in a 2D rectangular 4c4762a1bSJed Brown! domain. The command line options include: 5c4762a1bSJed Brown! -par <parameter>, where <parameter> indicates the nonlinearity of the problem 6c4762a1bSJed Brown! problem SFI: <parameter> = Bratu parameter (0 <= par <= 6.81) 7c4762a1bSJed Brown! -mx <xg>, where <xg> = number of grid points in the x-direction 8c4762a1bSJed Brown! -my <yg>, where <yg> = number of grid points in the y-direction 9c4762a1bSJed Brown! 10c4762a1bSJed Brown 11c4762a1bSJed Brown! 12c4762a1bSJed Brown! -------------------------------------------------------------------------- 13c4762a1bSJed Brown! 14c4762a1bSJed Brown! Solid Fuel Ignition (SFI) problem. This problem is modeled by 15c4762a1bSJed Brown! the partial differential equation 16c4762a1bSJed Brown! 17c4762a1bSJed Brown! -Laplacian u - lambda*exp(u) = 0, 0 < x,y < 1, 18c4762a1bSJed Brown! 19c4762a1bSJed Brown! with boundary conditions 20c4762a1bSJed Brown! 21c4762a1bSJed Brown! u = 0 for x = 0, x = 1, y = 0, y = 1. 22c4762a1bSJed Brown! 23c4762a1bSJed Brown! A finite difference approximation with the usual 5-point stencil 24c4762a1bSJed Brown! is used to discretize the boundary value problem to obtain a nonlinear 25c4762a1bSJed Brown! system of equations. 26c4762a1bSJed Brown! 27c4762a1bSJed Brown! The parallel version of this code is snes/tutorials/ex5f.F 28c4762a1bSJed Brown! 29c4762a1bSJed Brown! -------------------------------------------------------------------------- 30c4762a1bSJed Brown#include <petsc/finclude/petscsnes.h> 31c5e229c2SMartin Diehl#include <petsc/finclude/petscdraw.h> 3201fa2b5aSMartin Diehlmodule ex1fmodule 33c4762a1bSJed Brown use petscsnes 34c4762a1bSJed Brown implicit none 35e7a95102SMartin Diehlcontains 36e7a95102SMartin Diehl subroutine postcheck(snes, x, y, w, changed_y, changed_w, ctx, ierr) 37c4762a1bSJed Brown SNES snes 38c4762a1bSJed Brown PetscReal norm 39c4762a1bSJed Brown Vec tmp, x, y, w 40c4762a1bSJed Brown PetscBool changed_w, changed_y 41c4762a1bSJed Brown PetscErrorCode ierr 42c4762a1bSJed Brown PetscInt ctx 43c4762a1bSJed Brown PetscScalar mone 44*b06eb4cdSBarry Smith MPIU_Comm comm 45c4762a1bSJed Brown 4624fb275aSStefano Zampini character(len=PETSC_MAX_PATH_LEN) :: outputString 4724fb275aSStefano Zampini 4824fb275aSStefano Zampini PetscCallA(PetscObjectGetComm(snes, comm, ierr)) 49d8606c27SBarry Smith PetscCallA(VecDuplicate(x, tmp, ierr)) 50c4762a1bSJed Brown mone = -1.0 51d8606c27SBarry Smith PetscCallA(VecWAXPY(tmp, mone, x, w, ierr)) 52d8606c27SBarry Smith PetscCallA(VecNorm(tmp, NORM_2, norm, ierr)) 53d8606c27SBarry Smith PetscCallA(VecDestroy(tmp, ierr)) 5424fb275aSStefano Zampini write (outputString, *) norm 5524fb275aSStefano Zampini PetscCallA(PetscPrintf(comm, 'Norm of search step '//trim(outputString)//'\n', ierr)) 56c4762a1bSJed Brown end 57c4762a1bSJed Brown 58e7a95102SMartin Diehl! --------------------------------------------------------------------- 59e7a95102SMartin Diehl! 60e7a95102SMartin Diehl! FormInitialGuess - Forms initial approximation. 61e7a95102SMartin Diehl! 62e7a95102SMartin Diehl! Input Parameter: 63e7a95102SMartin Diehl! X - vector 64e7a95102SMartin Diehl! 65e7a95102SMartin Diehl! Output Parameters: 66e7a95102SMartin Diehl! X - vector 67e7a95102SMartin Diehl! ierr - error code 68e7a95102SMartin Diehl! 69e7a95102SMartin Diehl! Notes: 70e7a95102SMartin Diehl! This routine serves as a wrapper for the lower-level routine 71e7a95102SMartin Diehl! "ApplicationInitialGuess", where the actual computations are 72e7a95102SMartin Diehl! done using the standard Fortran style of treating the local 73e7a95102SMartin Diehl! vector data as a multidimensional array over the local mesh. 74e7a95102SMartin Diehl! This routine merely accesses the local vector data via 75e7a95102SMartin Diehl! VecGetArray() and VecRestoreArray(). 76e7a95102SMartin Diehl! 77e7a95102SMartin Diehl subroutine FormInitialGuess(X, ierr) 78e7a95102SMartin Diehl 79e7a95102SMartin Diehl! Input/output variables: 80e7a95102SMartin Diehl Vec X 81e7a95102SMartin Diehl PetscErrorCode ierr 82e7a95102SMartin Diehl 83e7a95102SMartin Diehl! Declarations for use with local arrays: 84e7a95102SMartin Diehl PetscScalar, pointer :: lx_v(:) 85e7a95102SMartin Diehl 86e7a95102SMartin Diehl ierr = 0 87e7a95102SMartin Diehl 88e7a95102SMartin Diehl! Get a pointer to vector data. 89e7a95102SMartin Diehl! - VecGetArray() returns a pointer to the data array. 90e7a95102SMartin Diehl! - You MUST call VecRestoreArray() when you no longer need access to 91e7a95102SMartin Diehl! the array. 92e7a95102SMartin Diehl 93e7a95102SMartin Diehl PetscCallA(VecGetArray(X, lx_v, ierr)) 94e7a95102SMartin Diehl 95e7a95102SMartin Diehl! Compute initial guess 96e7a95102SMartin Diehl 97e7a95102SMartin Diehl PetscCallA(ApplicationInitialGuess(lx_v, ierr)) 98e7a95102SMartin Diehl 99e7a95102SMartin Diehl! Restore vector 100e7a95102SMartin Diehl 101e7a95102SMartin Diehl PetscCallA(VecRestoreArray(X, lx_v, ierr)) 102e7a95102SMartin Diehl 103e7a95102SMartin Diehl end 104e7a95102SMartin Diehl 105e7a95102SMartin Diehl! ApplicationInitialGuess - Computes initial approximation, called by 106e7a95102SMartin Diehl! the higher level routine FormInitialGuess(). 107e7a95102SMartin Diehl! 108e7a95102SMartin Diehl! Input Parameter: 109e7a95102SMartin Diehl! x - local vector data 110e7a95102SMartin Diehl! 111e7a95102SMartin Diehl! Output Parameters: 112e7a95102SMartin Diehl! f - local vector data, f(x) 113e7a95102SMartin Diehl! ierr - error code 114e7a95102SMartin Diehl! 115e7a95102SMartin Diehl! Notes: 116e7a95102SMartin Diehl! This routine uses standard Fortran-style computations over a 2-dim array. 117e7a95102SMartin Diehl! 118e7a95102SMartin Diehl subroutine ApplicationInitialGuess(x, ierr) 119e7a95102SMartin Diehl 120e7a95102SMartin Diehl! Common blocks: 121e7a95102SMartin Diehl PetscReal lambda 122e7a95102SMartin Diehl PetscInt mx, my 123e7a95102SMartin Diehl PetscBool fd_coloring 124e7a95102SMartin Diehl common/params/lambda, mx, my, fd_coloring 125e7a95102SMartin Diehl 126e7a95102SMartin Diehl! Input/output variables: 127e7a95102SMartin Diehl PetscScalar x(mx, my) 128e7a95102SMartin Diehl PetscErrorCode ierr 129e7a95102SMartin Diehl 130e7a95102SMartin Diehl! Local variables: 131e7a95102SMartin Diehl PetscInt i, j 132e7a95102SMartin Diehl PetscReal temp1, temp, hx, hy, one 133e7a95102SMartin Diehl 134e7a95102SMartin Diehl! Set parameters 135e7a95102SMartin Diehl 136e7a95102SMartin Diehl ierr = 0 137e7a95102SMartin Diehl one = 1.0 138e7a95102SMartin Diehl hx = one/(mx - 1) 139e7a95102SMartin Diehl hy = one/(my - 1) 140e7a95102SMartin Diehl temp1 = lambda/(lambda + one) 141e7a95102SMartin Diehl 142e7a95102SMartin Diehl do j = 1, my 143e7a95102SMartin Diehl temp = min(j - 1, my - j)*hy 144e7a95102SMartin Diehl do i = 1, mx 145e7a95102SMartin Diehl if (i == 1 .or. j == 1 .or. i == mx .or. j == my) then 146e7a95102SMartin Diehl x(i, j) = 0.0 147e7a95102SMartin Diehl else 148e7a95102SMartin Diehl x(i, j) = temp1*sqrt(min(min(i - 1, mx - i)*hx, temp)) 149e7a95102SMartin Diehl end if 150e7a95102SMartin Diehl end do 151e7a95102SMartin Diehl end do 152e7a95102SMartin Diehl 153e7a95102SMartin Diehl end 154e7a95102SMartin Diehl 155e7a95102SMartin Diehl! --------------------------------------------------------------------- 156e7a95102SMartin Diehl! 157e7a95102SMartin Diehl! FormFunction - Evaluates nonlinear function, F(x). 158e7a95102SMartin Diehl! 159e7a95102SMartin Diehl! Input Parameters: 160e7a95102SMartin Diehl! snes - the SNES context 161e7a95102SMartin Diehl! X - input vector 162e7a95102SMartin Diehl! dummy - optional user-defined context, as set by SNESSetFunction() 163e7a95102SMartin Diehl! (not used here) 164e7a95102SMartin Diehl! 165e7a95102SMartin Diehl! Output Parameter: 166e7a95102SMartin Diehl! F - vector with newly computed function 167e7a95102SMartin Diehl! 168e7a95102SMartin Diehl! Notes: 169e7a95102SMartin Diehl! This routine serves as a wrapper for the lower-level routine 170e7a95102SMartin Diehl! "ApplicationFunction", where the actual computations are 171e7a95102SMartin Diehl! done using the standard Fortran style of treating the local 172e7a95102SMartin Diehl! vector data as a multidimensional array over the local mesh. 173e7a95102SMartin Diehl! This routine merely accesses the local vector data via 174e7a95102SMartin Diehl! VecGetArray() and VecRestoreArray(). 175e7a95102SMartin Diehl! 176e7a95102SMartin Diehl subroutine FormFunction(snes, X, F, fdcoloring, ierr) 177e7a95102SMartin Diehl 178e7a95102SMartin Diehl! Input/output variables: 179e7a95102SMartin Diehl SNES snes 180e7a95102SMartin Diehl Vec X, F 181e7a95102SMartin Diehl PetscErrorCode ierr 182e7a95102SMartin Diehl MatFDColoring fdcoloring 183e7a95102SMartin Diehl 184e7a95102SMartin Diehl! Common blocks: 185e7a95102SMartin Diehl PetscReal lambda 186e7a95102SMartin Diehl PetscInt mx, my 187e7a95102SMartin Diehl PetscBool fd_coloring 188e7a95102SMartin Diehl common/params/lambda, mx, my, fd_coloring 189e7a95102SMartin Diehl 190e7a95102SMartin Diehl! Declarations for use with local arrays: 191e7a95102SMartin Diehl PetscScalar, pointer :: lx_v(:), lf_v(:) 192e7a95102SMartin Diehl PetscInt, pointer :: indices(:) 193e7a95102SMartin Diehl 194e7a95102SMartin Diehl! Get pointers to vector data. 195e7a95102SMartin Diehl! - VecGetArray() returns a pointer to the data array. 196e7a95102SMartin Diehl! - You MUST call VecRestoreArray() when you no longer need access to 197e7a95102SMartin Diehl! the array. 198e7a95102SMartin Diehl 199e7a95102SMartin Diehl PetscCallA(VecGetArrayRead(X, lx_v, ierr)) 200e7a95102SMartin Diehl PetscCallA(VecGetArray(F, lf_v, ierr)) 201e7a95102SMartin Diehl 202e7a95102SMartin Diehl! Compute function 203e7a95102SMartin Diehl 204e7a95102SMartin Diehl PetscCallA(ApplicationFunction(lx_v, lf_v, ierr)) 205e7a95102SMartin Diehl 206e7a95102SMartin Diehl! Restore vectors 207e7a95102SMartin Diehl 208e7a95102SMartin Diehl PetscCallA(VecRestoreArrayRead(X, lx_v, ierr)) 209e7a95102SMartin Diehl PetscCallA(VecRestoreArray(F, lf_v, ierr)) 210e7a95102SMartin Diehl 211e7a95102SMartin Diehl PetscCallA(PetscLogFlops(11.0d0*mx*my, ierr)) 212e7a95102SMartin Diehl! 213e7a95102SMartin Diehl! fdcoloring is in the common block and used here ONLY to test the 214e7a95102SMartin Diehl! calls to MatFDColoringGetPerturbedColumns() and MatFDColoringRestorePerturbedColumns() 215e7a95102SMartin Diehl! 216e7a95102SMartin Diehl if (fd_coloring) then 217e7a95102SMartin Diehl PetscCallA(MatFDColoringGetPerturbedColumns(fdcoloring, PETSC_NULL_INTEGER, indices, ierr)) 218e7a95102SMartin Diehl print *, 'Indices from GetPerturbedColumns' 219e7a95102SMartin Diehl write (*, 1000) indices 220e7a95102SMartin Diehl1000 format(50i4) 221e7a95102SMartin Diehl PetscCallA(MatFDColoringRestorePerturbedColumns(fdcoloring, PETSC_NULL_INTEGER, indices, ierr)) 222e7a95102SMartin Diehl end if 223e7a95102SMartin Diehl end 224e7a95102SMartin Diehl 225e7a95102SMartin Diehl! --------------------------------------------------------------------- 226e7a95102SMartin Diehl! 227e7a95102SMartin Diehl! ApplicationFunction - Computes nonlinear function, called by 228e7a95102SMartin Diehl! the higher level routine FormFunction(). 229e7a95102SMartin Diehl! 230e7a95102SMartin Diehl! Input Parameter: 231e7a95102SMartin Diehl! x - local vector data 232e7a95102SMartin Diehl! 233e7a95102SMartin Diehl! Output Parameters: 234e7a95102SMartin Diehl! f - local vector data, f(x) 235e7a95102SMartin Diehl! ierr - error code 236e7a95102SMartin Diehl! 237e7a95102SMartin Diehl! Notes: 238e7a95102SMartin Diehl! This routine uses standard Fortran-style computations over a 2-dim array. 239e7a95102SMartin Diehl! 240e7a95102SMartin Diehl subroutine ApplicationFunction(x, f, ierr) 241e7a95102SMartin Diehl 242e7a95102SMartin Diehl! Common blocks: 243e7a95102SMartin Diehl PetscReal lambda 244e7a95102SMartin Diehl PetscInt mx, my 245e7a95102SMartin Diehl PetscBool fd_coloring 246e7a95102SMartin Diehl common/params/lambda, mx, my, fd_coloring 247e7a95102SMartin Diehl 248e7a95102SMartin Diehl! Input/output variables: 249e7a95102SMartin Diehl PetscScalar x(mx, my), f(mx, my) 250e7a95102SMartin Diehl PetscErrorCode ierr 251e7a95102SMartin Diehl 252e7a95102SMartin Diehl! Local variables: 253e7a95102SMartin Diehl PetscScalar two, one, hx, hy 254e7a95102SMartin Diehl PetscScalar hxdhy, hydhx, sc 255e7a95102SMartin Diehl PetscScalar u, uxx, uyy 256e7a95102SMartin Diehl PetscInt i, j 257e7a95102SMartin Diehl 258e7a95102SMartin Diehl ierr = 0 259e7a95102SMartin Diehl one = 1.0 260e7a95102SMartin Diehl two = 2.0 261e7a95102SMartin Diehl hx = one/(mx - 1) 262e7a95102SMartin Diehl hy = one/(my - 1) 263e7a95102SMartin Diehl sc = hx*hy*lambda 264e7a95102SMartin Diehl hxdhy = hx/hy 265e7a95102SMartin Diehl hydhx = hy/hx 266e7a95102SMartin Diehl 267e7a95102SMartin Diehl! Compute function 268e7a95102SMartin Diehl 269e7a95102SMartin Diehl do j = 1, my 270e7a95102SMartin Diehl do i = 1, mx 271e7a95102SMartin Diehl if (i == 1 .or. j == 1 .or. i == mx .or. j == my) then 272e7a95102SMartin Diehl f(i, j) = x(i, j) 273e7a95102SMartin Diehl else 274e7a95102SMartin Diehl u = x(i, j) 275e7a95102SMartin Diehl uxx = hydhx*(two*u - x(i - 1, j) - x(i + 1, j)) 276e7a95102SMartin Diehl uyy = hxdhy*(two*u - x(i, j - 1) - x(i, j + 1)) 277e7a95102SMartin Diehl f(i, j) = uxx + uyy - sc*exp(u) 278e7a95102SMartin Diehl end if 279e7a95102SMartin Diehl end do 280e7a95102SMartin Diehl end do 281e7a95102SMartin Diehl 282e7a95102SMartin Diehl end 283e7a95102SMartin Diehl 284e7a95102SMartin Diehl! --------------------------------------------------------------------- 285e7a95102SMartin Diehl! 286e7a95102SMartin Diehl! FormJacobian - Evaluates Jacobian matrix. 287e7a95102SMartin Diehl! 288e7a95102SMartin Diehl! Input Parameters: 289e7a95102SMartin Diehl! snes - the SNES context 290e7a95102SMartin Diehl! x - input vector 291e7a95102SMartin Diehl! dummy - optional user-defined context, as set by SNESSetJacobian() 292e7a95102SMartin Diehl! (not used here) 293e7a95102SMartin Diehl! 294e7a95102SMartin Diehl! Output Parameters: 295e7a95102SMartin Diehl! jac - Jacobian matrix 296e7a95102SMartin Diehl! jac_prec - optionally different matrix used to construct the preconditioner (not used here) 297e7a95102SMartin Diehl! 298e7a95102SMartin Diehl! Notes: 299e7a95102SMartin Diehl! This routine serves as a wrapper for the lower-level routine 300e7a95102SMartin Diehl! "ApplicationJacobian", where the actual computations are 301e7a95102SMartin Diehl! done using the standard Fortran style of treating the local 302e7a95102SMartin Diehl! vector data as a multidimensional array over the local mesh. 303e7a95102SMartin Diehl! This routine merely accesses the local vector data via 304e7a95102SMartin Diehl! VecGetArray() and VecRestoreArray(). 305e7a95102SMartin Diehl! 306e7a95102SMartin Diehl subroutine FormJacobian(snes, X, jac, jac_prec, dummy, ierr) 307e7a95102SMartin Diehl 308e7a95102SMartin Diehl! Input/output variables: 309e7a95102SMartin Diehl SNES snes 310e7a95102SMartin Diehl Vec X 311e7a95102SMartin Diehl Mat jac, jac_prec 312e7a95102SMartin Diehl PetscErrorCode ierr 313e7a95102SMartin Diehl integer dummy 314e7a95102SMartin Diehl 315e7a95102SMartin Diehl! Common blocks: 316e7a95102SMartin Diehl PetscReal lambda 317e7a95102SMartin Diehl PetscInt mx, my 318e7a95102SMartin Diehl PetscBool fd_coloring 319e7a95102SMartin Diehl common/params/lambda, mx, my, fd_coloring 320e7a95102SMartin Diehl 321e7a95102SMartin Diehl! Declarations for use with local array: 322e7a95102SMartin Diehl PetscScalar, pointer :: lx_v(:) 323e7a95102SMartin Diehl 324e7a95102SMartin Diehl! Get a pointer to vector data 325e7a95102SMartin Diehl 326e7a95102SMartin Diehl PetscCallA(VecGetArrayRead(X, lx_v, ierr)) 327e7a95102SMartin Diehl 328e7a95102SMartin Diehl! Compute Jacobian entries 329e7a95102SMartin Diehl 330e7a95102SMartin Diehl PetscCallA(ApplicationJacobian(lx_v, jac, jac_prec, ierr)) 331e7a95102SMartin Diehl 332e7a95102SMartin Diehl! Restore vector 333e7a95102SMartin Diehl 334e7a95102SMartin Diehl PetscCallA(VecRestoreArrayRead(X, lx_v, ierr)) 335e7a95102SMartin Diehl 336e7a95102SMartin Diehl! Assemble matrix 337e7a95102SMartin Diehl 338e7a95102SMartin Diehl PetscCallA(MatAssemblyBegin(jac_prec, MAT_FINAL_ASSEMBLY, ierr)) 339e7a95102SMartin Diehl PetscCallA(MatAssemblyEnd(jac_prec, MAT_FINAL_ASSEMBLY, ierr)) 340e7a95102SMartin Diehl 341e7a95102SMartin Diehl end 342e7a95102SMartin Diehl 343e7a95102SMartin Diehl! --------------------------------------------------------------------- 344e7a95102SMartin Diehl! 345e7a95102SMartin Diehl! ApplicationJacobian - Computes Jacobian matrix, called by 346e7a95102SMartin Diehl! the higher level routine FormJacobian(). 347e7a95102SMartin Diehl! 348e7a95102SMartin Diehl! Input Parameters: 349e7a95102SMartin Diehl! x - local vector data 350e7a95102SMartin Diehl! 351e7a95102SMartin Diehl! Output Parameters: 352e7a95102SMartin Diehl! jac - Jacobian matrix 353e7a95102SMartin Diehl! jac_prec - optionally different matrix used to construct the preconditioner (not used here) 354e7a95102SMartin Diehl! ierr - error code 355e7a95102SMartin Diehl! 356e7a95102SMartin Diehl! Notes: 357e7a95102SMartin Diehl! This routine uses standard Fortran-style computations over a 2-dim array. 358e7a95102SMartin Diehl! 359e7a95102SMartin Diehl subroutine ApplicationJacobian(x, jac, jac_prec, ierr) 360e7a95102SMartin Diehl! Common blocks: 361e7a95102SMartin Diehl PetscReal lambda 362e7a95102SMartin Diehl PetscInt mx, my 363e7a95102SMartin Diehl PetscBool fd_coloring 364e7a95102SMartin Diehl common/params/lambda, mx, my, fd_coloring 365e7a95102SMartin Diehl 366e7a95102SMartin Diehl! Input/output variables: 367e7a95102SMartin Diehl PetscScalar x(mx, my) 368e7a95102SMartin Diehl Mat jac, jac_prec 369e7a95102SMartin Diehl PetscErrorCode ierr 370e7a95102SMartin Diehl 371e7a95102SMartin Diehl! Local variables: 372e7a95102SMartin Diehl PetscInt i, j, row(1), col(5), i1, i5 373e7a95102SMartin Diehl PetscScalar two, one, hx, hy 374e7a95102SMartin Diehl PetscScalar hxdhy, hydhx, sc, v(5) 375e7a95102SMartin Diehl 376e7a95102SMartin Diehl! Set parameters 377e7a95102SMartin Diehl 378e7a95102SMartin Diehl i1 = 1 379e7a95102SMartin Diehl i5 = 5 380e7a95102SMartin Diehl one = 1.0 381e7a95102SMartin Diehl two = 2.0 382e7a95102SMartin Diehl hx = one/(mx - 1) 383e7a95102SMartin Diehl hy = one/(my - 1) 384e7a95102SMartin Diehl sc = hx*hy 385e7a95102SMartin Diehl hxdhy = hx/hy 386e7a95102SMartin Diehl hydhx = hy/hx 387e7a95102SMartin Diehl 388e7a95102SMartin Diehl! Compute entries of the Jacobian matrix 389e7a95102SMartin Diehl! - Here, we set all entries for a particular row at once. 390e7a95102SMartin Diehl! - Note that MatSetValues() uses 0-based row and column numbers 391e7a95102SMartin Diehl! in Fortran as well as in C. 392e7a95102SMartin Diehl 393e7a95102SMartin Diehl do j = 1, my 394e7a95102SMartin Diehl row(1) = (j - 1)*mx - 1 395e7a95102SMartin Diehl do i = 1, mx 396e7a95102SMartin Diehl row(1) = row(1) + 1 397e7a95102SMartin Diehl! boundary points 398e7a95102SMartin Diehl if (i == 1 .or. j == 1 .or. i == mx .or. j == my) then 399e7a95102SMartin Diehl PetscCallA(MatSetValues(jac_prec, i1, row, i1, row, [one], INSERT_VALUES, ierr)) 400e7a95102SMartin Diehl! interior grid points 401e7a95102SMartin Diehl else 402e7a95102SMartin Diehl v(1) = -hxdhy 403e7a95102SMartin Diehl v(2) = -hydhx 404e7a95102SMartin Diehl v(3) = two*(hydhx + hxdhy) - sc*lambda*exp(x(i, j)) 405e7a95102SMartin Diehl v(4) = -hydhx 406e7a95102SMartin Diehl v(5) = -hxdhy 407e7a95102SMartin Diehl col(1) = row(1) - mx 408e7a95102SMartin Diehl col(2) = row(1) - 1 409e7a95102SMartin Diehl col(3) = row(1) 410e7a95102SMartin Diehl col(4) = row(1) + 1 411e7a95102SMartin Diehl col(5) = row(1) + mx 412e7a95102SMartin Diehl PetscCallA(MatSetValues(jac_prec, i1, row, i5, col, v, INSERT_VALUES, ierr)) 413e7a95102SMartin Diehl end if 414e7a95102SMartin Diehl end do 415e7a95102SMartin Diehl end do 416e7a95102SMartin Diehl 417e7a95102SMartin Diehl end 418e7a95102SMartin Diehl 41901fa2b5aSMartin Diehlend module ex1fmodule 420c4762a1bSJed Brownprogram main 421ce78bad3SBarry Smith use petscdraw 422c4762a1bSJed Brown use petscsnes 42301fa2b5aSMartin Diehl use ex1fmodule 424c4762a1bSJed Brown implicit none 425c4762a1bSJed Brown! 426c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 427c4762a1bSJed Brown! Variable declarations 428c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 429c4762a1bSJed Brown! 430c4762a1bSJed Brown! Variables: 431c4762a1bSJed Brown! snes - nonlinear solver 432c4762a1bSJed Brown! x, r - solution, residual vectors 433c4762a1bSJed Brown! J - Jacobian matrix 434c4762a1bSJed Brown! its - iterations for convergence 435c4762a1bSJed Brown! matrix_free - flag - 1 indicates matrix-free version 436c4762a1bSJed Brown! lambda - nonlinearity parameter 437c4762a1bSJed Brown! draw - drawing context 438c4762a1bSJed Brown! 439c4762a1bSJed Brown SNES snes 440c4762a1bSJed Brown MatColoring mc 441c4762a1bSJed Brown Vec x, r 442c4762a1bSJed Brown PetscDraw draw 443c4762a1bSJed Brown Mat J 444c4762a1bSJed Brown PetscBool matrix_free, flg, fd_coloring 445c4762a1bSJed Brown PetscErrorCode ierr 446c4762a1bSJed Brown PetscInt its, N, mx, my, i5 447c4762a1bSJed Brown PetscMPIInt size, rank 448c4762a1bSJed Brown PetscReal lambda_max, lambda_min, lambda 449c4762a1bSJed Brown MatFDColoring fdcoloring 450c4762a1bSJed Brown ISColoring iscoloring 451c4762a1bSJed Brown PetscBool pc 452ce78bad3SBarry Smith integer4 imx, imy 45324fb275aSStefano Zampini character(len=PETSC_MAX_PATH_LEN) :: outputString 45442ce371bSBarry Smith PetscScalar, pointer :: lx_v(:) 455ce78bad3SBarry Smith integer4 xl, yl, width, height 456c4762a1bSJed Brown 457c4762a1bSJed Brown! Store parameters in common block 458c4762a1bSJed Brown 459c4762a1bSJed Brown common/params/lambda, mx, my, fd_coloring 460c4762a1bSJed Brown 461c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 462c4762a1bSJed Brown! Initialize program 463c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 464c4762a1bSJed Brown 465d8606c27SBarry Smith PetscCallA(PetscInitialize(ierr)) 466d8606c27SBarry Smith PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD, size, ierr)) 467d8606c27SBarry Smith PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD, rank, ierr)) 468c4762a1bSJed Brown 4694820e4eaSBarry Smith PetscCheckA(size == 1, PETSC_COMM_SELF, PETSC_ERR_WRONG_MPI_SIZE, 'This is a uniprocessor example only') 470c4762a1bSJed Brown 471c4762a1bSJed Brown! Initialize problem parameters 472c4762a1bSJed Brown i5 = 5 473c4762a1bSJed Brown lambda_max = 6.81 474c4762a1bSJed Brown lambda_min = 0.0 475c4762a1bSJed Brown lambda = 6.0 476c4762a1bSJed Brown mx = 4 477c4762a1bSJed Brown my = 4 478d8606c27SBarry Smith PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-mx', mx, flg, ierr)) 479d8606c27SBarry Smith PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-my', my, flg, ierr)) 480d8606c27SBarry Smith PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-par', lambda, flg, ierr)) 4814820e4eaSBarry Smith PetscCheckA(lambda < lambda_max .and. lambda > lambda_min, PETSC_COMM_SELF, PETSC_ERR_USER, 'Lambda out of range ') 482c4762a1bSJed Brown N = mx*my 483c4762a1bSJed Brown pc = PETSC_FALSE 484d8606c27SBarry Smith PetscCallA(PetscOptionsGetBool(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-pc', pc, PETSC_NULL_BOOL, ierr)) 485c4762a1bSJed Brown 486c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 487c4762a1bSJed Brown! Create nonlinear solver context 488c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 489c4762a1bSJed Brown 490d8606c27SBarry Smith PetscCallA(SNESCreate(PETSC_COMM_WORLD, snes, ierr)) 491c4762a1bSJed Brown 492c4762a1bSJed Brown if (pc .eqv. PETSC_TRUE) then 493d8606c27SBarry Smith PetscCallA(SNESSetType(snes, SNESNEWTONTR, ierr)) 494d8606c27SBarry Smith PetscCallA(SNESNewtonTRSetPostCheck(snes, postcheck, snes, ierr)) 495c4762a1bSJed Brown end if 496c4762a1bSJed Brown 497c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 498c4762a1bSJed Brown! Create vector data structures; set function evaluation routine 499c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 500c4762a1bSJed Brown 501d8606c27SBarry Smith PetscCallA(VecCreate(PETSC_COMM_WORLD, x, ierr)) 502d8606c27SBarry Smith PetscCallA(VecSetSizes(x, PETSC_DECIDE, N, ierr)) 503d8606c27SBarry Smith PetscCallA(VecSetFromOptions(x, ierr)) 504d8606c27SBarry Smith PetscCallA(VecDuplicate(x, r, ierr)) 505c4762a1bSJed Brown 506c4762a1bSJed Brown! Set function evaluation routine and vector. Whenever the nonlinear 507c4762a1bSJed Brown! solver needs to evaluate the nonlinear function, it will call this 508c4762a1bSJed Brown! routine. 509c4762a1bSJed Brown! - Note that the final routine argument is the user-defined 510c4762a1bSJed Brown! context that provides application-specific data for the 511c4762a1bSJed Brown! function evaluation routine. 512c4762a1bSJed Brown 513d8606c27SBarry Smith PetscCallA(SNESSetFunction(snes, r, FormFunction, fdcoloring, ierr)) 514c4762a1bSJed Brown 515c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 516c4762a1bSJed Brown! Create matrix data structure; set Jacobian evaluation routine 517c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 518c4762a1bSJed Brown 519c4762a1bSJed Brown! Create matrix. Here we only approximately preallocate storage space 520c4762a1bSJed Brown! for the Jacobian. See the users manual for a discussion of better 521c4762a1bSJed Brown! techniques for preallocating matrix memory. 522c4762a1bSJed Brown 523d8606c27SBarry Smith PetscCallA(PetscOptionsHasName(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-snes_mf', matrix_free, ierr)) 524c4762a1bSJed Brown if (.not. matrix_free) then 5255d83a8b1SBarry Smith PetscCallA(MatCreateSeqAIJ(PETSC_COMM_WORLD, N, N, i5, PETSC_NULL_INTEGER_ARRAY, J, ierr)) 526c4762a1bSJed Brown end if 527c4762a1bSJed Brown 528c4762a1bSJed Brown! 529c4762a1bSJed Brown! This option will cause the Jacobian to be computed via finite differences 530c4762a1bSJed Brown! efficiently using a coloring of the columns of the matrix. 531c4762a1bSJed Brown! 532c4762a1bSJed Brown fd_coloring = .false. 533d8606c27SBarry Smith PetscCallA(PetscOptionsHasName(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-snes_fd_coloring', fd_coloring, ierr)) 534c4762a1bSJed Brown if (fd_coloring) then 535c4762a1bSJed Brown 536c4762a1bSJed Brown! 537c4762a1bSJed Brown! This initializes the nonzero structure of the Jacobian. This is artificial 538c4762a1bSJed Brown! because clearly if we had a routine to compute the Jacobian we won't need 539c4762a1bSJed Brown! to use finite differences. 540c4762a1bSJed Brown! 541d8606c27SBarry Smith PetscCallA(FormJacobian(snes, x, J, J, 0, ierr)) 542c4762a1bSJed Brown! 543c4762a1bSJed Brown! Color the matrix, i.e. determine groups of columns that share no common 544a5b23f4aSJose E. Roman! rows. These columns in the Jacobian can all be computed simultaneously. 545c4762a1bSJed Brown! 546d8606c27SBarry Smith PetscCallA(MatColoringCreate(J, mc, ierr)) 547d8606c27SBarry Smith PetscCallA(MatColoringSetType(mc, MATCOLORINGNATURAL, ierr)) 548d8606c27SBarry Smith PetscCallA(MatColoringSetFromOptions(mc, ierr)) 549d8606c27SBarry Smith PetscCallA(MatColoringApply(mc, iscoloring, ierr)) 550d8606c27SBarry Smith PetscCallA(MatColoringDestroy(mc, ierr)) 551c4762a1bSJed Brown! 552c4762a1bSJed Brown! Create the data structure that SNESComputeJacobianDefaultColor() uses 553c4762a1bSJed Brown! to compute the actual Jacobians via finite differences. 554c4762a1bSJed Brown! 555d8606c27SBarry Smith PetscCallA(MatFDColoringCreate(J, iscoloring, fdcoloring, ierr)) 556d8606c27SBarry Smith PetscCallA(MatFDColoringSetFunction(fdcoloring, FormFunction, fdcoloring, ierr)) 557d8606c27SBarry Smith PetscCallA(MatFDColoringSetFromOptions(fdcoloring, ierr)) 558d8606c27SBarry Smith PetscCallA(MatFDColoringSetUp(J, iscoloring, fdcoloring, ierr)) 559c4762a1bSJed Brown! 560c4762a1bSJed Brown! Tell SNES to use the routine SNESComputeJacobianDefaultColor() 561c4762a1bSJed Brown! to compute Jacobians. 562c4762a1bSJed Brown! 563d8606c27SBarry Smith PetscCallA(SNESSetJacobian(snes, J, J, SNESComputeJacobianDefaultColor, fdcoloring, ierr)) 564d8606c27SBarry Smith PetscCallA(ISColoringDestroy(iscoloring, ierr)) 565c4762a1bSJed Brown 566c4762a1bSJed Brown else if (.not. matrix_free) then 567c4762a1bSJed Brown 568c4762a1bSJed Brown! Set Jacobian matrix data structure and default Jacobian evaluation 569c4762a1bSJed Brown! routine. Whenever the nonlinear solver needs to compute the 570c4762a1bSJed Brown! Jacobian matrix, it will call this routine. 571c4762a1bSJed Brown! - Note that the final routine argument is the user-defined 572c4762a1bSJed Brown! context that provides application-specific data for the 573c4762a1bSJed Brown! Jacobian evaluation routine. 574c4762a1bSJed Brown! - The user can override with: 575c4762a1bSJed Brown! -snes_fd : default finite differencing approximation of Jacobian 576c4762a1bSJed Brown! -snes_mf : matrix-free Newton-Krylov method with no preconditioning 577c4762a1bSJed Brown! (unless user explicitly sets preconditioner) 5787addb90fSBarry Smith! -snes_mf_operator : form matrix from which to construct the preconditioner as set by the user, 579c4762a1bSJed Brown! but use matrix-free approx for Jacobian-vector 580c4762a1bSJed Brown! products within Newton-Krylov method 581c4762a1bSJed Brown! 582d8606c27SBarry Smith PetscCallA(SNESSetJacobian(snes, J, J, FormJacobian, 0, ierr)) 583c4762a1bSJed Brown end if 584c4762a1bSJed Brown 585c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 586c4762a1bSJed Brown! Customize nonlinear solver; set runtime options 587c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 588c4762a1bSJed Brown 589c4762a1bSJed Brown! Set runtime options (e.g., -snes_monitor -snes_rtol <rtol> -ksp_type <type>) 590c4762a1bSJed Brown 591d8606c27SBarry Smith PetscCallA(SNESSetFromOptions(snes, ierr)) 592c4762a1bSJed Brown 593c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 594c4762a1bSJed Brown! Evaluate initial guess; then solve nonlinear system. 595c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 596c4762a1bSJed Brown 597c4762a1bSJed Brown! Note: The user should initialize the vector, x, with the initial guess 598c4762a1bSJed Brown! for the nonlinear solver prior to calling SNESSolve(). In particular, 599c4762a1bSJed Brown! to employ an initial guess of zero, the user should explicitly set 600c4762a1bSJed Brown! this vector to zero by calling VecSet(). 601c4762a1bSJed Brown 602d8606c27SBarry Smith PetscCallA(FormInitialGuess(x, ierr)) 603d8606c27SBarry Smith PetscCallA(SNESSolve(snes, PETSC_NULL_VEC, x, ierr)) 604d8606c27SBarry Smith PetscCallA(SNESGetIterationNumber(snes, its, ierr)) 60524fb275aSStefano Zampini write (outputString, *) its 60624fb275aSStefano Zampini PetscCallA(PetscPrintf(PETSC_COMM_WORLD, 'Number of SNES iterations = '//trim(outputString)//'\n', ierr)) 607c4762a1bSJed Brown 608c4762a1bSJed Brown! PetscDraw contour plot of solution 609c4762a1bSJed Brown 610ce78bad3SBarry Smith xl = 300 611ce78bad3SBarry Smith yl = 0 612ce78bad3SBarry Smith width = 300 613ce78bad3SBarry Smith height = 300 614ce78bad3SBarry Smith PetscCallA(PetscDrawCreate(PETSC_COMM_WORLD, PETSC_NULL_CHARACTER, 'Solution', xl, yl, width, height, draw, ierr)) 615d8606c27SBarry Smith PetscCallA(PetscDrawSetFromOptions(draw, ierr)) 616c4762a1bSJed Brown 617ce78bad3SBarry Smith PetscCallA(VecGetArrayRead(x, lx_v, ierr)) 618ce78bad3SBarry Smith imx = int(mx, kind=kind(imx)) 619ce78bad3SBarry Smith imy = int(my, kind=kind(imy)) 620ce78bad3SBarry Smith PetscCallA(PetscDrawTensorContour(draw, imx, imy, PETSC_NULL_REAL_ARRAY, PETSC_NULL_REAL_ARRAY, lx_v, ierr)) 621ce78bad3SBarry Smith PetscCallA(VecRestoreArrayRead(x, lx_v, ierr)) 622c4762a1bSJed Brown 623c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 624c4762a1bSJed Brown! Free work space. All PETSc objects should be destroyed when they 625c4762a1bSJed Brown! are no longer needed. 626c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 627c4762a1bSJed Brown 628d8606c27SBarry Smith if (.not. matrix_free) PetscCallA(MatDestroy(J, ierr)) 629d8606c27SBarry Smith if (fd_coloring) PetscCallA(MatFDColoringDestroy(fdcoloring, ierr)) 630c4762a1bSJed Brown 631d8606c27SBarry Smith PetscCallA(VecDestroy(x, ierr)) 632d8606c27SBarry Smith PetscCallA(VecDestroy(r, ierr)) 633d8606c27SBarry Smith PetscCallA(SNESDestroy(snes, ierr)) 634d8606c27SBarry Smith PetscCallA(PetscDrawDestroy(draw, ierr)) 635d8606c27SBarry Smith PetscCallA(PetscFinalize(ierr)) 636c4762a1bSJed Brownend 637c4762a1bSJed Brown! 638c4762a1bSJed Brown!/*TEST 639c4762a1bSJed Brown! 640c4762a1bSJed Brown! build: 641ce78bad3SBarry Smith! requires: !single !complex 642c4762a1bSJed Brown! 643c4762a1bSJed Brown! test: 644c4762a1bSJed Brown! args: -snes_monitor_short -nox -snes_type newtontr -ksp_gmres_cgs_refinement_type refine_always 645c4762a1bSJed Brown! 646c4762a1bSJed Brown! test: 647c4762a1bSJed Brown! suffix: 2 648c4762a1bSJed Brown! args: -snes_monitor_short -nox -snes_fd -ksp_gmres_cgs_refinement_type refine_always 649c4762a1bSJed Brown! 650c4762a1bSJed Brown! test: 651c4762a1bSJed Brown! suffix: 3 652c4762a1bSJed Brown! args: -snes_monitor_short -nox -snes_fd_coloring -mat_coloring_type sl -ksp_gmres_cgs_refinement_type refine_always 653c4762a1bSJed Brown! filter: sort -b 654c4762a1bSJed Brown! filter_output: sort -b 655c4762a1bSJed Brown! 656c4762a1bSJed Brown! test: 657c4762a1bSJed Brown! suffix: 4 658c4762a1bSJed Brown! args: -pc -par 6.807 -nox 659c4762a1bSJed Brown! 660c4762a1bSJed Brown!TEST*/ 661