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 Smithprogram 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)) 68*4820e4eaSBarry Smith if (user(param) >= param_max .or. user(param) <= param_min) then 69d8606c27SBarry Smith print *, 'Parameter is out of range' 70d8606c27SBarry Smith end if 71*4820e4eaSBarry Smith if (user(lmx) > user(lmy)) then 72d8606c27SBarry Smith dt = .5/user(lmx) 73d8606c27SBarry Smith else 74d8606c27SBarry Smith dt = .5/user(lmy) 75d8606c27SBarry Smith end if 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 925d83a8b1SBarry Smith PetscCallA(MatCreateSeqAIJ(PETSC_COMM_SELF, N, N, i5, PETSC_NULL_INTEGER_ARRAY, 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 Smith100 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 Smithend 184d8606c27SBarry Smith 185d8606c27SBarry Smith! 186d8606c27SBarry Smith! -------------------- Form initial approximation ----------------- 187d8606c27SBarry Smith! 188d8606c27SBarry Smithsubroutine 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 19842ce371bSBarry 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 211ce78bad3SBarry Smith PetscCall(VecGetArray(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 217*4820e4eaSBarry Smith if (i == 1 .or. j == 1 .or. i == mx .or. j == my) then 21842ce371bSBarry Smith xx(row) = 0.0 219d8606c27SBarry Smith else 22042ce371bSBarry Smith xx(row) = temp1*sqrt(min(min(i - 1, mx - i)*hx, temp)) 221d8606c27SBarry Smith end if 222d8606c27SBarry Smith20 continue 223d8606c27SBarry Smith10 continue 224ce78bad3SBarry Smith PetscCall(VecRestoreArray(X, xx, ierr)) 225d8606c27SBarry Smith end 226d8606c27SBarry Smith! 227d8606c27SBarry Smith! -------------------- Evaluate Function F(x) --------------------- 228d8606c27SBarry Smith! 229d8606c27SBarry Smith subroutine FormFunction(ts, t, X, F, user, ierr) 230d8606c27SBarry Smith use petscts 231d8606c27SBarry Smith implicit none 232d8606c27SBarry Smith 233d8606c27SBarry Smith TS ts 234d8606c27SBarry Smith PetscReal t 235d8606c27SBarry Smith Vec X, F 236d8606c27SBarry Smith PetscReal user(3) 237d8606c27SBarry Smith PetscErrorCode ierr 238d8606c27SBarry Smith PetscInt i, j, row, mx, my 239d8606c27SBarry Smith PetscReal two, lambda 240d8606c27SBarry Smith PetscReal hx, hy, hxdhy, hydhx 241d8606c27SBarry Smith PetscScalar ut, ub, ul, ur, u 242d8606c27SBarry Smith PetscScalar uxx, uyy, sc 24342ce371bSBarry Smith PetscScalar, pointer :: xx(:), ff(:) 244d8606c27SBarry Smith PetscInt param, lmx, lmy 245d8606c27SBarry Smith parameter(param=1, lmx=2, lmy=3) 246d8606c27SBarry Smith 247d8606c27SBarry Smith two = 2.0 248d8606c27SBarry Smith 249d8606c27SBarry Smith mx = int(user(lmx)) 250d8606c27SBarry Smith my = int(user(lmy)) 251d8606c27SBarry Smith lambda = user(param) 252d8606c27SBarry Smith 253d8606c27SBarry Smith hx = 1.0/real(mx - 1) 254d8606c27SBarry Smith hy = 1.0/real(my - 1) 255d8606c27SBarry Smith sc = hx*hy 256d8606c27SBarry Smith hxdhy = hx/hy 257d8606c27SBarry Smith hydhx = hy/hx 258d8606c27SBarry Smith 259ce78bad3SBarry Smith PetscCall(VecGetArrayRead(X, xx, ierr)) 260ce78bad3SBarry Smith PetscCall(VecGetArray(F, ff, ierr)) 261d8606c27SBarry Smith do 10 j = 1, my 262d8606c27SBarry Smith do 20 i = 1, mx 263d8606c27SBarry Smith row = i + (j - 1)*mx 264*4820e4eaSBarry Smith if (i == 1 .or. j == 1 .or. i == mx .or. j == my) then 26542ce371bSBarry Smith ff(row) = xx(row) 266d8606c27SBarry Smith else 26742ce371bSBarry Smith u = xx(row) 26842ce371bSBarry Smith ub = xx(row - mx) 26942ce371bSBarry Smith ul = xx(row - 1) 27042ce371bSBarry Smith ut = xx(row + mx) 27142ce371bSBarry Smith ur = xx(row + 1) 272d8606c27SBarry Smith uxx = (-ur + two*u - ul)*hydhx 273d8606c27SBarry Smith uyy = (-ut + two*u - ub)*hxdhy 27442ce371bSBarry Smith ff(row) = -uxx - uyy + sc*lambda*exp(u) 275d8606c27SBarry Smith end if 276d8606c27SBarry Smith20 continue 277d8606c27SBarry Smith10 continue 278d8606c27SBarry Smith 279ce78bad3SBarry Smith PetscCall(VecRestoreArrayRead(X, xx, ierr)) 280ce78bad3SBarry Smith PetscCall(VecRestoreArray(F, ff, ierr)) 281d8606c27SBarry Smith end 282d8606c27SBarry Smith! 283d8606c27SBarry Smith! -------------------- Evaluate Jacobian of F(x) -------------------- 284d8606c27SBarry Smith! 285d8606c27SBarry Smith subroutine FormJacobian(ts, ctime, X, JJ, B, user, ierr) 286d8606c27SBarry Smith use petscts 287d8606c27SBarry Smith implicit none 288d8606c27SBarry Smith 289d8606c27SBarry Smith TS ts 290d8606c27SBarry Smith Vec X 291d8606c27SBarry Smith Mat JJ, B 292d8606c27SBarry Smith PetscReal user(3), ctime 293d8606c27SBarry Smith PetscErrorCode ierr 294d8606c27SBarry Smith Mat jac 295d8606c27SBarry Smith PetscInt i, j, row(1), mx, my 296d8606c27SBarry Smith PetscInt col(5), i1, i5 297d8606c27SBarry Smith PetscScalar two, one, lambda 29842ce371bSBarry Smith PetscScalar v(5), sc 29942ce371bSBarry Smith PetscScalar, pointer :: xx(:) 300d8606c27SBarry Smith PetscReal hx, hy, hxdhy, hydhx 301d8606c27SBarry Smith 302d8606c27SBarry Smith PetscInt param, lmx, lmy 303d8606c27SBarry Smith parameter(param=1, lmx=2, lmy=3) 304d8606c27SBarry Smith 305d8606c27SBarry Smith i1 = 1 306d8606c27SBarry Smith i5 = 5 307d8606c27SBarry Smith jac = B 308d8606c27SBarry Smith two = 2.0 309d8606c27SBarry Smith one = 1.0 310d8606c27SBarry Smith 311d8606c27SBarry Smith mx = int(user(lmx)) 312d8606c27SBarry Smith my = int(user(lmy)) 313d8606c27SBarry Smith lambda = user(param) 314d8606c27SBarry Smith 315d8606c27SBarry Smith hx = 1.0/real(mx - 1) 316d8606c27SBarry Smith hy = 1.0/real(my - 1) 317d8606c27SBarry Smith sc = hx*hy 318d8606c27SBarry Smith hxdhy = hx/hy 319d8606c27SBarry Smith hydhx = hy/hx 320d8606c27SBarry Smith 321ce78bad3SBarry Smith PetscCall(VecGetArrayRead(X, xx, ierr)) 322d8606c27SBarry Smith do 10 j = 1, my 323d8606c27SBarry Smith do 20 i = 1, mx 324d8606c27SBarry Smith! 325d8606c27SBarry Smith! When inserting into PETSc matrices, indices start at 0 326d8606c27SBarry Smith! 327d8606c27SBarry Smith row(1) = i - 1 + (j - 1)*mx 328*4820e4eaSBarry Smith if (i == 1 .or. j == 1 .or. i == mx .or. j == my) then 3295d83a8b1SBarry Smith PetscCall(MatSetValues(jac, i1, [row], i1, [row], [one], INSERT_VALUES, ierr)) 330d8606c27SBarry Smith else 331d8606c27SBarry Smith v(1) = hxdhy 332d8606c27SBarry Smith col(1) = row(1) - mx 333d8606c27SBarry Smith v(2) = hydhx 334d8606c27SBarry Smith col(2) = row(1) - 1 33542ce371bSBarry Smith v(3) = -two*(hydhx + hxdhy) + sc*lambda*exp(xx(row(1))) 336d8606c27SBarry Smith col(3) = row(1) 337d8606c27SBarry Smith v(4) = hydhx 338d8606c27SBarry Smith col(4) = row(1) + 1 339d8606c27SBarry Smith v(5) = hxdhy 340d8606c27SBarry Smith col(5) = row(1) + mx 3415d83a8b1SBarry Smith PetscCall(MatSetValues(jac, i1, [row], i5, col, v, INSERT_VALUES, ierr)) 342d8606c27SBarry Smith end if 343d8606c27SBarry Smith20 continue 344d8606c27SBarry Smith10 continue 345d8606c27SBarry Smith PetscCall(MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY, ierr)) 346d8606c27SBarry Smith PetscCall(MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY, ierr)) 347ce78bad3SBarry Smith PetscCall(VecRestoreArray(X, xx, ierr)) 348d8606c27SBarry Smith end 349d8606c27SBarry Smith 350d8606c27SBarry Smith!/*TEST 351d8606c27SBarry Smith! 352d8606c27SBarry Smith! test: 353d8606c27SBarry Smith! TODO: broken 354d8606c27SBarry 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 355d8606c27SBarry Smith! 356d8606c27SBarry Smith!TEST*/ 357