Diagonally-dominant tridiagonal solve; central diagonal supplied as the
OFFSET ac from al + au (full pivot = ac + al + au). Never divides by
zero for positive-definite ac, al, au (White & Adcroft 2008).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | n |
Number of unknowns (= number of edges = nz+1) |
||
| real(kind=wp), | intent(in) | :: | al(n) |
Lower diagonal (al(1) unused) |
||
| real(kind=wp), | intent(in) | :: | ac(n) |
Central-diagonal OFFSET from al+au (full diagonal = ac+al+au) |
||
| real(kind=wp), | intent(in) | :: | au(n) |
Upper diagonal (au(n) unused) |
||
| real(kind=wp), | intent(in) | :: | r(n) |
Right-hand side |
||
| real(kind=wp), | intent(out) | :: | x(n) |
Solution vector |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private | :: | c1(NZ_STACK_MAX+1) | ||||
| real(kind=wp), | private | :: | d1 | ||||
| real(kind=wp), | private | :: | denom_t1 | ||||
| real(kind=wp), | private | :: | i_pivot | ||||
| integer, | private | :: | k |
pure subroutine pqm_solve_diag_dominant(n, al, ac, au, r, x) !$acc routine seq !! Diagonally-dominant tridiagonal solve; central diagonal supplied as the !! OFFSET `ac` from `al + au` (full pivot = ac + al + au). Never divides by !! zero for positive-definite ac, al, au (White & Adcroft 2008). integer, intent(in) :: n !! Number of unknowns (= number of edges = nz+1) real(wp), intent(in) :: al(n) !! Lower diagonal (al(1) unused) real(wp), intent(in) :: ac(n) !! Central-diagonal OFFSET from al+au (full diagonal = ac+al+au) real(wp), intent(in) :: au(n) !! Upper diagonal (au(n) unused) real(wp), intent(in) :: r(n) !! Right-hand side real(wp), intent(out) :: x(n) !! Solution vector real(wp) :: c1(NZ_STACK_MAX + 1) real(wp) :: d1, i_pivot, denom_t1 integer :: k i_pivot = 1.0_wp/(ac(1) + au(1)) d1 = ac(1)*i_pivot c1(1) = au(1)*i_pivot x(1) = r(1)*i_pivot do k = 2, n - 1 denom_t1 = ac(k) + d1*al(k) i_pivot = 1.0_wp/(denom_t1 + au(k)) d1 = denom_t1*i_pivot c1(k) = au(k)*i_pivot x(k) = (r(k) - al(k)*x(k - 1))*i_pivot end do i_pivot = 1.0_wp/(ac(n) + d1*al(n)) x(n) = (r(n) - al(n)*x(n - 1))*i_pivot do k = n - 1, 1, -1 x(k) = x(k) - c1(k)*x(k + 1) end do end subroutine pqm_solve_diag_dominant