Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_tridiagonal.F90
Go to the documentation of this file.
1 !**************************************************************
2 ! Copyright INRIA
3 ! Authors :
4 ! CALVI project team
5 !
6 ! This code SeLaLib (for Semi-Lagrangian-Library)
7 ! is a parallel library for simulating the plasma turbulence
8 ! in a tokamak.
9 !
10 ! This software is governed by the CeCILL-B license
11 ! under French law and abiding by the rules of distribution
12 ! of free software. You can use, modify and redistribute
13 ! the software under the terms of the CeCILL-B license as
14 ! circulated by CEA, CNRS and INRIA at the following URL
15 ! "http://www.cecill.info".
16 !**************************************************************
17 
58 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
59 #include "sll_working_precision.h"
60 
61  implicit none
62 
63  public :: &
67 
68  private
69 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
70 
74  end interface
75 contains
76 
77 ! careful with side-effects here
78 #define SWP(aval,bval) swp=(aval); aval=(bval); bval=swp
79 
80  !---------------------------------------------------------------------------
81  !
82  ! Implementation notes:
83  ! **********************
84  ! (Adapted) description for the C implementation:
85  !
86  ! sll_s_setup_cyclic_tridiag computes the LU factorization of a cylic
87  ! tridiagonal matrix specified in a band-diagonal representation.
88  ! sll_o_solve_cyclic_tridiag uses this factorization to solve of the
89  ! system to solve the system Ax = b quickly and robustly.
90  !
91  ! Unambigously, the input tridiagonal system is specified by:
92  !
93  ! + a(2) a(3) a(1) +
94  ! | a(4) a(5) a(6) |
95  ! A = | a(7) a(8) a(9) |
96  ! | ... |
97  ! | a(3n-5) a(3n-4) a(3n-3) |
98  ! + a(3n) a(3n-2) a(3n-1) +
99  !
100  ! The LU factorization does partial (row) pivoting, so the
101  ! factorization requires slightly more memory to hold than standard
102  ! non-pivoting tridiagonal (or cyclic tridiagonal) solution methods
103  ! The benefit is that this routine can accomodate systems that are
104  ! not diagonally dominant.
105  !
106  ! The output factorization is stored in "cts" and "ipiv" (the pivot
107  ! information). In general, all you need to know about "cts" is that
108  ! it is what you give to sll_o_solve_cyclic_tridiag. However, for the
109  ! masochistic, the final factorization is stored in seven vectors
110  ! of length n which are packed into the vector cts in the order:
111  ! d u v q r l m. The L and U factors of A are built out of vectors
112  ! and have the structure:
113  !
114  ! + 1 +
115  ! | l0 1 |
116  ! | l1 1 |
117  ! | ... |
118  ! L = | ... |
119  ! | ln4 1 |
120  ! | ln3 1 |
121  ! + m0 m1 m2 ... mn4 mn3 ln2 1 +
122  !
123  ! and:
124  !
125  ! + d0 u0 v0 q0 r0 +
126  ! | d1 u1 v1 q1 r1 |
127  ! | d2 u2 v2 q2 r2 |
128  ! | ... : : |
129  ! U = | ... : : |
130  ! | dn6 un6 vn6 qn6 rn6 |
131  ! | dn5 un5 vn5 qn5 rn5 |
132  ! | dn4 un4 vn4 rn4 |
133  ! | dn3 un3 vn3 |
134  ! | dn2 un2 |
135  ! + dn1 +
136  !
137  ! Such that LU = PA. (The vector p describes the pivoting matrix.
138  ! p[i] = j indicates that in step i of the factorization, row i was
139  ! swapped with row j. See Golub & van Loan. Matrix Computations.
140  ! Section 3.4.3 for more details.) For the convenience of other
141  ! functions that use the output, the elements of d,l,m,u,v,q,r not
142  ! shown explicitly above are set to zero.
143  !
144  ! Note that if a zero pivot is encountered (i.e. the det(A) is
145  ! indistinguishable from zero as far as the computer can tell),
146  ! this routine returns an error."
147  !
148  ! *************************************************************************
149 
150 !---------------------------------------------------------------------------
161  subroutine sll_s_setup_cyclic_tridiag(a, n, cts, ipiv)
162  intrinsic :: abs
163  sll_real64, dimension(:) :: a ! 3*n size allocation
164  sll_int32, intent(in) :: n ! a is nXn
165  sll_int32, intent(out), dimension(1:n) :: ipiv
166  sll_real64, intent(out), dimension(1:7*n), target :: cts ! 7*n allocation
167 
168  ! The following variables represent a scratch space where the local
169  ! computations are made.
170  sll_real64 :: s11, s12, s13, s14, s15
171  sll_real64 :: s21, s22, s23, s24, s25
172  sll_real64 :: s31, s32, s33, s34, s35
173  sll_real64 :: t1, t2, t3, swp
174 
175  sll_real64, pointer :: d(:)
176  sll_real64, pointer :: u(:)
177  sll_real64, pointer :: v(:)
178  sll_real64, pointer :: q(:)
179  sll_real64, pointer :: r(:)
180  sll_real64, pointer :: l(:)
181  sll_real64, pointer :: m(:)
182  sll_int32 :: i
183 
184  s11 = 0._f64
185  s12 = 0._f64
186  s13 = 0._f64
187  s14 = 0._f64
188  s15 = 0._f64
189 
190  s21 = 0._f64
191  s22 = 0._f64
192  s23 = 0._f64
193  s24 = 0._f64
194  s25 = 0._f64
195 
196  s31 = 0._f64
197  s32 = 0._f64
198  s33 = 0._f64
199  s34 = 0._f64
200  s35 = 0._f64
201 
202  cts(1:7*n) = 0._f64
203  d => cts(1:n)
204  u => cts(n + 1:2*n)
205  v => cts(2*n + 1:3*n)
206  q => cts(3*n + 1:4*n)
207  r => cts(4*n + 1:5*n)
208  l => cts(5*n + 1:6*n)
209  m => cts(6*n + 1:7*n)
210 
211  ! The following indexing allows us to dereference the array a as if it
212  ! were a rank-2 array. Note that a(1,0) = a(1), i.e.: the cyclic term
213  ! in the first equation and that a(n,n+1) = a(n), i.e.: the cyclic term
214  ! in the last equation.
215 #define aa(ii,jj) a(2*((ii)-1)+(jj)+1)
216  select case (n)
217  case (3) ! we just reproduce the input array on the scratch space
218  s11 = aa(1, 1); s12 = aa(1, 2); s13 = aa(1, 0)
219  s21 = aa(2, 1); s22 = aa(2, 2); s23 = aa(2, 3)
220  s31 = aa(3, 4); s32 = aa(3, 2); s33 = aa(3, 3)
221  case (4)
222  s11 = aa(1, 1); s12 = aa(1, 2); s13 = 0.0_f64; s14 = aa(1, 0)
223  s21 = aa(2, 1); s22 = aa(2, 2); s23 = aa(2, 3); s24 = 0.0_f64
224  s31 = aa(4, 5); s32 = 0.0_f64; s33 = aa(4, 3); s34 = aa(4, 4)
225  case default
226  s11 = aa(1, 1); s12 = aa(1, 2); s13 = 0.0_f64; s14 = 0.0_f64; s15 = aa(1, 0)
227  s21 = aa(2, 1); s22 = aa(2, 2); s23 = aa(2, 3); s24 = 0.0_f64; s25 = 0.0_f64
228  s31 = aa(n, n + 1); s32 = 0.0_f64; s33 = 0.0_f64; s34 = aa(n, n - 1); s35 = aa(n, n)
229  end select
230 
231  ! Factor the matrix with row pivoting
232  do i = 1, n
233  if (i .lt. n - 3) then
234  ! Matrix thus far (zeros not shown)
235  !
236  ! | 1 2 3 4 5 ... i-1 i i+1 i+2 ... n-1 n
237  ! --+-------------------------------------------------------------
238  ! 1 | d1 u1 v1 q1 r1
239  ! 2 | l1 d2 u2 v2 q2 r2
240  ! 3 | l2 d3 u3 v4 q3 r3
241  ! : | ... : :
242  ! : | ... : :
243  !i-1| di1 ui1 vi1 qi ri1
244  ! i | li1 s11 s12 s13... s14 s15
245  !i+1| s21 s22 s23... s24 s25
246  ! |
247  ! | Untouched rows of A
248  ! |
249  ! n | m1 m2 m3 m4 m5 ... mi1 s31 s32 s33 ...s34 s35
250 
251  ! Pivot
252 
253  t1 = abs(s11)
254  t2 = abs(s21)
255  t3 = abs(s31)
256  if ((t1 < t2) .or. (t1 < t3)) then
257  if (t3 > t2) then ! swap rows i and n
258  swp(s11, s31)
259  swp(s12, s32)
260  swp(s13, s33)
261  swp(s14, s34)
262  swp(s15, s35)
263  ipiv(i) = n
264  else ! swap rows i and i+1
265  swp(s11, s21)
266  swp(s12, s22)
267  swp(s13, s23)
268  swp(s14, s24)
269  swp(s15, s25)
270  ipiv(i) = i + 1
271  end if
272  else ! no swapping necessary
273  ipiv(i) = i
274  end if
275  ! Eliminate the current column of A below the diagonal. The
276  ! column of L will be stored in place of the zeros.
277  if (s11 == 0.0_f64) print *, 'zero determinant' ! FIX THIS
278  s21 = s21/s11
279  s22 = s22 - s21*s12
280  s23 = s23 - s21*s13
281  s24 = s24 - s21*s14
282  s25 = s25 - s21*s15
283  s31 = s31/s11
284  s32 = s32 - s31*s12
285  s33 = s33 - s31*s13
286  s34 = s34 - s31*s14
287  s35 = s35 - s31*s15
288 
289  ! Save the column of L an row of U
290 
291  d(i) = s11; u(i) = s12; v(i) = s13; q(i) = s14; r(i) = s15
292  l(i) = s21
293  m(i) = s31
294 
295  ! Advance the scratch space for the next iteration
296 
297  if (i < (n - 4)) then
298  s11 = s22; s12 = s23; s13 = 0.0_f64; s14 = s24; s15 = s25
299  s21 = aa(i + 2, i + 1); s22 = aa(i + 2, i + 2); s23 = aa(i + 2, i + 3); s24 = 0.0_f64; s25 = 0.0_f64
300  s31 = s32; s32 = s33; s33 = 0.0_f64; s34 = s34; s35 = s35
301  else
302  s11 = s22; s12 = s23; s13 = s24; s14 = s25;
303  s21 = aa(i + 2, i + 1); s22 = aa(i + 2, i + 2); s23 = aa(i + 2, i + 3); s24 = 0.0_f64
304  s31 = s32; s32 = s33; s33 = s34; s34 = s35
305  end if
306  else if (i == (n - 3)) then
307  ! Matrix so far (zeros not shown):
308  !
309  ! | 1 2 3 4 5 ... n-5 n-4 n-3 n-2 n-1 n
310  ! ----+---------------------------------------------------
311  ! 1 | d1 u1 v1 q1 r1
312  ! 2 | l1 d2 u2 v2 q2 r2
313  ! 3 | l2 d3 u3 v3 q3 r3
314  ! : | ... : :
315  ! : | ... : :
316  ! n-5 | dn5 un5 vn5 qn5 rn5
317  ! n-4 | ln5 dn4 un4 vn4 qn4 rn4
318  ! n-3 | ln4 s11 s12 s13 s14
319  ! n-2 | s21 s22 s23 s24
320  ! n-1 | Untouched row of A
321  ! n | m1 m2 m3 m4 m5 ... mn5 mn4 s31 s32 s33 s34
322  !
323  ! Pivot
324  t1 = abs(s11)
325  t2 = abs(s21)
326  t3 = abs(s31)
327  if ((t1 < t2) .or. (t1 < t3)) then
328  if (t3 > t2) then ! swap rows i and n
329  swp(s11, s31)
330  swp(s12, s32)
331  swp(s13, s33)
332  swp(s14, s34)
333  ipiv(i) = n
334  else ! swap rows i and i+1
335  swp(s11, s21)
336  swp(s12, s22)
337  swp(s13, s23)
338  swp(s14, s24)
339  ipiv(i) = i + 1
340  end if
341  else
342  ipiv(i) = i
343  end if
344 
345  ! Eliminate the current column of A below the diagonal. The column
346  ! of L will be stored in place of the zeros.
347 
348  if (s11 == 0.0_f64) print *, 'Zero determinant' ! FIX: Do something else!
349  s21 = s21/s11
350  s22 = s22 - s21*s12
351  s23 = s23 - s21*s13
352  s24 = s24 - s21*s14
353  s31 = s31/s11
354  s32 = s32 - s31*s12
355  s33 = s33 - s31*s13
356  s34 = s34 - s31*s14
357 
358  ! Save the column of L and row of U
359  d(i) = s11; u(i) = s12; v(i) = s13; r(i) = s14
360  l(i) = s21
361  m(i) = s31
362  q(i) = 0.0_f64
363 
364  ! Advance the scratch space for the next iteration
365  s11 = s22; s12 = s23; s13 = s24
366  s21 = aa(i + 2, i + 1); s22 = aa(i + 2, i + 2); s23 = aa(i + 2, i + 3)
367  s31 = s32; s32 = s33; s33 = s34
368  else if (i == n - 2) then
369  ! Matrix so far (zeros not shown):
370  !
371  ! | 1 2 3 4 5 ... n-5 n-4 n-3 n-2 n-1 n
372  ! ----+---------------------------------------------------
373  ! 1 | d1 u1 v1 q1 r1
374  ! 2 | l1 d2 u2 v2 q2 r2
375  ! 3 | l2 d3 u3 v3 q3 r3
376  ! : | ... : :
377  ! : | ... : :
378  ! n-5 | dn5 un5 vn5 qn5 rn5
379  ! n-4 | ln5 dn4 un4 vn4 qn4 rn4
380  ! n-3 | ln4 dn3 un3 vn3 rn3
381  ! n-2 | ln3 s11 s12 s13
382  ! n-1 | s21 s22 s23
383  ! n | m1 m2 m3 m4 m5 ... mn5 mn4 mn3 s31 s32 s33
384  !
385  ! Pivot
386  t1 = abs(s11)
387  t2 = abs(s21)
388  t3 = abs(s31)
389  if ((t1 < t2) .or. (t1 < t3)) then
390  if (t3 > t2) then ! swap rows i and n
391  swp(s11, s31)
392  swp(s12, s32)
393  swp(s13, s33)
394  ipiv(i) = n
395  else ! swap rows i and i+1
396  swp(s11, s21)
397  swp(s12, s22)
398  swp(s13, s23)
399  ipiv(i) = i + 1
400  end if
401  else
402  ipiv(i) = i
403  end if
404  ! Eliminate the current column of A below the diagonal. The
405  ! column of L will be sotred inplace of the zeros.
406  if (s11 == 0.0_f64) print *, 'zero determinant' ! FIX THIS
407  s21 = s21/s11
408  s22 = s22 - s21*s12
409  s23 = s23 - s21*s13
410  s31 = s31/s11
411  s32 = s32 - s31*s12
412  s33 = s33 - s31*s13
413 
414  ! Save the column of L and row of U
415  d(i) = s11; u(i) = s12; v(i) = s13
416  l(i) = s21
417  m(i) = s31
418 
419  q(i) = 0.0_f64
420  r(i) = 0.0_f64
421 
422  ! Advance the scratch space for the next iteration
423  s11 = s22; s12 = s23
424  s21 = s32; s22 = s33
425  else if (i == n - 1) then
426 
427  ! Matrix so far (zeros not shown):
428  !
429  ! | 1 2 3 4 5 ... n-5 n-4 n-3 n-2 n-1 n
430  ! ----+---------------------------------------------------
431  ! 1 | d1 u1 v1 q1 r1
432  ! 2 | l1 d2 u2 v2 q2 r2
433  ! 3 | l2 d3 u3 v3 q3 r3
434  ! : | ... : :
435  ! : | ... : :
436  ! n-5 | dn5 un5 vn5 qn5 rn5
437  ! n-4 | ln5 dn4 un4 vn4 qn4 rn4
438  ! n-3 | ln4 dn3 un3 vn3 rn3
439  ! n-2 | ln3 dn2 un2 vn2
440  ! n-1 | ln2 s11 s12
441  ! n | m1 m2 m3 m4 m5 ... mn5 mn4 mn3 mn2 s21 s22
442  !
443  ! Pivot
444  t1 = abs(s11)
445  t2 = abs(s21)
446  if (t1 < t2) then
447  swp(s11, s21)
448  swp(s12, s22)
449  ipiv(i) = i + 1
450  else ! swap rows i and i+1
451  ipiv(i) = i
452  end if
453 
454  ! Eliminate the current column of A below the diagonal.
455  ! The column of L will be stored in place of the zeros.
456  if (s11 == 0.0_f64) print *, 'Zero determinant' ! FIX THIS
457  s21 = s21/s11
458  s22 = s22 - s21*s12
459 
460  ! Save the column of L and row of U
461 
462  d(i) = s11; u(i) = s12
463  l(i) = s21
464 
465  v(i) = 0.0_f64
466  r(i) = 0.0_f64
467  q(i) = 0.0_f64
468  m(i) = 0.0_f64
469 
470  ! Advance the scratch space for the next iteration
471 
472  s11 = s22
473 
474  else ! i==n
475  ! Matrix so far (zeros not shown):
476  !
477  ! | 1 2 3 4 5 ... n-5 n-4 n-3 n-2 n-1 n
478  ! ----+---------------------------------------------------
479  ! 1 | d1 u1 v1 q1 r1
480  ! 2 | l1 d2 u2 v2 q1 r1
481  ! 3 | l2 d3 u3 v3 q3 r3
482  ! : | ... : :
483  ! : | ... : :
484  ! n-5 | dn5 un5 vn5 qn5 rn5
485  ! n-4 | ln5 dn4 un4 vn4 qn4 rn4
486  ! n-3 | ln4 dn3 un3 vn3 rn3
487  ! n-2 | ln3 dn2 un2 vn2
488  ! n-1 | ln2 dn1 un1
489  ! n | m1 m2 m3 m4 m5 ... mn5 mn4 mn3 mn2 ln1 s11
490 
491  if (s11 == 0.0_f64) print *, 'zero determinant' ! FIX THIS
492  ipiv(i) = i
493  d(i) = s11
494  u(i) = 0.0_f64
495  v(i) = 0.0_f64
496  r(i) = 0.0_f64
497  q(i) = 0.0_f64
498  l(i) = 0.0_f64
499  m(i) = 0.0_f64
500  end if
501  end do
502 
503  end subroutine sll_s_setup_cyclic_tridiag
504 #undef aa
505 
506  !---------------------------------------------------------------------------
527  subroutine sll_s_solve_cyclic_tridiag_double(cts, ipiv, b, n, x)
528  ! size of the allocations:
529  ! x: n
530  ! cts: 7n
531  ! ipiv: n
532  ! b: n
533 
534  sll_int32, intent(in) :: n ! matrix size
535  sll_real64, dimension(1:7*n), target :: cts ! 7*n size allocation
536  sll_int32, dimension(1:n), intent(in) :: ipiv
537  sll_real64, target :: b(n)
538  sll_real64, target :: x(n)
539  sll_real64, pointer, dimension(:) :: bptr
540  sll_real64, pointer, dimension(:) :: xptr
541  sll_real64 :: swp
542  sll_int32 :: i
543  sll_int32 :: inew
544  sll_real64, pointer :: d(:)
545  sll_real64, pointer :: u(:)
546  sll_real64, pointer :: v(:)
547  sll_real64, pointer :: q(:)
548  sll_real64, pointer :: r(:)
549  sll_real64, pointer :: l(:)
550  sll_real64, pointer :: m(:)
551 
552  d => cts(1:n)
553  u => cts(n + 1:2*n)
554  v => cts(2*n + 1:3*n)
555  q => cts(3*n + 1:4*n)
556  r => cts(4*n + 1:5*n)
557  l => cts(5*n + 1:6*n)
558  m => cts(6*n + 1:7*n)
559 
560  !do i=1,n
561  ! print *,'duvqrlm=',i,d(i),u(i),v(i),q(i),r(i),l(i),m(i)
562  !enddo
563 
564  bptr => b(1:n)
565  xptr => x(1:n)
566  ! FIX: ADD SOME ERROR CHECKING ON ARGUMENTS
567  if (.not. associated(xptr, target=bptr)) then
568  do i = 1, n
569  x(i) = b(i)
570  end do
571  end if
572  ! 'x' contains now the informatin in 'b', in case that it was given as
573  ! a different array.
574  !
575  ! Overwrite x with the solution of Ly = Pb
576  do i = 1, n - 1
577  swp(x(i), x(ipiv(i)))
578  x(i + 1) = x(i + 1) - l(i)*x(i)
579  x(n) = x(n) - m(i)*x(i)
580  end do
581 
582  ! Overwrite x with the solution of Ux = y
583  i = n
584  x(i) = x(i)/d(i)
585  i = i - 1
586  x(i) = (x(i) - u(i)*x(i + 1))/d(i)
587  !i = i-1
588  inew = i - 1
589  do i = inew, 1, -1
590  !do i=i,1,-1
591  x(i) = (x(i) - (u(i)*x(i + 1) + v(i)*x(i + 2) + &
592  q(i)*x(n - 1) + r(i)*x(n)))/d(i)
593  end do
594  end subroutine sll_s_solve_cyclic_tridiag_double
595 
602  subroutine solve_cyclic_tridiag_complex(cts, ipiv, b, n, x)
603  ! size of the allocations:
604  ! x: n
605  ! cts: 7n
606  ! ipiv: n
607  ! b: n
608 
609  sll_int32, intent(in) :: n ! matrix size
610  sll_real64, dimension(1:7*n), target :: cts ! 7*n size allocation
611  sll_int32, dimension(1:n), intent(in) :: ipiv
612  sll_comp64, target :: b(n)
613  sll_comp64, target :: x(n)
614  sll_comp64, pointer, dimension(:) :: bptr
615  sll_comp64, pointer, dimension(:) :: xptr
616  sll_comp64 :: swp
617  sll_int32 :: i, inew
618  sll_real64, pointer :: d(:)
619  sll_real64, pointer :: u(:)
620  sll_real64, pointer :: v(:)
621  sll_real64, pointer :: q(:)
622  sll_real64, pointer :: r(:)
623  sll_real64, pointer :: l(:)
624  sll_real64, pointer :: m(:)
625 
626  d => cts(1:n)
627  u => cts(n + 1:2*n)
628  v => cts(2*n + 1:3*n)
629  q => cts(3*n + 1:4*n)
630  r => cts(4*n + 1:5*n)
631  l => cts(5*n + 1:6*n)
632  m => cts(6*n + 1:7*n)
633 
634  bptr => b(1:n)
635  xptr => x(1:n)
636 
637  ! FIX: ADD SOME ERROR CHECKING ON ARGUMENTS
638  if (.not. associated(xptr, target=bptr)) then
639  do i = 1, n
640  x(i) = b(i)
641  end do
642  end if
643  ! 'x' contains now the informatin in 'b', in case that it was given as
644  ! a different array.
645  !
646  ! Overwrite x with the solution of Ly = Pb
647  do i = 1, n - 1
648  swp(x(i), x(ipiv(i)))
649  x(i + 1) = x(i + 1) - cmplx(l(i), 0.0_f64, kind=f64)*x(i)
650  x(n) = x(n) - cmplx(m(i), 0.0, f64)*x(i)
651  end do
652 
653  ! Overwrite x with the solution of Ux = y
654  i = n
655  x(i) = x(i)/cmplx(d(i), 0.0, f64)
656  i = i - 1
657  x(i) = (x(i) - cmplx(u(i), 0.0, f64)*x(i + 1))/cmplx(d(i), 0.0, f64)
658  inew = i - 1
659  do i = inew, 1, -1
660  x(i) = (x(i) - (cmplx(u(i), 0.0, f64)*x(i + 1) + cmplx(v(i), 0.0, f64)*x(i + 2) + &
661  cmplx(q(i), 0.0, f64)*x(n - 1) + cmplx(r(i), 0.0, f64)*x(n)))/cmplx(d(i), 0.0, kind=f64)
662  end do
663  end subroutine solve_cyclic_tridiag_complex
664 
665  ! @brief Solves the system ax=b
666  ! param[in] a Global matrix
667  ! param[in] b Second member
668  ! param[in] n Problem size (a is nxn)
669  ! param[out] x Solution vector
670  !SUBROUTINE solve_tridiag(a, b, n ,x)
671  ! sll_int32, intent(in) :: n
672  ! sll_real64, DIMENSION(n), intent(in) :: a
673  ! sll_real64, DIMENSION(n), intent(inout) :: b
674  ! sll_real64, DIMENSION(1:7*n) :: cts
675  ! sll_int32, DIMENSION(1:n) :: ipiv
676  ! sll_real64, DIMENSION(:) :: x
677  ! CALL sll_s_setup_cyclic_tridiag( a, n, cts, ipiv )
678  ! CALL sll_o_solve_cyclic_tridiag( cts, ipiv, b, n, x )
679  !END SUBROUTINE solve_tridiag
680 
681 end module sll_m_tridiagonal
Solve tridiagonal system (double or complex)
Tridiagonal system solver.
subroutine, public sll_s_setup_cyclic_tridiag(a, n, cts, ipiv)
Give the factorization of the matrix in argument.
subroutine, public sll_s_solve_cyclic_tridiag_double(cts, ipiv, b, n, x)
Solves tridiagonal system.
subroutine solve_cyclic_tridiag_complex(cts, ipiv, b, n, x)
Complex version of sll_s_solve_cyclic_tridiag_double.
    Report Typos and Errors