1d8606c27SBarry Smith! 2d8606c27SBarry Smith! Solves the time dependent Bratu problem using pseudo-timestepping 3d8606c27SBarry Smith! 4d8606c27SBarry Smith! This code demonstrates how one may solve a nonlinear problem 5d8606c27SBarry Smith! with pseudo-timestepping. In this simple example, the pseudo-timestep 6d8606c27SBarry Smith! is the same for all grid points, i.e., this is equivalent to using 7d8606c27SBarry Smith! the backward Euler method with a variable timestep. 8d8606c27SBarry Smith! 9d8606c27SBarry Smith! Note: This example does not require pseudo-timestepping since it 10d8606c27SBarry Smith! is an easy nonlinear problem, but it is included to demonstrate how 11d8606c27SBarry Smith! the pseudo-timestepping may be done. 12d8606c27SBarry Smith! 13d8606c27SBarry Smith! See snes/tutorials/ex4.c[ex4f.F] and 14d8606c27SBarry Smith! snes/tutorials/ex5.c[ex5f.F] where the problem is described 15d8606c27SBarry Smith! and solved using the method of Newton alone. 16d8606c27SBarry Smith! 17d8606c27SBarry Smith! 18d8606c27SBarry Smith!23456789012345678901234567890123456789012345678901234567890123456789012 19d8606c27SBarry Smith program main 20d8606c27SBarry Smith#include <petsc/finclude/petscts.h> 21d8606c27SBarry Smith use petscts 22d8606c27SBarry Smith implicit none 23d8606c27SBarry Smith 24d8606c27SBarry Smith! 25d8606c27SBarry Smith! Create an application context to contain data needed by the 26d8606c27SBarry Smith! application-provided call-back routines, FormJacobian() and 27d8606c27SBarry Smith! FormFunction(). We use a double precision array with three 28d8606c27SBarry Smith! entries indexed by param, lmx, lmy. 29d8606c27SBarry Smith! 30d8606c27SBarry Smith PetscReal user(3) 31d8606c27SBarry Smith PetscInt param,lmx,lmy,i5 32d8606c27SBarry Smith parameter (param = 1,lmx = 2,lmy = 3) 33d8606c27SBarry Smith! 34d8606c27SBarry Smith! User-defined routines 35d8606c27SBarry Smith! 36d8606c27SBarry Smith external FormJacobian,FormFunction 37d8606c27SBarry Smith! 38d8606c27SBarry Smith! Data for problem 39d8606c27SBarry Smith! 40d8606c27SBarry Smith TS ts 41d8606c27SBarry Smith Vec x,r 42d8606c27SBarry Smith Mat J 43d8606c27SBarry Smith PetscInt its,N,i1000,itmp 44d8606c27SBarry Smith PetscBool flg 45d8606c27SBarry Smith PetscErrorCode ierr 46d8606c27SBarry Smith PetscReal param_max,param_min,dt 47d8606c27SBarry Smith PetscReal tmax 48d8606c27SBarry Smith PetscReal ftime 49d8606c27SBarry Smith TSConvergedReason reason 50d8606c27SBarry Smith 51d8606c27SBarry Smith i5 = 5 52d8606c27SBarry Smith param_max = 6.81 53d8606c27SBarry Smith param_min = 0 54d8606c27SBarry Smith 55d8606c27SBarry Smith PetscCallA(PetscInitialize(ierr)) 56d8606c27SBarry Smith user(lmx) = 4 57d8606c27SBarry Smith user(lmy) = 4 58d8606c27SBarry Smith user(param) = 6.0 59d8606c27SBarry Smith 60d8606c27SBarry Smith! 61d8606c27SBarry Smith! Allow user to set the grid dimensions and nonlinearity parameter at run-time 62d8606c27SBarry Smith! 63d8606c27SBarry Smith PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-mx',user(lmx),flg,ierr)) 64d8606c27SBarry Smith itmp = 4 65d8606c27SBarry Smith PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-my',itmp,flg,ierr)) 66d8606c27SBarry Smith user(lmy) = itmp 67d8606c27SBarry Smith PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-param',user(param),flg,ierr)) 68d8606c27SBarry Smith if (user(param) .ge. param_max .or. user(param) .le. param_min) then 69d8606c27SBarry Smith print*,'Parameter is out of range' 70d8606c27SBarry Smith endif 71d8606c27SBarry Smith if (user(lmx) .gt. user(lmy)) then 72d8606c27SBarry Smith dt = .5/user(lmx) 73d8606c27SBarry Smith else 74d8606c27SBarry Smith dt = .5/user(lmy) 75d8606c27SBarry Smith endif 76d8606c27SBarry Smith PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-dt',dt,flg,ierr)) 77d8606c27SBarry Smith N = int(user(lmx)*user(lmy)) 78d8606c27SBarry Smith 79d8606c27SBarry Smith! 80d8606c27SBarry Smith! Create vectors to hold the solution and function value 81d8606c27SBarry Smith! 82d8606c27SBarry Smith PetscCallA(VecCreateSeq(PETSC_COMM_SELF,N,x,ierr)) 83d8606c27SBarry Smith PetscCallA(VecDuplicate(x,r,ierr)) 84d8606c27SBarry Smith 85d8606c27SBarry Smith! 86d8606c27SBarry Smith! Create matrix to hold Jacobian. Preallocate 5 nonzeros per row 87d8606c27SBarry Smith! in the sparse matrix. Note that this is not the optimal strategy see 88d8606c27SBarry Smith! the Performance chapter of the users manual for information on 89d8606c27SBarry Smith! preallocating memory in sparse matrices. 90d8606c27SBarry Smith! 91d8606c27SBarry Smith i5 = 5 92d8606c27SBarry Smith PetscCallA(MatCreateSeqAIJ(PETSC_COMM_SELF,N,N,i5,PETSC_NULL_INTEGER,J,ierr)) 93d8606c27SBarry Smith 94d8606c27SBarry Smith! 95d8606c27SBarry Smith! Create timestepper context 96d8606c27SBarry Smith! 97d8606c27SBarry Smith 98d8606c27SBarry Smith PetscCallA(TSCreate(PETSC_COMM_WORLD,ts,ierr)) 99d8606c27SBarry Smith PetscCallA(TSSetProblemType(ts,TS_NONLINEAR,ierr)) 100d8606c27SBarry Smith 101d8606c27SBarry Smith! 102d8606c27SBarry Smith! Tell the timestepper context where to compute solutions 103d8606c27SBarry Smith! 104d8606c27SBarry Smith 105d8606c27SBarry Smith PetscCallA(TSSetSolution(ts,x,ierr)) 106d8606c27SBarry Smith 107d8606c27SBarry Smith! 108d8606c27SBarry Smith! Provide the call-back for the nonlinear function we are 109d8606c27SBarry Smith! evaluating. Thus whenever the timestepping routines need the 110d8606c27SBarry Smith! function they will call this routine. Note the final argument 111d8606c27SBarry Smith! is the application context used by the call-back functions. 112d8606c27SBarry Smith! 113d8606c27SBarry Smith 114d8606c27SBarry Smith PetscCallA(TSSetRHSFunction(ts,PETSC_NULL_VEC,FormFunction,user,ierr)) 115d8606c27SBarry Smith 116d8606c27SBarry Smith! 117d8606c27SBarry Smith! Set the Jacobian matrix and the function used to compute 118d8606c27SBarry Smith! Jacobians. 119d8606c27SBarry Smith! 120d8606c27SBarry Smith 121d8606c27SBarry Smith PetscCallA(TSSetRHSJacobian(ts,J,J,FormJacobian,user,ierr)) 122d8606c27SBarry Smith 123d8606c27SBarry Smith! 124d8606c27SBarry Smith! For the initial guess for the problem 125d8606c27SBarry Smith! 126d8606c27SBarry Smith 127d8606c27SBarry Smith PetscCallA(FormInitialGuess(x,user,ierr)) 128d8606c27SBarry Smith 129d8606c27SBarry Smith! 130d8606c27SBarry Smith! This indicates that we are using pseudo timestepping to 131d8606c27SBarry Smith! find a steady state solution to the nonlinear problem. 132d8606c27SBarry Smith! 133d8606c27SBarry Smith 134d8606c27SBarry Smith PetscCallA(TSSetType(ts,TSPSEUDO,ierr)) 135d8606c27SBarry Smith 136d8606c27SBarry Smith! 137d8606c27SBarry Smith! Set the initial time to start at (this is arbitrary for 138d8606c27SBarry Smith! steady state problems and the initial timestep given above 139d8606c27SBarry Smith! 140d8606c27SBarry Smith 141d8606c27SBarry Smith PetscCallA(TSSetTimeStep(ts,dt,ierr)) 142d8606c27SBarry Smith 143d8606c27SBarry Smith! 144d8606c27SBarry Smith! Set a large number of timesteps and final duration time 145d8606c27SBarry Smith! to insure convergence to steady state. 146d8606c27SBarry Smith! 147d8606c27SBarry Smith i1000 = 1000 148d8606c27SBarry Smith tmax = 1.e12 149d8606c27SBarry Smith PetscCallA(TSSetMaxSteps(ts,i1000,ierr)) 150d8606c27SBarry Smith PetscCallA(TSSetMaxTime(ts,tmax,ierr)) 151d8606c27SBarry Smith PetscCallA(TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER,ierr)) 152d8606c27SBarry Smith 153d8606c27SBarry Smith! 154d8606c27SBarry Smith! Set any additional options from the options database. This 155d8606c27SBarry Smith! includes all options for the nonlinear and linear solvers used 156d8606c27SBarry Smith! internally the timestepping routines. 157d8606c27SBarry Smith! 158d8606c27SBarry Smith 159d8606c27SBarry Smith PetscCallA(TSSetFromOptions(ts,ierr)) 160d8606c27SBarry Smith 161d8606c27SBarry Smith PetscCallA(TSSetUp(ts,ierr)) 162d8606c27SBarry Smith 163d8606c27SBarry Smith! 164d8606c27SBarry Smith! Perform the solve. This is where the timestepping takes place. 165d8606c27SBarry Smith! 166d8606c27SBarry Smith PetscCallA(TSSolve(ts,x,ierr)) 167d8606c27SBarry Smith PetscCallA(TSGetSolveTime(ts,ftime,ierr)) 168d8606c27SBarry Smith PetscCallA(TSGetStepNumber(ts,its,ierr)) 169d8606c27SBarry Smith PetscCallA(TSGetConvergedReason(ts,reason,ierr)) 170d8606c27SBarry Smith 171d8606c27SBarry Smith write(6,100) its,ftime,reason 172d8606c27SBarry Smith 100 format('Number of pseudo time-steps ',i5,' final time ',1pe9.2,' reason ',i3) 173d8606c27SBarry Smith 174d8606c27SBarry Smith! 175d8606c27SBarry Smith! Free the data structures constructed above 176d8606c27SBarry Smith! 177d8606c27SBarry Smith 178d8606c27SBarry Smith PetscCallA(VecDestroy(x,ierr)) 179d8606c27SBarry Smith PetscCallA(VecDestroy(r,ierr)) 180d8606c27SBarry Smith PetscCallA(MatDestroy(J,ierr)) 181d8606c27SBarry Smith PetscCallA(TSDestroy(ts,ierr)) 182d8606c27SBarry Smith PetscCallA(PetscFinalize(ierr)) 183d8606c27SBarry Smith end 184d8606c27SBarry Smith 185d8606c27SBarry Smith! 186d8606c27SBarry Smith! -------------------- Form initial approximation ----------------- 187d8606c27SBarry Smith! 188d8606c27SBarry Smith subroutine FormInitialGuess(X,user,ierr) 189d8606c27SBarry Smith use petscts 190d8606c27SBarry Smith implicit none 191d8606c27SBarry Smith 192d8606c27SBarry Smith Vec X 193d8606c27SBarry Smith PetscReal user(3) 194d8606c27SBarry Smith PetscInt i,j,row,mx,my 195d8606c27SBarry Smith PetscErrorCode ierr 196d8606c27SBarry Smith PetscReal one,lambda 197d8606c27SBarry Smith PetscReal temp1,temp,hx,hy 198*42ce371bSBarry Smith PetscScalar,pointer :: xx(:) 199d8606c27SBarry Smith PetscInt param,lmx,lmy 200d8606c27SBarry Smith parameter (param = 1,lmx = 2,lmy = 3) 201d8606c27SBarry Smith 202d8606c27SBarry Smith one = 1.0 203d8606c27SBarry Smith 204d8606c27SBarry Smith mx = int(user(lmx)) 205d8606c27SBarry Smith my = int(user(lmy)) 206d8606c27SBarry Smith lambda = user(param) 207d8606c27SBarry Smith 208d8606c27SBarry Smith hy = one / (my-1) 209d8606c27SBarry Smith hx = one / (mx-1) 210d8606c27SBarry Smith 211*42ce371bSBarry Smith PetscCall(VecGetArrayF90(X,xx,ierr)) 212d8606c27SBarry Smith temp1 = lambda/(lambda + one) 213d8606c27SBarry Smith do 10, j=1,my 214d8606c27SBarry Smith temp = min(j-1,my-j)*hy 215d8606c27SBarry Smith do 20 i=1,mx 216d8606c27SBarry Smith row = i + (j-1)*mx 217d8606c27SBarry Smith if (i .eq. 1 .or. j .eq. 1 .or. i .eq. mx .or. j .eq. my) then 218*42ce371bSBarry Smith xx(row) = 0.0 219d8606c27SBarry Smith else 220*42ce371bSBarry Smith xx(row) = temp1*sqrt(min(min(i-1,mx-i)*hx,temp)) 221d8606c27SBarry Smith endif 222d8606c27SBarry Smith 20 continue 223d8606c27SBarry Smith 10 continue 224*42ce371bSBarry Smith PetscCall(VecRestoreArrayF90(X,xx,ierr)) 225d8606c27SBarry Smith return 226d8606c27SBarry Smith end 227d8606c27SBarry Smith! 228d8606c27SBarry Smith! -------------------- Evaluate Function F(x) --------------------- 229d8606c27SBarry Smith! 230d8606c27SBarry Smith subroutine FormFunction(ts,t,X,F,user,ierr) 231d8606c27SBarry Smith use petscts 232d8606c27SBarry Smith implicit none 233d8606c27SBarry Smith 234d8606c27SBarry Smith TS ts 235d8606c27SBarry Smith PetscReal t 236d8606c27SBarry Smith Vec X,F 237d8606c27SBarry Smith PetscReal user(3) 238d8606c27SBarry Smith PetscErrorCode ierr 239d8606c27SBarry Smith PetscInt i,j,row,mx,my 240d8606c27SBarry Smith PetscReal two,lambda 241d8606c27SBarry Smith PetscReal hx,hy,hxdhy,hydhx 242d8606c27SBarry Smith PetscScalar ut,ub,ul,ur,u 243d8606c27SBarry Smith PetscScalar uxx,uyy,sc 244*42ce371bSBarry Smith PetscScalar,pointer :: xx(:), ff(:) 245d8606c27SBarry Smith PetscInt param,lmx,lmy 246d8606c27SBarry Smith parameter (param = 1,lmx = 2,lmy = 3) 247d8606c27SBarry Smith 248d8606c27SBarry Smith two = 2.0 249d8606c27SBarry Smith 250d8606c27SBarry Smith mx = int(user(lmx)) 251d8606c27SBarry Smith my = int(user(lmy)) 252d8606c27SBarry Smith lambda = user(param) 253d8606c27SBarry Smith 254d8606c27SBarry Smith hx = 1.0 / real(mx-1) 255d8606c27SBarry Smith hy = 1.0 / real(my-1) 256d8606c27SBarry Smith sc = hx*hy 257d8606c27SBarry Smith hxdhy = hx/hy 258d8606c27SBarry Smith hydhx = hy/hx 259d8606c27SBarry Smith 260*42ce371bSBarry Smith PetscCall(VecGetArrayReadF90(X,xx,ierr)) 261*42ce371bSBarry Smith PetscCall(VecGetArrayF90(F,ff,ierr)) 262d8606c27SBarry Smith do 10 j=1,my 263d8606c27SBarry Smith do 20 i=1,mx 264d8606c27SBarry Smith row = i + (j-1)*mx 265d8606c27SBarry Smith if (i .eq. 1 .or. j .eq. 1 .or. i .eq. mx .or. j .eq. my) then 266*42ce371bSBarry Smith ff(row) = xx(row) 267d8606c27SBarry Smith else 268*42ce371bSBarry Smith u = xx(row) 269*42ce371bSBarry Smith ub = xx(row - mx) 270*42ce371bSBarry Smith ul = xx(row - 1) 271*42ce371bSBarry Smith ut = xx(row + mx) 272*42ce371bSBarry Smith ur = xx(row + 1) 273d8606c27SBarry Smith uxx = (-ur + two*u - ul)*hydhx 274d8606c27SBarry Smith uyy = (-ut + two*u - ub)*hxdhy 275*42ce371bSBarry Smith ff(row) = -uxx - uyy + sc*lambda*exp(u) 276d8606c27SBarry Smith endif 277d8606c27SBarry Smith 20 continue 278d8606c27SBarry Smith 10 continue 279d8606c27SBarry Smith 280*42ce371bSBarry Smith PetscCall(VecRestoreArrayReadF90(X,xx,ierr)) 281*42ce371bSBarry Smith PetscCall(VecRestoreArrayF90(F,ff,ierr)) 282d8606c27SBarry Smith return 283d8606c27SBarry Smith end 284d8606c27SBarry Smith! 285d8606c27SBarry Smith! -------------------- Evaluate Jacobian of F(x) -------------------- 286d8606c27SBarry Smith! 287d8606c27SBarry Smith subroutine FormJacobian(ts,ctime,X,JJ,B,user,ierr) 288d8606c27SBarry Smith use petscts 289d8606c27SBarry Smith implicit none 290d8606c27SBarry Smith 291d8606c27SBarry Smith TS ts 292d8606c27SBarry Smith Vec X 293d8606c27SBarry Smith Mat JJ,B 294d8606c27SBarry Smith PetscReal user(3),ctime 295d8606c27SBarry Smith PetscErrorCode ierr 296d8606c27SBarry Smith Mat jac 297d8606c27SBarry Smith PetscInt i,j,row(1),mx,my 298d8606c27SBarry Smith PetscInt col(5),i1,i5 299d8606c27SBarry Smith PetscScalar two,one,lambda 300*42ce371bSBarry Smith PetscScalar v(5),sc 301*42ce371bSBarry Smith PetscScalar,pointer :: xx(:) 302d8606c27SBarry Smith PetscReal hx,hy,hxdhy,hydhx 303d8606c27SBarry Smith 304d8606c27SBarry Smith PetscInt param,lmx,lmy 305d8606c27SBarry Smith parameter (param = 1,lmx = 2,lmy = 3) 306d8606c27SBarry Smith 307d8606c27SBarry Smith i1 = 1 308d8606c27SBarry Smith i5 = 5 309d8606c27SBarry Smith jac = B 310d8606c27SBarry Smith two = 2.0 311d8606c27SBarry Smith one = 1.0 312d8606c27SBarry Smith 313d8606c27SBarry Smith mx = int(user(lmx)) 314d8606c27SBarry Smith my = int(user(lmy)) 315d8606c27SBarry Smith lambda = user(param) 316d8606c27SBarry Smith 317d8606c27SBarry Smith hx = 1.0 / real(mx-1) 318d8606c27SBarry Smith hy = 1.0 / real(my-1) 319d8606c27SBarry Smith sc = hx*hy 320d8606c27SBarry Smith hxdhy = hx/hy 321d8606c27SBarry Smith hydhx = hy/hx 322d8606c27SBarry Smith 323*42ce371bSBarry Smith PetscCall(VecGetArrayReadF90(X,xx,ierr)) 324d8606c27SBarry Smith do 10 j=1,my 325d8606c27SBarry Smith do 20 i=1,mx 326d8606c27SBarry Smith! 327d8606c27SBarry Smith! When inserting into PETSc matrices, indices start at 0 328d8606c27SBarry Smith! 329d8606c27SBarry Smith row(1) = i - 1 + (j-1)*mx 330d8606c27SBarry Smith if (i .eq. 1 .or. j .eq. 1 .or. i .eq. mx .or. j .eq. my) then 331d8606c27SBarry Smith PetscCall(MatSetValues(jac,i1,row,i1,row,one,INSERT_VALUES,ierr)) 332d8606c27SBarry Smith else 333d8606c27SBarry Smith v(1) = hxdhy 334d8606c27SBarry Smith col(1) = row(1) - mx 335d8606c27SBarry Smith v(2) = hydhx 336d8606c27SBarry Smith col(2) = row(1) - 1 337*42ce371bSBarry Smith v(3) = -two*(hydhx+hxdhy)+sc*lambda*exp(xx(row(1))) 338d8606c27SBarry Smith col(3) = row(1) 339d8606c27SBarry Smith v(4) = hydhx 340d8606c27SBarry Smith col(4) = row(1) + 1 341d8606c27SBarry Smith v(5) = hxdhy 342d8606c27SBarry Smith col(5) = row(1) + mx 343d8606c27SBarry Smith PetscCall(MatSetValues(jac,i1,row,i5,col,v,INSERT_VALUES,ierr)) 344d8606c27SBarry Smith endif 345d8606c27SBarry Smith 20 continue 346d8606c27SBarry Smith 10 continue 347d8606c27SBarry Smith PetscCall(MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY,ierr)) 348d8606c27SBarry Smith PetscCall(MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY,ierr)) 349*42ce371bSBarry Smith PetscCall(VecRestoreArrayF90(X,xx,ierr)) 350d8606c27SBarry Smith return 351d8606c27SBarry Smith end 352d8606c27SBarry Smith 353d8606c27SBarry Smith!/*TEST 354d8606c27SBarry Smith! 355d8606c27SBarry Smith! test: 356d8606c27SBarry Smith! TODO: broken 357d8606c27SBarry Smith! args: -ksp_gmres_cgs_refinement_type refine_always -snes_type newtonls -ts_monitor_pseudo -ts_max_snes_failures 3 -ts_pseudo_frtol 1.e-5 -snes_stol 1e-5 358d8606c27SBarry Smith! 359d8606c27SBarry Smith!TEST*/ 360d8606c27SBarry Smith 361