module matrix_inversion use types, only : p implicit none private public inv contains subroutine ludcmp(a, n, np, indx, d) real(p), intent(inout) :: a(np, np), d integer, intent(inout) :: indx(n) integer, intent(in) :: n, np integer, parameter :: nmax = 100 real(p), parameter :: tiny = 1.0e-20 integer :: i, j, k, imax real(p) :: vv(nmax), aamax, dum, sum d = 1.0 imax = 0 do i = 1, n aamax = 0. do j = 1, n if(abs(a(i, j))>aamax) aamax = abs(a(i, j)) end do if(aamax==0.) then write(0,*) "Error during the LU decomposition. The input matrix is singular." stop end if vv(i) = 1. / aamax end do do j = 1, n if(j>1) then do i = 1, j - 1 sum = a(i, j) if(i>1) then do k = 1, i - 1 sum = sum - a(i, k) * a(k, j) end do a(i, j) = sum end if end do end if aamax = 0. do i = j, n sum = a(i, j) if (j>1) then do k = 1, j - 1 sum = sum - a(i, k) * a(k, j) end do a(i, j) = sum end if dum = vv(i) * abs(sum) if(dum>=aamax) then imax = i aamax = dum end if end do if (j/=imax) then do k = 1, n dum = a(imax, k) a(imax, k) = a(j, k) a(j, k) = dum end do d = -d vv(imax) = vv(j) end if indx(j) = imax if(j/=n) then if(a(j, j)==0) a(j, j) = tiny dum = 1. / a(j, j) do i = j + 1, n a(i, j) = a(i, j) * dum end do end if end do if (a(n, n)==0.) then a(n, n) = tiny end if end subroutine lubksb(a, n, np, indx, b) real(p), intent(inout) :: a(np, np), b(n) integer, intent(in) :: n, np, indx(n) integer :: ii, i, ll, j real(p) :: sum ii = 0 do i = 1, n ll = indx(i) sum = b(ll) b(ll) = b(i) if(ii/=0) then do j = ii, i - 1 sum = sum - a(i, j) * b(j) end do else if(sum/=0) then ii = i end if b(i) = sum end do do i = n, 1, -1 sum = b(i) if(i<n) then do j = i + 1, n sum = sum - a(i, j) * b(j) end do end if b(i) = sum / a(i, i) end do end subroutine inv(a, y, indx, n) real(p), intent(inout) :: a(n, n), y(n, n) integer, intent(inout) :: indx(n) integer, intent(in) :: n integer :: i real(p) :: d y = 0.0 do i = 1, n y(i, i) = 1. end do call ludcmp(a, n, n, indx, d) do i = 1, n call lubksb(a, n, n, indx, y(1, i)) end do end end module