Inverts the n x n matrix a by Gauss-Jordan elimination with partial pivoting, in double precision. Used once in Init for the (N+1) x (N+1) sweep matrices, which are small and well enough conditioned for a direct solve; this follows the routine of the same name in SELF_RefinementIndicator_3D_t.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=real64), | intent(in) | :: | a(1:n,1:n) | |||
| real(kind=real64), | intent(out) | :: | aInv(1:n,1:n) | |||
| integer, | intent(in) | :: | n |
subroutine InvertMatrix(a,aInv,n)
!! Inverts the n x n matrix a by Gauss-Jordan elimination with partial pivoting, in
!! double precision. Used once in Init for the (N+1) x (N+1) sweep matrices, which
!! are small and well enough conditioned for a direct solve; this follows the
!! routine of the same name in SELF_RefinementIndicator_3D_t.
implicit none
integer,intent(in) :: n
real(real64),intent(in) :: a(1:n,1:n)
real(real64),intent(out) :: aInv(1:n,1:n)
! Local
real(real64) :: b(1:n,1:n)
integer :: i,j,k,piv
real(real64) :: pmax,factor,tmp
b = a
aInv = 0.0_real64
do i = 1,n
aInv(i,i) = 1.0_real64
enddo
do k = 1,n
! Partial pivot: the largest entry of column k at or below the diagonal
piv = k
pmax = abs(b(k,k))
do i = k+1,n
if(abs(b(i,k)) > pmax) then
pmax = abs(b(i,k))
piv = i
endif
enddo
if(pmax <= 0.0_real64) then
error stop "ColumnOperators3D : singular sweep matrix"
endif
if(piv /= k) then
do j = 1,n
tmp = b(k,j); b(k,j) = b(piv,j); b(piv,j) = tmp
tmp = aInv(k,j); aInv(k,j) = aInv(piv,j); aInv(piv,j) = tmp
enddo
endif
! Normalize the pivot row
factor = b(k,k)
do j = 1,n
b(k,j) = b(k,j)/factor
aInv(k,j) = aInv(k,j)/factor
enddo
! Eliminate column k from every other row
do i = 1,n
if(i /= k) then
factor = b(i,k)
do j = 1,n
b(i,j) = b(i,j)-factor*b(k,j)
aInv(i,j) = aInv(i,j)-factor*aInv(k,j)
enddo
endif
enddo
enddo
endsubroutine InvertMatrix