https://github.com/CosmicFish/CosmicFish
Raw File
Tip revision: 84d4d231d5f2d5c0fc1691f8e61368864d461973 authored by Marco Raveri on 03 February 2017, 19:55:45 UTC
Window function printer added
Tip revision: 84d4d23
001_Matrix_utilities.f90
!----------------------------------------------------------------------------------------
!
! This file is part of CosmicFish.
!
! Copyright (C) 2015-2016 by the CosmicFish authors
!
! The CosmicFish code is free software;
! You can use it, redistribute it, and/or modify it under the terms
! of the GNU General Public License as published by the Free Software Foundation;
! either version 3 of the License, or (at your option) any later version.
! The full text of the license can be found in the file LICENSE at
! the top level of the CosmicFish distribution.
!
!----------------------------------------------------------------------------------------

!> @file 001_Matrix_utilities.f90
!! This file contains several subroutine and functions that can be used to
!! manipulate and modify matrices.
!! For many of them it is simply a wrapper to LAPACK.

!----------------------------------------------------------------------------------------
!> This module contains the subroutine and functions to manipulate and modify matrices.

!> @author Marco Raveri

module Matrix_utilities

    use precision

    implicit none

    private

    public Sym_Matrix_Inversion, matrix_determinant, matrix_eigenvalues_eigenvectors_sym

contains

    ! ---------------------------------------------------------------------------------------------
    !> This subroutine computes the inverse of a square symmetric matrix by means of LAPACK
    !! LU decomposition and inversion.
    subroutine Sym_Matrix_Inversion(A, error_code)

        implicit none

        real(dl), dimension(:,:), intent(inout) :: A !< Input and output matrix. Inversion happends in place.
        integer , intent(out) :: error_code          !< Error code: 0 means everything ok
                                                     !! 1 means singular matrix
                                                     !! 2 means inversion failed for some reason

        real(dl), dimension(size(A,1)) :: work   ! work array for LAPACK
        integer , dimension(size(A,1)) :: ipiv   ! pivot indices
        integer :: n, info

        ! External procedures defined in LAPACK
        external dgetrf
        external dgetri

        error_code = 0
        n = size(A,1)

        ! dgetrf computes an LU factorization of a general M-by-N matrix A
        ! using partial pivoting with row interchanges.
        call dgetrf(n, n, A, n, ipiv, info)

        if (info /= 0) then
            error_code = 1
            write(*,*) 'Matrix is numerically singular!'
            return
        end if

        ! dgetri computes the inverse of a matrix using the LU factorization
        ! computed by dgetrf.
        call dgetri(n, A, n, ipiv, work, n, info)

        if (info /= 0) then
            error_code = 2
            write(*,*) 'Matrix inversion failed!'
            return
        end if

    end subroutine Sym_Matrix_Inversion

    ! ---------------------------------------------------------------------------------------------
    !> This subroutine computes the determinant of a matrix.
    subroutine matrix_determinant(A, det, error_code)

        implicit none

        real(dl), dimension(:,:), intent(in) :: A !< Input matrix.
        real(dl), intent(out) :: det              !< Output determinant of the matrix.
        integer , intent(out) :: error_code       !< Error code: 0 means everything ok

        integer  :: N, i, info, AllocateStatus
        real(dl) :: sgn
        integer , dimension(:), allocatable :: ipiv   ! pivot indices
        ! External procedures defined in LAPACK
        external dgetrf

        N          = size(A,1)
        error_code = 0

        allocate( ipiv(N), stat = AllocateStatus )
        if (AllocateStatus /= 0) stop "matrix_determinant: allocation failed. Not enough memory."

        ipiv=0

        ! dgetrf computes an LU factorization of a general M-by-N matrix A
        ! using partial pivoting with row interchanges.
        call dgetrf(n, n, A, n, ipiv, info)

        if (info /= 0) then
            error_code = 1
            write(*,*) 'Matrix is numerically singular!'
            stop
        end if

        det = 1._dl

        do i=1, N
            det = det*A(i,i)
        end do

        sgn = 1._dl

        do i=1, N
            if(ipiv(i)/=i)then
                sgn=-sgn
            end if
        end do

        det=sgn*det

        return

    end subroutine matrix_determinant

    ! ---------------------------------------------------------------------------------------------
    !> This subroutine computes the eigenvalues and eigenvectors of a matrix.
    subroutine matrix_eigenvalues_eigenvectors_sym(A, eigenvalues, eigenvectors, error_code)

        implicit none

        real(dl), dimension(:,:), intent(in)  :: A             !< Input matrix.
        real(dl), dimension(:)  , intent(out) :: eigenvalues   !< Output eigenvalues
        real(dl), dimension(:,:), intent(out) :: eigenvectors  !< Output eigenvectors
        integer , intent(out) :: error_code                    !< Error code: 0 means everything ok

        eigenvectors = 0._dl
        eigenvalues  = 0._dl
        error_code   = 0

        stop 'matrix_eigenvalues_eigenvectors_sym not yet implemented.'

    end subroutine matrix_eigenvalues_eigenvectors_sym

    ! ---------------------------------------------------------------------------------------------

end module Matrix_utilities
back to top