xref: /petsc/src/ts/tutorials/ex1f.F90 (revision 42ce371b2bd7d45eb85bb2bb31075ac1967f9fc8)
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