xref: /petsc/src/ts/tutorials/ex22f.F90 (revision ceeae6b5899f2879f7a95602f98efecbe51ff614)
1d8606c27SBarry Smith! Time-dependent advection-reaction PDE in 1d. Demonstrates IMEX methods
2d8606c27SBarry Smith!
3d8606c27SBarry Smith!   u_t + a1*u_x = -k1*u + k2*v + s1
4d8606c27SBarry Smith!   v_t + a2*v_x = k1*u - k2*v + s2
5ccfd86f1SBarry Smith!   0 < x < 1
6d8606c27SBarry Smith!   a1 = 1, k1 = 10^6, s1 = 0,
7d8606c27SBarry Smith!   a2 = 0, k2 = 2*k1, s2 = 1
8d8606c27SBarry Smith!
9d8606c27SBarry Smith!   Initial conditions:
10d8606c27SBarry Smith!   u(x,0) = 1 + s2*x
11d8606c27SBarry Smith!   v(x,0) = k0/k1*u(x,0) + s1/k1
12d8606c27SBarry Smith!
13d8606c27SBarry Smith!   Upstream boundary conditions:
14d8606c27SBarry Smith!   u(0,t) = 1-sin(12*t)^4
15d8606c27SBarry Smith!
16d8606c27SBarry Smith
17d8606c27SBarry Smith#include <petsc/finclude/petscts.h>
18d8606c27SBarry Smith#include <petsc/finclude/petscdmda.h>
19c5e229c2SMartin Diehlprogram main
20d8606c27SBarry Smith  use petscts
21d8606c27SBarry Smith  implicit none
22d8606c27SBarry Smith
23d8606c27SBarry Smith!
24d8606c27SBarry Smith!  Create an application context to contain data needed by the
25d8606c27SBarry Smith!  application-provided call-back routines, FormJacobian() and
26d8606c27SBarry Smith!  FormFunction(). We use a double precision array with six
27d8606c27SBarry Smith!  entries, two for each problem parameter a, k, s.
28d8606c27SBarry Smith!
29d8606c27SBarry Smith  PetscReal user(6)
30d8606c27SBarry Smith  integer user_a, user_k, user_s
31d8606c27SBarry Smith  parameter(user_a=0, user_k=2, user_s=4)
32d8606c27SBarry Smith
33d8606c27SBarry Smith  TS ts
34d8606c27SBarry Smith  SNES snes
35d8606c27SBarry Smith  SNESLineSearch linesearch
36d8606c27SBarry Smith  Vec X
37d8606c27SBarry Smith  Mat J
38d8606c27SBarry Smith  PetscInt mx
39d8606c27SBarry Smith  PetscErrorCode ierr
40d8606c27SBarry Smith  DM da
41d8606c27SBarry Smith  PetscReal ftime, dt
42d8606c27SBarry Smith  PetscReal one, pone
43d8606c27SBarry Smith  PetscInt im11, i2
44d8606c27SBarry Smith  PetscBool flg
45d8606c27SBarry Smith
46d8606c27SBarry Smith  im11 = 11
47d8606c27SBarry Smith  i2 = 2
48d8606c27SBarry Smith  one = 1.0
49d8606c27SBarry Smith  pone = one/10
50d8606c27SBarry Smith
51d8606c27SBarry Smith  PetscCallA(PetscInitialize(ierr))
52d8606c27SBarry Smith
53d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
54d8606c27SBarry Smith!  Create distributed array (DMDA) to manage parallel grid and vectors
55d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
56d8606c27SBarry Smith  PetscCallA(DMDACreate1d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, im11, i2, i2, PETSC_NULL_INTEGER, da, ierr))
57d8606c27SBarry Smith  PetscCallA(DMSetFromOptions(da, ierr))
58d8606c27SBarry Smith  PetscCallA(DMSetUp(da, ierr))
59d8606c27SBarry Smith
60d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
61ccfd86f1SBarry Smith!    Extract global vectors from DMDA
62d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
63d8606c27SBarry Smith  PetscCallA(DMCreateGlobalVector(da, X, ierr))
64d8606c27SBarry Smith
65d8606c27SBarry Smith! Initialize user application context
66d8606c27SBarry Smith! Use zero-based indexing for command line parameters to match ex22.c
67d8606c27SBarry Smith  user(user_a + 1) = 1.0
68d8606c27SBarry Smith  PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-a0', user(user_a + 1), flg, ierr))
69d8606c27SBarry Smith  user(user_a + 2) = 0.0
70d8606c27SBarry Smith  PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-a1', user(user_a + 2), flg, ierr))
71d8606c27SBarry Smith  user(user_k + 1) = 1000000.0
72d8606c27SBarry Smith  PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-k0', user(user_k + 1), flg, ierr))
73d8606c27SBarry Smith  user(user_k + 2) = 2*user(user_k + 1)
74d8606c27SBarry Smith  PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-k1', user(user_k + 2), flg, ierr))
75d8606c27SBarry Smith  user(user_s + 1) = 0.0
76d8606c27SBarry Smith  PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-s0', user(user_s + 1), flg, ierr))
77d8606c27SBarry Smith  user(user_s + 2) = 1.0
78d8606c27SBarry Smith  PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-s1', user(user_s + 2), flg, ierr))
79d8606c27SBarry Smith
80d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
81d8606c27SBarry Smith!    Create timestepping solver context
82d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
83d8606c27SBarry Smith  PetscCallA(TSCreate(PETSC_COMM_WORLD, ts, ierr))
84d8606c27SBarry Smith  PetscCallA(TSSetDM(ts, da, ierr))
85d8606c27SBarry Smith  PetscCallA(TSSetType(ts, TSARKIMEX, ierr))
86d8606c27SBarry Smith  PetscCallA(TSSetRHSFunction(ts, PETSC_NULL_VEC, FormRHSFunction, user, ierr))
87d8606c27SBarry Smith  PetscCallA(TSSetIFunction(ts, PETSC_NULL_VEC, FormIFunction, user, ierr))
88d8606c27SBarry Smith  PetscCallA(DMSetMatType(da, MATAIJ, ierr))
89d8606c27SBarry Smith  PetscCallA(DMCreateMatrix(da, J, ierr))
90d8606c27SBarry Smith  PetscCallA(TSSetIJacobian(ts, J, J, FormIJacobian, user, ierr))
91d8606c27SBarry Smith
92d8606c27SBarry Smith  PetscCallA(TSGetSNES(ts, snes, ierr))
93d8606c27SBarry Smith  PetscCallA(SNESGetLineSearch(snes, linesearch, ierr))
94d8606c27SBarry Smith  PetscCallA(SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC, ierr))
95d8606c27SBarry Smith
96d8606c27SBarry Smith  ftime = 1.0
97d8606c27SBarry Smith  PetscCallA(TSSetMaxTime(ts, ftime, ierr))
98d8606c27SBarry Smith  PetscCallA(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_STEPOVER, ierr))
99d8606c27SBarry Smith
100d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
101d8606c27SBarry Smith!  Set initial conditions
102d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
103d8606c27SBarry Smith  PetscCallA(FormInitialSolution(ts, X, user, ierr))
104d8606c27SBarry Smith  PetscCallA(TSSetSolution(ts, X, ierr))
105d8606c27SBarry Smith  PetscCallA(VecGetSize(X, mx, ierr))
106d8606c27SBarry Smith!  Advective CFL, I don't know why it needs so much safety factor.
107ccfd86f1SBarry Smith  dt = pone*max(user(user_a + 1), user(user_a + 2))/mx
108d8606c27SBarry Smith  PetscCallA(TSSetTimeStep(ts, dt, ierr))
109d8606c27SBarry Smith
110d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
111d8606c27SBarry Smith!   Set runtime options
112d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
113d8606c27SBarry Smith  PetscCallA(TSSetFromOptions(ts, ierr))
114d8606c27SBarry Smith
115d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
116d8606c27SBarry Smith!  Solve nonlinear system
117d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
118d8606c27SBarry Smith  PetscCallA(TSSolve(ts, X, ierr))
119d8606c27SBarry Smith
120d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
121d8606c27SBarry Smith!  Free work space.
122d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
123d8606c27SBarry Smith  PetscCallA(MatDestroy(J, ierr))
124d8606c27SBarry Smith  PetscCallA(VecDestroy(X, ierr))
125d8606c27SBarry Smith  PetscCallA(TSDestroy(ts, ierr))
126d8606c27SBarry Smith  PetscCallA(DMDestroy(da, ierr))
127d8606c27SBarry Smith  PetscCallA(PetscFinalize(ierr))
128fe66ebccSMartin Diehlcontains
129d8606c27SBarry Smith
130d8606c27SBarry Smith! Small helper to extract the layout, result uses 1-based indexing.
131d8606c27SBarry Smith  subroutine GetLayout(da, mx, xs, xe, gxs, gxe, ierr)
132ce78bad3SBarry Smith    use petscdm
133d8606c27SBarry Smith    implicit none
134d8606c27SBarry Smith
135d8606c27SBarry Smith    DM da
136d8606c27SBarry Smith    PetscInt mx, xs, xe, gxs, gxe
137d8606c27SBarry Smith    PetscErrorCode ierr
138d8606c27SBarry Smith    PetscInt xm, gxm
1395d83a8b1SBarry Smith    PetscCall(DMDAGetInfo(da, PETSC_NULL_INTEGER, mx, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, PETSC_NULL_ENUM, PETSC_NULL_ENUM, PETSC_NULL_ENUM, PETSC_NULL_ENUM, ierr))
140d8606c27SBarry Smith    PetscCall(DMDAGetCorners(da, xs, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, xm, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, ierr))
141d8606c27SBarry Smith    PetscCall(DMDAGetGhostCorners(da, gxs, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, gxm, PETSC_NULL_INTEGER, PETSC_NULL_INTEGER, ierr))
142d8606c27SBarry Smith    xs = xs + 1
143d8606c27SBarry Smith    gxs = gxs + 1
144d8606c27SBarry Smith    xe = xs + xm - 1
145d8606c27SBarry Smith    gxe = gxs + gxm - 1
146d8606c27SBarry Smith  end subroutine
147d8606c27SBarry Smith
148d8606c27SBarry Smith  subroutine FormIFunctionLocal(mx, xs, xe, gxs, gxe, x, xdot, f, a, k, s, ierr)
149d8606c27SBarry Smith    implicit none
150d8606c27SBarry Smith    PetscInt mx, xs, xe, gxs, gxe
151d8606c27SBarry Smith    PetscScalar x(2, xs:xe)
152d8606c27SBarry Smith    PetscScalar xdot(2, xs:xe)
153d8606c27SBarry Smith    PetscScalar f(2, xs:xe)
154d8606c27SBarry Smith    PetscReal a(2), k(2), s(2)
155d8606c27SBarry Smith    PetscErrorCode ierr
156d8606c27SBarry Smith    PetscInt i
157*ceeae6b5SMartin Diehl    do i = xs, xe
158d8606c27SBarry Smith      f(1, i) = xdot(1, i) + k(1)*x(1, i) - k(2)*x(2, i) - s(1)
159d8606c27SBarry Smith      f(2, i) = xdot(2, i) - k(1)*x(1, i) + k(2)*x(2, i) - s(2)
160*ceeae6b5SMartin Diehl    end do
161d8606c27SBarry Smith  end subroutine
162d8606c27SBarry Smith
163d8606c27SBarry Smith  subroutine FormIFunction(ts, t, X, Xdot, F, user, ierr)
164d8606c27SBarry Smith    use petscts
165d8606c27SBarry Smith    implicit none
166d8606c27SBarry Smith
167d8606c27SBarry Smith    TS ts
168d8606c27SBarry Smith    PetscReal t
169d8606c27SBarry Smith    Vec X, Xdot, F
170d8606c27SBarry Smith    PetscReal user(6)
171d8606c27SBarry Smith    PetscErrorCode ierr
172d8606c27SBarry Smith    integer user_a, user_k, user_s
173d8606c27SBarry Smith    parameter(user_a=1, user_k=3, user_s=5)
174d8606c27SBarry Smith
175d8606c27SBarry Smith    DM da
176d8606c27SBarry Smith    PetscInt mx, xs, xe, gxs, gxe
17742ce371bSBarry Smith    PetscScalar, pointer :: xx(:), xxdot(:), ff(:)
178d8606c27SBarry Smith
179d8606c27SBarry Smith    PetscCall(TSGetDM(ts, da, ierr))
180d8606c27SBarry Smith    PetscCall(GetLayout(da, mx, xs, xe, gxs, gxe, ierr))
181d8606c27SBarry Smith
182d8606c27SBarry Smith! Get access to vector data
183ce78bad3SBarry Smith    PetscCall(VecGetArrayRead(X, xx, ierr))
184ce78bad3SBarry Smith    PetscCall(VecGetArrayRead(Xdot, xxdot, ierr))
185ce78bad3SBarry Smith    PetscCall(VecGetArray(F, ff, ierr))
186d8606c27SBarry Smith
18742ce371bSBarry Smith    PetscCall(FormIFunctionLocal(mx, xs, xe, gxs, gxe, xx, xxdot, ff, user(user_a), user(user_k), user(user_s), ierr))
188d8606c27SBarry Smith
189ce78bad3SBarry Smith    PetscCall(VecRestoreArrayRead(X, xx, ierr))
190ce78bad3SBarry Smith    PetscCall(VecRestoreArrayRead(Xdot, xxdot, ierr))
191ce78bad3SBarry Smith    PetscCall(VecRestoreArray(F, ff, ierr))
192d8606c27SBarry Smith  end subroutine
193d8606c27SBarry Smith
194d8606c27SBarry Smith  subroutine FormRHSFunctionLocal(mx, xs, xe, gxs, gxe, t, x, f, a, k, s, ierr)
195d8606c27SBarry Smith    implicit none
196d8606c27SBarry Smith    PetscInt mx, xs, xe, gxs, gxe
197d8606c27SBarry Smith    PetscReal t
198d8606c27SBarry Smith    PetscScalar x(2, gxs:gxe), f(2, xs:xe)
199d8606c27SBarry Smith    PetscReal a(2), k(2), s(2)
200d8606c27SBarry Smith    PetscErrorCode ierr
201d8606c27SBarry Smith    PetscInt i, j
202d8606c27SBarry Smith    PetscReal hx, u0t(2)
203d8606c27SBarry Smith    PetscReal one, two, three, four, six, twelve
204d8606c27SBarry Smith    PetscReal half, third, twothird, sixth
205d8606c27SBarry Smith    PetscReal twelfth
206d8606c27SBarry Smith
207d8606c27SBarry Smith    one = 1.0
208d8606c27SBarry Smith    two = 2.0
209d8606c27SBarry Smith    three = 3.0
210d8606c27SBarry Smith    four = 4.0
211d8606c27SBarry Smith    six = 6.0
212d8606c27SBarry Smith    twelve = 12.0
213d8606c27SBarry Smith    hx = one/mx
214d8606c27SBarry Smith!     The Fortran standard only allows positive base for power functions; Nag compiler fails on this
215d8606c27SBarry Smith    u0t(1) = one - abs(sin(twelve*t))**four
216d8606c27SBarry Smith    u0t(2) = 0.0
217d8606c27SBarry Smith    half = one/two
218d8606c27SBarry Smith    third = one/three
219d8606c27SBarry Smith    twothird = two/three
220d8606c27SBarry Smith    sixth = one/six
221d8606c27SBarry Smith    twelfth = one/twelve
222*ceeae6b5SMartin Diehl    do i = xs, xe
223*ceeae6b5SMartin Diehl      do j = 1, 2
2244820e4eaSBarry Smith        if (i == 1) then
225d8606c27SBarry Smith          f(j, i) = a(j)/hx*(third*u0t(j) + half*x(j, i) - x(j, i + 1)  &
226d8606c27SBarry Smith&              + sixth*x(j, i + 2))
2274820e4eaSBarry Smith        else if (i == 2) then
228d8606c27SBarry Smith          f(j, i) = a(j)/hx*(-twelfth*u0t(j) + twothird*x(j, i - 1)    &
229d8606c27SBarry Smith&              - twothird*x(j, i + 1) + twelfth*x(j, i + 2))
2304820e4eaSBarry Smith        else if (i == mx - 1) then
231d8606c27SBarry Smith          f(j, i) = a(j)/hx*(-sixth*x(j, i - 2) + x(j, i - 1)             &
232d8606c27SBarry Smith&         - half*x(j, i) - third*x(j, i + 1))
2334820e4eaSBarry Smith        else if (i == mx) then
234d8606c27SBarry Smith          f(j, i) = a(j)/hx*(-x(j, i) + x(j, i - 1))
235d8606c27SBarry Smith        else
236d8606c27SBarry Smith          f(j, i) = a(j)/hx*(-twelfth*x(j, i - 2)                      &
237d8606c27SBarry Smith&              + twothird*x(j, i - 1)                                 &
238d8606c27SBarry Smith&              - twothird*x(j, i + 1) + twelfth*x(j, i + 2))
239d8606c27SBarry Smith        end if
240*ceeae6b5SMartin Diehl      end do
241*ceeae6b5SMartin Diehl    end do
242d8606c27SBarry Smith  end subroutine
243d8606c27SBarry Smith
244d8606c27SBarry Smith  subroutine FormRHSFunction(ts, t, X, F, user, ierr)
245d8606c27SBarry Smith    use petscts
246d8606c27SBarry Smith    implicit none
247d8606c27SBarry Smith
248d8606c27SBarry Smith    TS ts
249d8606c27SBarry Smith    PetscReal t
250d8606c27SBarry Smith    Vec X, F
251d8606c27SBarry Smith    PetscReal user(6)
252d8606c27SBarry Smith    PetscErrorCode ierr
253d8606c27SBarry Smith    integer user_a, user_k, user_s
254d8606c27SBarry Smith    parameter(user_a=1, user_k=3, user_s=5)
255d8606c27SBarry Smith    DM da
256d8606c27SBarry Smith    Vec Xloc
257d8606c27SBarry Smith    PetscInt mx, xs, xe, gxs, gxe
25842ce371bSBarry Smith    PetscScalar, pointer :: xx(:), ff(:)
259d8606c27SBarry Smith
260d8606c27SBarry Smith    PetscCall(TSGetDM(ts, da, ierr))
261d8606c27SBarry Smith    PetscCall(GetLayout(da, mx, xs, xe, gxs, gxe, ierr))
262d8606c27SBarry Smith
263d8606c27SBarry Smith!     Scatter ghost points to local vector,using the 2-step process
264d8606c27SBarry Smith!        DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
265d8606c27SBarry Smith!     By placing code between these two statements, computations can be
266d8606c27SBarry Smith!     done while messages are in transition.
267d8606c27SBarry Smith    PetscCall(DMGetLocalVector(da, Xloc, ierr))
268d8606c27SBarry Smith    PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, Xloc, ierr))
269d8606c27SBarry Smith    PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, Xloc, ierr))
270d8606c27SBarry Smith
271d8606c27SBarry Smith! Get access to vector data
272ce78bad3SBarry Smith    PetscCall(VecGetArrayRead(Xloc, xx, ierr))
273ce78bad3SBarry Smith    PetscCall(VecGetArray(F, ff, ierr))
274d8606c27SBarry Smith
27542ce371bSBarry Smith    PetscCall(FormRHSFunctionLocal(mx, xs, xe, gxs, gxe, t, xx, ff, user(user_a), user(user_k), user(user_s), ierr))
276d8606c27SBarry Smith
277ce78bad3SBarry Smith    PetscCall(VecRestoreArrayRead(Xloc, xx, ierr))
278ce78bad3SBarry Smith    PetscCall(VecRestoreArray(F, ff, ierr))
279d8606c27SBarry Smith    PetscCall(DMRestoreLocalVector(da, Xloc, ierr))
280d8606c27SBarry Smith  end subroutine
281d8606c27SBarry Smith
282d8606c27SBarry Smith! ---------------------------------------------------------------------
283d8606c27SBarry Smith!
284d8606c27SBarry Smith!  IJacobian - Compute IJacobian = dF/dU + shift*dF/dUdot
285d8606c27SBarry Smith!
286d8606c27SBarry Smith  subroutine FormIJacobian(ts, t, X, Xdot, shift, J, Jpre, user, ierr)
287d8606c27SBarry Smith    use petscts
288d8606c27SBarry Smith    implicit none
289d8606c27SBarry Smith
290d8606c27SBarry Smith    TS ts
291d8606c27SBarry Smith    PetscReal t, shift
292d8606c27SBarry Smith    Vec X, Xdot
293d8606c27SBarry Smith    Mat J, Jpre
294d8606c27SBarry Smith    PetscReal user(6)
295d8606c27SBarry Smith    PetscErrorCode ierr
296d8606c27SBarry Smith    integer user_a, user_k, user_s
297d8606c27SBarry Smith    parameter(user_a=0, user_k=2, user_s=4)
298d8606c27SBarry Smith
299d8606c27SBarry Smith    DM da
300d8606c27SBarry Smith    PetscInt mx, xs, xe, gxs, gxe
301d8606c27SBarry Smith    PetscInt i, i1, row, col
302ccfd86f1SBarry Smith    PetscReal k1, k2
303d8606c27SBarry Smith    PetscScalar val(4)
304d8606c27SBarry Smith
305d8606c27SBarry Smith    PetscCall(TSGetDM(ts, da, ierr))
306d8606c27SBarry Smith    PetscCall(GetLayout(da, mx, xs, xe, gxs, gxe, ierr))
307d8606c27SBarry Smith
308d8606c27SBarry Smith    i1 = 1
309d8606c27SBarry Smith    k1 = user(user_k + 1)
310d8606c27SBarry Smith    k2 = user(user_k + 2)
311*ceeae6b5SMartin Diehl    do i = xs, xe
312d8606c27SBarry Smith      row = i - gxs
313d8606c27SBarry Smith      col = i - gxs
314d8606c27SBarry Smith      val(1) = shift + k1
315d8606c27SBarry Smith      val(2) = -k2
316d8606c27SBarry Smith      val(3) = -k1
317d8606c27SBarry Smith      val(4) = shift + k2
3185d83a8b1SBarry Smith      PetscCall(MatSetValuesBlockedLocal(Jpre, i1, [row], i1, [col], val, INSERT_VALUES, ierr))
319*ceeae6b5SMartin Diehl    end do
320d8606c27SBarry Smith    PetscCall(MatAssemblyBegin(Jpre, MAT_FINAL_ASSEMBLY, ierr))
321d8606c27SBarry Smith    PetscCall(MatAssemblyEnd(Jpre, MAT_FINAL_ASSEMBLY, ierr))
322d8606c27SBarry Smith    if (J /= Jpre) then
323d8606c27SBarry Smith      PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY, ierr))
324d8606c27SBarry Smith      PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY, ierr))
325d8606c27SBarry Smith    end if
326d8606c27SBarry Smith  end subroutine
327d8606c27SBarry Smith
328d8606c27SBarry Smith  subroutine FormInitialSolutionLocal(mx, xs, xe, gxs, gxe, x, a, k, s, ierr)
329d8606c27SBarry Smith    implicit none
330d8606c27SBarry Smith    PetscInt mx, xs, xe, gxs, gxe
331d8606c27SBarry Smith    PetscScalar x(2, xs:xe)
332d8606c27SBarry Smith    PetscReal a(2), k(2), s(2)
333d8606c27SBarry Smith    PetscErrorCode ierr
334d8606c27SBarry Smith
335d8606c27SBarry Smith    PetscInt i
336d8606c27SBarry Smith    PetscReal one, hx, r, ik
337d8606c27SBarry Smith    one = 1.0
338d8606c27SBarry Smith    hx = one/mx
339*ceeae6b5SMartin Diehl    do i = xs, xe
340d8606c27SBarry Smith      r = i*hx
3414820e4eaSBarry Smith      if (k(2) /= 0.0) then
342d8606c27SBarry Smith        ik = one/k(2)
343d8606c27SBarry Smith      else
344d8606c27SBarry Smith        ik = one
345d8606c27SBarry Smith      end if
346d8606c27SBarry Smith      x(1, i) = one + s(2)*r
347d8606c27SBarry Smith      x(2, i) = k(1)*ik*x(1, i) + s(2)*ik
348*ceeae6b5SMartin Diehl    end do
349d8606c27SBarry Smith  end subroutine
350d8606c27SBarry Smith
351d8606c27SBarry Smith  subroutine FormInitialSolution(ts, X, user, ierr)
352d8606c27SBarry Smith    use petscts
353d8606c27SBarry Smith    implicit none
354d8606c27SBarry Smith
355d8606c27SBarry Smith    TS ts
356d8606c27SBarry Smith    Vec X
357d8606c27SBarry Smith    PetscReal user(6)
358d8606c27SBarry Smith    PetscErrorCode ierr
359d8606c27SBarry Smith    integer user_a, user_k, user_s
360d8606c27SBarry Smith    parameter(user_a=1, user_k=3, user_s=5)
361d8606c27SBarry Smith
362d8606c27SBarry Smith    DM da
363d8606c27SBarry Smith    PetscInt mx, xs, xe, gxs, gxe
36442ce371bSBarry Smith    PetscScalar, pointer :: xx(:)
365d8606c27SBarry Smith
366d8606c27SBarry Smith    PetscCall(TSGetDM(ts, da, ierr))
367d8606c27SBarry Smith    PetscCall(GetLayout(da, mx, xs, xe, gxs, gxe, ierr))
368d8606c27SBarry Smith
369d8606c27SBarry Smith! Get access to vector data
370ce78bad3SBarry Smith    PetscCall(VecGetArray(X, xx, ierr))
371d8606c27SBarry Smith
37242ce371bSBarry Smith    PetscCall(FormInitialSolutionLocal(mx, xs, xe, gxs, gxe, xx, user(user_a), user(user_k), user(user_s), ierr))
373d8606c27SBarry Smith
374ce78bad3SBarry Smith    PetscCall(VecRestoreArray(X, xx, ierr))
375d8606c27SBarry Smith  end subroutine
376fe66ebccSMartin Diehlend program
377d8606c27SBarry Smith!/*TEST
378d8606c27SBarry Smith!
379d8606c27SBarry Smith!    test:
380d8606c27SBarry Smith!      args: -da_grid_x 200 -ts_arkimex_type 4
381d8606c27SBarry Smith!      requires: !single
3823886731fSPierre Jolivet!      output_file: output/empty.out
383d8606c27SBarry Smith!
384d8606c27SBarry Smith!TEST*/
385