!> !> @file matrix.f90 !> !> @brief !> !> @copyright !> Copyright (©) 2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) !> SPC (Swiss Plasma Center) !> !> SPClibs is free software: you can redistribute it and/or modify it under !> the terms of the GNU Lesser General Public License as published by the Free !> Software Foundation, either version 3 of the License, or (at your option) !> any later version. !> !> SPClibs is distributed in the hope that it will be useful, but WITHOUT ANY !> WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS !> FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. !> !> You should have received a copy of the GNU Lesser General Public License !> along with this program. If not, see . !> !> @author !> (in alphabetical order) !> @author Trach-Minh Tran !> MODULE matrix ! ! MATRIX: Simple interface to the direct solver LAPACK. ! ! T.M. Tran, CRPP-EPFL ! February 2007 ! IMPLICIT NONE ! TYPE gbmat ! Lapack General Band matrix storage INTEGER :: kl, ku, rank INTEGER :: mrows, ncols INTEGER :: nterms, kmat INTEGER, DIMENSION(:), POINTER :: piv => null() DOUBLE PRECISION, DIMENSION(:,:), POINTER :: val => null() END TYPE gbmat ! TYPE gemat ! Lapack General DENSE matrix storage INTEGER :: rank INTEGER :: mrows, ncols INTEGER :: nterms, kmat INTEGER, DIMENSION(:), POINTER :: piv => null() DOUBLE PRECISION, DIMENSION(:,:), POINTER :: val => null() END TYPE gemat ! TYPE pbmat ! Lapack Pack Band matrix storage (super-diagonals) INTEGER :: ku, rank INTEGER :: nterms, kmat DOUBLE PRECISION, DIMENSION(:,:), POINTER :: val => null() END TYPE pbmat ! TYPE zgbmat ! Lapack General Band matrix storage INTEGER :: kl, ku, rank INTEGER :: mrows, ncols INTEGER :: nterms, kmat INTEGER, DIMENSION(:), POINTER :: piv => null() DOUBLE COMPLEX, DIMENSION(:,:), POINTER :: val => NULL() END TYPE zgbmat ! TYPE zgemat ! Lapack General DENSE matrix storage INTEGER :: rank INTEGER :: mrows, ncols INTEGER :: nterms, kmat INTEGER, DIMENSION(:), POINTER :: piv => null() DOUBLE COMPLEX, DIMENSION(:,:), POINTER :: val => null() END TYPE zgemat ! TYPE zpbmat ! Lapack Pack Band matrix storage (super-diagonals) INTEGER :: ku, rank INTEGER :: nterms, kmat DOUBLE COMPLEX, DIMENSION(:,:), POINTER :: val => null() END TYPE zpbmat ! TYPE periodic_mat TYPE(gbmat) :: mat INTEGER :: nterms DOUBLE PRECISION, DIMENSION(:,:), POINTER :: & & matu => null(), & & matvt => null() END TYPE periodic_mat ! TYPE zperiodic_mat TYPE(zgbmat) :: mat INTEGER :: nterms DOUBLE COMPLEX, DIMENSION(:,:), POINTER :: & & matu => null(), & & matvt => null() END TYPE zperiodic_mat ! !-------------------------------------------------------------------------------- INTERFACE init MODULE PROCEDURE init_gb, init_ge, init_pb, & & init_zgb, init_zge, init_zpb, & & init_periodic, init_zperiodic END INTERFACE INTERFACE getvalp MODULE PROCEDURE getvalp_gb, getvalp_ge, getvalp_pb, & & getvalp_zgb, getvalp_zge, getvalp_zpb END INTERFACE INTERFACE mcopy MODULE PROCEDURE mcopy_gb, mcopy_ge, mcopy_pb, & & mcopy_zgb, mcopy_zge, mcopy_zpb, & & mcopy_periodic, mcopy_zperiodic END INTERFACE INTERFACE maddto MODULE PROCEDURE maddto_gb, maddto_ge, maddto_pb, & & maddto_zgb, maddto_zge, maddto_zpb, & & maddto_periodic, maddto_zperiodic END INTERFACE INTERFACE destroy MODULE PROCEDURE destroy_gb, destroy_ge, destroy_pb, & & destroy_zgb, destroy_zge, destroy_zpb, & & destroy_periodic, destroy_zperiodic END INTERFACE INTERFACE updtmat MODULE PROCEDURE updt_gb, updt_ge, updt_pb, & & updt_zgb, updt_zpb, & & updt_periodic, updt_zperiodic END INTERFACE INTERFACE getele MODULE PROCEDURE getele_gb, getele_pb, & & getele_zgb, getele_zpb, & & getele_periodic, getele_zperiodic END INTERFACE INTERFACE putele MODULE PROCEDURE putele_gb, putele_pb, & & putele_zgb, putele_zpb, & & putele_periodic, putele_zperiodic END INTERFACE INTERFACE getcol MODULE PROCEDURE getcol_gb, getcol_pb, & & getcol_zgb, getcol_zpb, & & getcol_periodic, getcol_zperiodic END INTERFACE INTERFACE getrow MODULE PROCEDURE getrow_gb, getrow_ge, getrow_pb, & & getrow_zgb, getrow_zpb, & & getrow_periodic, getrow_zperiodic END INTERFACE INTERFACE putcol MODULE PROCEDURE putcol_gb, putcol_ge, putcol_pb, & & putcol_zgb, putcol_zpb, & & putcol_periodic, putcol_zperiodic END INTERFACE INTERFACE putrow MODULE PROCEDURE putrow_gb, putrow_ge, putrow_pb, & & putrow_zgb, putrow_zpb, & & putrow_periodic, putrow_zperiodic END INTERFACE INTERFACE factor MODULE PROCEDURE factor_gb, factor_ge, factor_pb, & & factor_zgb, factor_zge, factor_zpb, & & factor_periodic, factor_zperiodic END INTERFACE INTERFACE bsolve MODULE PROCEDURE bsolve_gb1, bsolve_gbn, bsolve_ge1, bsolve_gen, & & bsolve_pb1, bsolve_pbn, & & bsolve_periodic1, bsolve_periodicn, & & bsolve_zperiodic1, bsolve_zperiodicn, & & bsolve_zgb1, bsolve_zgbn, bsolve_zge1, bsolve_zgen, & & bsolve_zpb1, bsolve_zpbn END INTERFACE INTERFACE vmx MODULE PROCEDURE vmx_gb, vmx_gbn, vmx_pb, vmx_pbn, & & vmx_zgb, vmx_zgbn, vmx_zpb, vmx_zpbn, & & vmx_ge, vmx_gen, vmx_zge, vmx_zgen, & & vmx_periodic, vmx_zperiodic END INTERFACE INTERFACE determinant MODULE PROCEDURE determinant_ge, determinant_gb, determinant_pb, & & determinant_zge, determinant_zgb, determinant_zpb END INTERFACE INTERFACE putmat MODULE PROCEDURE putmat_gb END INTERFACE INTERFACE getmat MODULE PROCEDURE getmat_gb END INTERFACE INTERFACE kron MODULE PROCEDURE kron_ge END INTERFACE kron ! CONTAINS !=========================================================================== SUBROUTINE init_ge(n, nterms, mat, kmat, mrows) ! ! Initialize Lapack General Dense matrice ! INTEGER, INTENT(in) :: n, nterms INTEGER, OPTIONAL :: kmat INTEGER, OPTIONAL :: mrows TYPE(gemat) :: mat ! mat%ncols = n mat%mrows = n IF(PRESENT(mrows)) THEN mat%mrows = mrows END IF mat%rank = n ! Warning: ok if square matrix mat%nterms = nterms IF(PRESENT(kmat)) mat%kmat = kmat IF( ASSOCIATED(mat%val)) DEALLOCATE(mat%val) IF( ASSOCIATED(mat%piv)) DEALLOCATE(mat%piv) ALLOCATE(mat%val(mat%mrows,mat%ncols)) ALLOCATE(mat%piv(MIN(mat%mrows,mat%ncols))) mat%val = 0.0d0 mat%piv = 0 END SUBROUTINE init_ge !=========================================================================== SUBROUTINE init_gb(kl, ku, n, nterms, mat, kmat, mrows) ! ! Initialize Lapack General Banded matrice ! INTEGER, INTENT(in) :: kl, ku, n, nterms INTEGER, OPTIONAL :: kmat INTEGER, OPTIONAL :: mrows TYPE(gbmat) :: mat INTEGER :: lda ! mat%kl = kl mat%ku = ku mat%ncols = n mat%mrows = n IF(PRESENT(mrows)) THEN mat%mrows = mrows END IF mat%rank = n ! Warning: ok if square matrix mat%nterms = nterms IF(PRESENT(kmat)) mat%kmat = kmat lda = 2*kl + ku + 1 IF( ASSOCIATED(mat%val)) DEALLOCATE(mat%val) IF( ASSOCIATED(mat%piv)) DEALLOCATE(mat%piv) ALLOCATE(mat%val(lda,n)) ALLOCATE(mat%piv(n)) mat%val = 0.0d0 mat%piv = 0 END SUBROUTINE init_gb !=========================================================================== SUBROUTINE init_periodic(kl, ku, n, nterms, mat, kmat) ! ! Initialize Lapack Periodic General Banded matrice ! INTEGER, INTENT(in) :: kl, ku, n, nterms INTEGER, OPTIONAL :: kmat TYPE(periodic_mat) :: mat INTEGER :: i,j DOUBLE PRECISION, PARAMETER :: zero=0.0d0, one=1.0d0 ! ! In band matrix matp%mat is a GB matrix IF( PRESENT(kmat)) THEN CALL init(kl, ku, n, nterms, mat%mat, kmat) ELSE CALL init(kl, ku, n, nterms, mat%mat) END IF mat%nterms = nterms ! ! Off band matrices IF( ASSOCIATED(mat%matu)) DEALLOCATE(mat%matu) IF( ASSOCIATED(mat%matvt)) DEALLOCATE(mat%matvt) ALLOCATE(mat%matu(n, kl+ku)) ALLOCATE(mat%matvt(kl+ku,n)) ! mat%matu = zero mat%matvt = zero ! kl=3, ku=2 DO j=1,kl ! [ 1 0 0 . . ] mat%matu(j,j) = one ! [ 0 1 0 . . ] END DO ! [ 0 0 1 . . ] ! ! [ 0 . . . . ] DO j=1,ku ! [ . . . . . ] i=n-ku+j ! [ . . . 1 0 ] mat%matu(i,ku+j) = one ! [ . . . 0 1 ] END DO END SUBROUTINE init_periodic !=========================================================================== SUBROUTINE init_zperiodic(kl, ku, n, nterms, mat, kmat) ! ! Initialize Lapack Periodic General Banded matrice ! INTEGER, INTENT(in) :: kl, ku, n, nterms INTEGER, OPTIONAL :: kmat TYPE(zperiodic_mat) :: mat INTEGER :: i,j DOUBLE PRECISION, PARAMETER :: zero=0.0d0, one=1.0d0 ! ! In band matrix matp%mat is a GB matrix IF( PRESENT(kmat)) THEN CALL init(kl, ku, n, nterms, mat%mat, kmat) ELSE CALL init(kl, ku, n, nterms, mat%mat) END IF mat%nterms = nterms ! ! Off band matrices IF( ASSOCIATED(mat%matu)) DEALLOCATE(mat%matu) IF( ASSOCIATED(mat%matvt)) DEALLOCATE(mat%matvt) ALLOCATE(mat%matu(n, kl+ku)) ALLOCATE(mat%matvt(kl+ku,n)) ! mat%matu = zero mat%matvt = zero ! kl=3, ku=2 DO j=1,kl ! [ 1 0 0 . . ] mat%matu(j,j) = one ! [ 0 1 0 . . ] END DO ! [ 0 0 1 . . ] ! ! [ 0 . . . . ] DO j=1,ku ! [ . . . . . ] i=n-ku+j ! [ . . . 1 0 ] mat%matu(i,ku+j) = one ! [ . . . 0 1 ] END DO END SUBROUTINE init_zperiodic !=========================================================================== SUBROUTINE init_pb(ku, n, nterms, mat, kmat) ! ! Initialize Lapack Packed Banded matrice ! INTEGER, INTENT(in) :: ku, n, nterms INTEGER, OPTIONAL :: kmat TYPE(pbmat) :: mat INTEGER :: lda ! mat%ku = ku mat%rank = n mat%nterms = nterms IF(PRESENT(kmat)) mat%kmat = kmat lda = ku + 1 IF( ASSOCIATED(mat%val)) DEALLOCATE(mat%val) ALLOCATE(mat%val(lda,n)) mat%val = 0.0d0 END SUBROUTINE init_pb !=========================================================================== SUBROUTINE init_zge(n, nterms, mat, kmat, mrows) ! ! Initialize Lapack General Dense matrice ! INTEGER, INTENT(in) :: n, nterms INTEGER, OPTIONAL :: kmat INTEGER, OPTIONAL :: mrows TYPE(zgemat) :: mat ! mat%ncols = n mat%mrows = n IF(PRESENT(mrows)) THEN mat%mrows = mrows END IF mat%rank = n mat%nterms = nterms IF(PRESENT(kmat)) mat%kmat = kmat IF( ASSOCIATED(mat%val)) DEALLOCATE(mat%val) IF( ASSOCIATED(mat%piv)) DEALLOCATE(mat%piv) ALLOCATE(mat%val(mat%mrows,mat%ncols)) ALLOCATE(mat%piv(MIN(mat%mrows,mat%ncols))) mat%val = 0.0d0 mat%piv = 0 END SUBROUTINE init_zge !=========================================================================== SUBROUTINE init_zgb(kl, ku, n, nterms, mat, kmat, mrows) ! ! Initialize Lapack General Banded matrice ! INTEGER, INTENT(in) :: kl, ku, n, nterms INTEGER, OPTIONAL :: kmat INTEGER, OPTIONAL :: mrows TYPE(zgbmat) :: mat INTEGER :: lda ! mat%kl = kl mat%ku = ku mat%ncols = n mat%mrows = n IF(PRESENT(mrows)) THEN mat%mrows = mrows END IF mat%rank = n ! Warning: ok if square matrix mat%nterms = nterms IF(PRESENT(kmat)) mat%kmat = kmat lda = 2*kl + ku + 1 IF( ASSOCIATED(mat%val)) DEALLOCATE(mat%val) IF( ASSOCIATED(mat%piv)) DEALLOCATE(mat%piv) ALLOCATE(mat%val(lda,n)) ALLOCATE(mat%piv(n)) mat%val = 0.0d0 mat%piv = 0 END SUBROUTINE init_zgb !=========================================================================== SUBROUTINE init_zpb(ku, n, nterms, mat, kmat) ! ! Initialize Lapack Packed Banded matrice ! INTEGER, INTENT(in) :: ku, n, nterms INTEGER, OPTIONAL :: kmat TYPE(zpbmat) :: mat INTEGER :: lda ! mat%ku = ku mat%rank = n mat%nterms = nterms IF(PRESENT(kmat)) mat%kmat = kmat lda = ku + 1 IF( ASSOCIATED(mat%val)) DEALLOCATE(mat%val) ALLOCATE(mat%val(lda,n)) mat%val = 0.0d0 END SUBROUTINE init_zpb !=========================================================================== SUBROUTINE mcopy_ge(mata, matb) ! ! Matrix copy: B = A ! TYPE(gemat) :: mata, matb ! matb%rank = mata%rank matb%mrows = mata%mrows matb%ncols = mata%ncols matb%nterms = mata%nterms matb%kmat = mata%kmat IF( ASSOCIATED(matb%val)) DEALLOCATE(matb%val) IF( ASSOCIATED(matb%piv)) DEALLOCATE(matb%piv) ALLOCATE(matb%val(matb%mrows,matb%ncols)) ALLOCATE(matb%piv(MIN(matb%mrows,matb%ncols))) matb%val = mata%val matb%piv = mata%piv END SUBROUTINE mcopy_ge !=========================================================================== SUBROUTINE mcopy_gb(mata, matb) ! ! Matrix copy: B = A ! TYPE(gbmat) :: mata, matb INTEGER :: n, lda ! n = mata%rank matb%kl = mata%kl matb%ku = mata%ku matb%rank = mata%rank matb%mrows = mata%mrows matb%ncols = mata%ncols matb%nterms = mata%nterms matb%kmat = mata%kmat lda = 2*mata%kl + mata%ku + 1 IF( ASSOCIATED(matb%val)) DEALLOCATE(matb%val) IF( ASSOCIATED(matb%piv)) DEALLOCATE(matb%piv) ALLOCATE(matb%val(lda,n)) ALLOCATE(matb%piv(n)) matb%val = mata%val matb%piv = mata%piv END SUBROUTINE mcopy_gb !=========================================================================== SUBROUTINE mcopy_periodic(mata, matb) ! ! Matrix copy: B = A ! TYPE(periodic_mat) :: mata, matb INTEGER :: n, kl, ku ! kl = mata%mat%kl ku = mata%mat%ku n = mata%mat%rank ! CALL mcopy(mata%mat, matb%mat) IF( ASSOCIATED(matb%matu)) DEALLOCATE(matb%matu) IF( ASSOCIATED(matb%matvt)) DEALLOCATE(matb%matvt) ALLOCATE(matb%matu(n,kl+ku)) ALLOCATE(matb%matvt(kl+ku,n)) matb%matu = mata%matu matb%matvt = mata%matvt END SUBROUTINE mcopy_periodic !=========================================================================== SUBROUTINE mcopy_zperiodic(mata, matb) ! ! Matrix copy: B = A ! TYPE(zperiodic_mat) :: mata, matb INTEGER :: n, kl, ku ! kl = mata%mat%kl ku = mata%mat%ku n = mata%mat%rank ! CALL mcopy(mata%mat, matb%mat) IF( ASSOCIATED(matb%matu)) DEALLOCATE(matb%matu) IF( ASSOCIATED(matb%matvt)) DEALLOCATE(matb%matvt) ALLOCATE(matb%matu(n,kl+ku)) ALLOCATE(matb%matvt(kl+ku,n)) matb%matu = mata%matu matb%matvt = mata%matvt END SUBROUTINE mcopy_zperiodic !=========================================================================== SUBROUTINE mcopy_pb(mata, matb) ! ! Matrix copy: B = A ! TYPE(pbmat) :: mata, matb INTEGER :: n, lda ! n = mata%rank matb%ku = mata%ku matb%rank = mata%rank matb%nterms = mata%nterms lda = mata%ku + 1 IF( ASSOCIATED(matb%val)) DEALLOCATE(matb%val) ALLOCATE(matb%val(lda,n)) matb%val = mata%val END SUBROUTINE mcopy_pb !=========================================================================== SUBROUTINE mcopy_zge(mata, matb) ! ! Matrix copy: B = A ! TYPE(zgemat) :: mata, matb INTEGER :: n ! n = mata%rank matb%rank = n IF( ASSOCIATED(matb%val)) DEALLOCATE(matb%val) IF( ASSOCIATED(matb%piv)) DEALLOCATE(matb%piv) ALLOCATE(matb%val(n,n)) ALLOCATE(matb%piv(n)) matb%val = mata%val matb%piv = mata%piv END SUBROUTINE mcopy_zge !=========================================================================== SUBROUTINE mcopy_zgb(mata, matb) ! ! Matrix copy: B = A ! TYPE(zgbmat) :: mata, matb INTEGER :: n, lda ! n = mata%rank matb%kl = mata%kl matb%ku = mata%ku matb%rank = mata%rank matb%nterms = mata%nterms lda = 2*mata%kl + mata%ku + 1 IF( ASSOCIATED(matb%val)) DEALLOCATE(matb%val) IF( ASSOCIATED(matb%piv)) DEALLOCATE(matb%piv) ALLOCATE(matb%val(lda,n)) ALLOCATE(matb%piv(n)) matb%val = mata%val matb%piv = mata%piv END SUBROUTINE mcopy_zgb !=========================================================================== SUBROUTINE mcopy_zpb(mata, matb) ! ! Matrix copy: B = A ! TYPE(zpbmat) :: mata, matb INTEGER :: n, lda ! n = mata%rank matb%ku = mata%ku matb%rank = mata%rank matb%nterms = mata%nterms lda = mata%ku + 1 IF( ASSOCIATED(matb%val)) DEALLOCATE(matb%val) ALLOCATE(matb%val(lda,n)) matb%val = mata%val END SUBROUTINE mcopy_zpb !=========================================================================== SUBROUTINE maddto_ge(mata, alpha, matb) ! ! A <- A + alpha*B ! TYPE(gemat) :: mata, matb DOUBLE PRECISION :: alpha ! mata%val = mata%val + alpha*matb%val END SUBROUTINE maddto_ge !=========================================================================== SUBROUTINE maddto_gb(mata, alpha, matb) ! ! A <- A + alpha*B ! TYPE(gbmat) :: mata, matb DOUBLE PRECISION :: alpha ! mata%val = mata%val + alpha*matb%val END SUBROUTINE maddto_gb !=========================================================================== SUBROUTINE maddto_periodic(mata, alpha, matb) ! ! A <- A + alpha*B ! TYPE(periodic_mat) :: mata, matb DOUBLE PRECISION :: alpha ! mata%mat%val = mata%mat%val + alpha*matb%mat%val mata%matvt = mata%matvt + alpha*matb%matvt END SUBROUTINE maddto_periodic !=========================================================================== SUBROUTINE maddto_zperiodic(mata, alpha, matb) ! ! A <- A + alpha*B ! TYPE(zperiodic_mat) :: mata, matb DOUBLE COMPLEX :: alpha ! mata%mat%val = mata%mat%val + alpha*matb%mat%val mata%matvt = mata%matvt + alpha*matb%matvt END SUBROUTINE maddto_zperiodic !=========================================================================== SUBROUTINE maddto_pb(mata, alpha, matb) ! ! A <- A + alpha*B ! TYPE(pbmat) :: mata, matb DOUBLE PRECISION :: alpha ! mata%val = mata%val + alpha*matb%val END SUBROUTINE maddto_pb !=========================================================================== SUBROUTINE maddto_zge(mata, alpha, matb) ! ! A <- A + alpha*B ! TYPE(zgemat) :: mata, matb DOUBLE COMPLEX :: alpha ! mata%val = mata%val + alpha*matb%val END SUBROUTINE maddto_zge !=========================================================================== SUBROUTINE maddto_zgb(mata, alpha, matb) ! ! A <- A + alpha*B ! TYPE(zgbmat) :: mata, matb DOUBLE COMPLEX :: alpha ! mata%val = mata%val + alpha*matb%val END SUBROUTINE maddto_zgb !=========================================================================== SUBROUTINE maddto_zpb(mata, alpha, matb) ! ! A <- A + alpha*B ! TYPE(zpbmat) :: mata, matb DOUBLE COMPLEX :: alpha ! mata%val = mata%val + alpha*matb%val END SUBROUTINE maddto_zpb !=========================================================================== SUBROUTINE getvalp_ge(mat, p) ! ! Get pointer to matrix coefficients ! TYPE(gemat) :: mat DOUBLE PRECISION, DIMENSION(:,:), POINTER :: p ! p => mat%val END SUBROUTINE getvalp_ge !=========================================================================== SUBROUTINE getvalp_gb(mat, p) ! ! Get pointer to matrix coefficients ! TYPE(gbmat) :: mat DOUBLE PRECISION, DIMENSION(:,:), POINTER :: p ! p => mat%val END SUBROUTINE getvalp_gb !=========================================================================== SUBROUTINE getvalp_pb(mat, p) ! ! Get pointer to matrix coefficients ! TYPE(pbmat) :: mat DOUBLE PRECISION, DIMENSION(:,:), POINTER :: p ! p => mat%val END SUBROUTINE getvalp_pb !=========================================================================== SUBROUTINE getvalp_zge(mat, p) ! ! Get pointer to matrix coefficients ! TYPE(zgemat) :: mat DOUBLE COMPLEX, DIMENSION(:,:), POINTER :: p ! p => mat%val END SUBROUTINE getvalp_zge !=========================================================================== SUBROUTINE getvalp_zgb(mat, p) ! ! Get pointer to matrix coefficients ! TYPE(zgbmat) :: mat DOUBLE COMPLEX, DIMENSION(:,:), POINTER :: p ! p => mat%val END SUBROUTINE getvalp_zgb !=========================================================================== SUBROUTINE getvalp_zpb(mat, p) ! ! Get pointer to matrix coefficients ! TYPE(zpbmat) :: mat DOUBLE COMPLEX, DIMENSION(:,:), POINTER :: p ! p => mat%val END SUBROUTINE getvalp_zpb !=========================================================================== SUBROUTINE destroy_gb(mat) ! ! Deallocate pointers in mat ! TYPE(gbmat) :: mat IF( ASSOCIATED(mat%val)) DEALLOCATE(mat%val) IF( ASSOCIATED(mat%piv)) DEALLOCATE(mat%piv) END SUBROUTINE destroy_gb !=========================================================================== SUBROUTINE destroy_ge(mat) ! ! Deallocate pointers in mat ! TYPE(gemat) :: mat IF( ASSOCIATED(mat%val)) DEALLOCATE(mat%val) IF( ASSOCIATED(mat%piv)) DEALLOCATE(mat%piv) END SUBROUTINE destroy_ge !=========================================================================== SUBROUTINE destroy_pb(mat) ! ! Deallocate pointers in mat ! TYPE(pbmat) :: mat IF( ASSOCIATED(mat%val)) DEALLOCATE(mat%val) END SUBROUTINE destroy_pb !=========================================================================== SUBROUTINE destroy_zgb(mat) ! ! Deallocate pointers in mat ! TYPE(zgbmat) :: mat IF( ASSOCIATED(mat%val)) DEALLOCATE(mat%val) IF( ASSOCIATED(mat%piv)) DEALLOCATE(mat%piv) END SUBROUTINE destroy_zgb !=========================================================================== SUBROUTINE destroy_zge(mat) ! ! Deallocate pointers in mat ! TYPE(zgemat) :: mat IF( ASSOCIATED(mat%val)) DEALLOCATE(mat%val) IF( ASSOCIATED(mat%piv)) DEALLOCATE(mat%piv) END SUBROUTINE destroy_zge !=========================================================================== SUBROUTINE destroy_zpb(mat) ! ! Deallocate pointers in mat ! TYPE(zpbmat) :: mat IF( ASSOCIATED(mat%val)) DEALLOCATE(mat%val) END SUBROUTINE destroy_zpb !=========================================================================== SUBROUTINE destroy_periodic(mat) ! ! Deallocate pointers in mat ! TYPE(periodic_mat) :: mat IF( ASSOCIATED(mat%matu)) DEALLOCATE(mat%matu) IF( ASSOCIATED(mat%matvt)) DEALLOCATE(mat%matvt) CALL destroy(mat%mat) END SUBROUTINE destroy_periodic !=========================================================================== SUBROUTINE destroy_zperiodic(mat) ! ! Deallocate pointers in mat ! TYPE(zperiodic_mat) :: mat IF( ASSOCIATED(mat%matu)) DEALLOCATE(mat%matu) IF( ASSOCIATED(mat%matvt)) DEALLOCATE(mat%matvt) CALL destroy(mat%mat) END SUBROUTINE destroy_zperiodic !=========================================================================== SUBROUTINE updt_gb(mat, i, j, val) ! ! Update element Aij into banded matrix ! TYPE(gbmat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i, j DOUBLE PRECISION, INTENT(in) :: val INTEGER :: lda, n, ib ! lda = SIZE(mat%val, 1) n = mat%rank ib = mat%kl + mat%ku + i - j + 1 IF( (ib .GT. lda) .OR. (j .GT. n) .OR. (j .LT. 1)) THEN WRITE(*,*) 'UPDT: i, j out of range ', i, j, lda, n STOP '*** Abnormal EXIT in MODULE matrix ***' END IF mat%val(ib,j) = mat%val(ib,j) + val END SUBROUTINE updt_gb !=========================================================================== SUBROUTINE updt_ge(mat, i, j, val) ! ! Update element Aij into banded matrix ! TYPE(gemat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i, j DOUBLE PRECISION, INTENT(in) :: val ! IF( (i .GT. mat%mrows) .OR. (j .GT. mat%ncols) .OR. (j .LT. 1) .OR. (i.LT.1)) THEN WRITE(*,*) 'UPDT: i, j out of range ', i, j, mat%mrows, mat%ncols STOP '*** Abnormal EXIT in MODULE matrix ***' END IF mat%val(i,j) = mat%val(i,j) + val END SUBROUTINE updt_ge !=========================================================================== SUBROUTINE updt_periodic(mat, i, j, val) ! ! Update element Aij into periodic banded matrix ! TYPE(periodic_mat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i, j DOUBLE PRECISION, INTENT(in) :: val INTEGER :: n, kl, ku ! n = mat%mat%rank kl = mat%mat%kl ku = mat%mat%ku ! IF( i.LE.kl .AND. j.GE.n-kl+1 ) THEN ! ! Put into C(1:kl, 1:kl) = V^T(1:kl, n-kl+1:n) mat%matvt(i,j) = mat%matvt(i,j) + val ! ELSE IF( i.GE.n-ku+1 .AND. j.LE.ku ) THEN ! ! Put into D(1:ku,1:ku) = V^T(kl+1:kl+ku, 1:ku) mat%matvt(i-n+kl+ku,j) = mat%matvt(i-n+kl+ku,j) + val ! ELSE ! ! Put into the banded matrix CALL updtmat(mat%mat, i, j, val) ! END IF END SUBROUTINE updt_periodic !=========================================================================== SUBROUTINE updt_zperiodic(mat, i, j, val) ! ! Update element Aij into periodic banded matrix ! TYPE(zperiodic_mat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i, j DOUBLE COMPLEX, INTENT(in) :: val INTEGER :: n, kl, ku ! n = mat%mat%rank kl = mat%mat%kl ku = mat%mat%ku ! IF( i.LE.kl .AND. j.GE.n-kl+1 ) THEN ! ! Put into C(1:kl, 1:kl) = V^T(1:kl, n-kl+1:n) mat%matvt(i,j) = mat%matvt(i,j) + val ! ELSE IF( i.GE.n-ku+1 .AND. j.LE.ku ) THEN ! ! Put into D(1:ku,1:ku) = V^T(kl+1:kl+ku, 1:ku) mat%matvt(i-n+kl+ku,j) = mat%matvt(i-n+kl+ku,j) + val ! ELSE ! ! Put into the banded matrix CALL updtmat(mat%mat, i, j, val) ! END IF END SUBROUTINE updt_zperiodic !=========================================================================== SUBROUTINE updt_pb(mat, i, j, val) ! ! Update element Aij into banded matrix ! TYPE(pbmat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i, j DOUBLE PRECISION, INTENT(in) :: val INTEGER :: lda, n, ib ! lda = SIZE(mat%val, 1) n = mat%rank IF( i .LE. j ) THEN ib = mat%ku + i - j + 1 IF( (ib .GT. lda) .OR. (j .GT. n) .OR. (j .LT. 1)) THEN WRITE(*,*) 'UPDT: i, j out of range ', i, j, lda, n STOP '*** Abnormal EXIT in MODULE matrix ***' END IF mat%val(ib,j) = mat%val(ib,j) + val END IF END SUBROUTINE updt_pb !=========================================================================== SUBROUTINE updt_zgb(mat, i, j, val) ! ! Update element Aij into banded matrix ! TYPE(zgbmat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i, j DOUBLE COMPLEX, INTENT(in) :: val INTEGER :: lda, n, ib ! lda = SIZE(mat%val, 1) n = mat%rank ib = mat%kl + mat%ku + i - j + 1 IF( (ib .GT. lda) .OR. (j .GT. n) .OR. (j .LT. 1)) THEN WRITE(*,*) 'UPDT: i, j out of range ', i, j, lda, n STOP '*** Abnormal EXIT in MODULE matrix ***' END IF mat%val(ib,j) = mat%val(ib,j) + val END SUBROUTINE updt_zgb !=========================================================================== SUBROUTINE updt_zpb(mat, i, j, val) ! ! Update element Aij into banded matrix ! TYPE(zpbmat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i, j DOUBLE COMPLEX, INTENT(in) :: val INTEGER :: lda, n, ib ! lda = SIZE(mat%val, 1) n = mat%rank IF( i .LE. j ) THEN ib = mat%ku + i - j + 1 IF( (ib .GT. lda) .OR. (j .GT. n) .OR. (j .LT. 1)) THEN WRITE(*,*) 'UPDT: i, j out of range ', i, j, lda, n STOP '*** Abnormal EXIT in MODULE matrix ***' END IF mat%val(ib,j) = mat%val(ib,j) + val END IF END SUBROUTINE updt_zpb !=========================================================================== SUBROUTINE getele_gb(mat, i, j, val) ! ! Get element (i,j) of matrix ! TYPE(gbmat), INTENT(in) :: mat DOUBLE PRECISION, INTENT (OUT) :: val INTEGER, INTENT (IN) :: i, j INTEGER :: lda, n, ib ! lda = SIZE(mat%val, 1) n = mat%rank ib = mat%kl + mat%ku + i - j + 1 IF( (ib .GT. lda) .OR. (j .GT. n)) THEN WRITE(*,*) 'GETELE: i, j out of range ', i, j STOP '*** Abnormal EXIT in MODULE matrix***' END IF val = mat%val(ib,j) END SUBROUTINE getele_gb !=========================================================================== SUBROUTINE getele_periodic(mat, i, j, val) ! ! Get element Aij of periodic banded matrix ! TYPE(periodic_mat), INTENT(in) :: mat INTEGER, INTENT(in) :: i, j DOUBLE PRECISION, INTENT(out) :: val INTEGER :: n, kl, ku ! n = mat%mat%rank kl = mat%mat%kl ku = mat%mat%ku ! IF( i.LE.kl .AND. j.GE.n-kl+1 ) THEN ! ! Put into C(1:kl, 1:kl) = V^T(1:kl, n-kl+1:n) val =mat%matvt(i,j) ! ELSE IF( i.GE.n-ku+1 .AND. j.LE.ku ) THEN ! ! Put into D(1:ku,1:ku) = V^T(kl+1:kl+ku, 1:ku) val = mat%matvt(i-n+kl+ku,j) ! ELSE ! ! Put into the banded matrix CALL getele(mat%mat, i, j, val) ! END IF END SUBROUTINE getele_periodic !=========================================================================== SUBROUTINE getele_zperiodic(mat, i, j, val) ! ! Get element Aij of periodic banded matrix ! TYPE(zperiodic_mat), INTENT(in) :: mat INTEGER, INTENT(in) :: i, j DOUBLE COMPLEX, INTENT(out) :: val INTEGER :: n, kl, ku ! n = mat%mat%rank kl = mat%mat%kl ku = mat%mat%ku ! IF( i.LE.kl .AND. j.GE.n-kl+1 ) THEN ! ! Put into C(1:kl, 1:kl) = V^T(1:kl, n-kl+1:n) val =mat%matvt(i,j) ! ELSE IF( i.GE.n-ku+1 .AND. j.LE.ku ) THEN ! ! Put into D(1:ku,1:ku) = V^T(kl+1:kl+ku, 1:ku) val = mat%matvt(i-n+kl+ku,j) ! ELSE ! ! Put into the banded matrix CALL getele(mat%mat, i, j, val) ! END IF END SUBROUTINE getele_zperiodic !=========================================================================== SUBROUTINE getele_pb(mat, i, j, val) ! ! Get element (i,j) of matrix ! TYPE(pbmat), INTENT(in) :: mat DOUBLE PRECISION, INTENT (OUT) :: val INTEGER, INTENT (IN) :: i, j INTEGER :: lda, n, ib, irow, jcol ! lda = SIZE(mat%val, 1) n = mat%rank IF( i .LE. j ) THEN ! Upper triangular matrix irow = i; jcol = j ELSE ! Lower triangular matrix irow = j; jcol = i END IF ib = mat%ku + irow - jcol + 1 IF( (ib .GT. lda) .OR. (jcol .GT. n)) THEN WRITE(*,*) 'GETELE: i, j out of range ', i, j STOP '*** Abnormal EXIT in MODULE matrix***' END IF val = mat%val(ib,jcol) END SUBROUTINE getele_pb !=========================================================================== SUBROUTINE getele_zgb(mat, i, j, val) ! ! Get element (i,j) of matrix ! TYPE(zgbmat), INTENT(in) :: mat DOUBLE COMPLEX, INTENT (OUT) :: val INTEGER, INTENT (IN) :: i, j INTEGER :: lda, n, ib ! lda = SIZE(mat%val, 1) n = mat%rank ib = mat%kl + mat%ku + i - j + 1 IF( (ib .GT. lda) .OR. (j .GT. n)) THEN WRITE(*,*) 'GETELE: i, j out of range ', i, j STOP '*** Abnormal EXIT in MODULE matrix***' END IF val = mat%val(ib,j) END SUBROUTINE getele_zgb !=========================================================================== SUBROUTINE getele_zpb(mat, i, j, val) ! ! Get element (i,j) of matrix ! TYPE(zpbmat), INTENT(in) :: mat DOUBLE COMPLEX, INTENT (OUT) :: val INTEGER, INTENT (IN) :: i, j INTEGER :: lda, n, ib, irow, jcol ! lda = SIZE(mat%val, 1) n = mat%rank ! IF( i .LE. j ) THEN ! Upper triangular matrix irow = i; jcol = j ib = mat%ku + irow - jcol + 1 IF( (ib .GT. lda) .OR. (jcol .GT. n)) THEN WRITE(*,*) 'GETELE: i, j out of range ', i, j STOP '*** Abnormal EXIT in MODULE matrix***' END IF val = mat%val(ib,jcol) RETURN ELSE ! Lower triangular matrix irow = j; jcol = i ib = mat%ku + irow - jcol + 1 IF( (ib .GT. lda) .OR. (jcol .GT. n)) THEN WRITE(*,*) 'GETELE: i, j out of range ', i, j STOP '*** Abnormal EXIT in MODULE matrix***' END IF val = CONJG(mat%val(ib,jcol)) END IF END SUBROUTINE getele_zpb !=========================================================================== SUBROUTINE putele_gb(mat, i, j, val) ! ! Put element (i,j) of matrix ! TYPE(gbmat), INTENT(inout) :: mat DOUBLE PRECISION, INTENT (in) :: val INTEGER, INTENT (in) :: i, j INTEGER :: lda, n, ib ! lda = SIZE(mat%val, 1) n = mat%rank ib = mat%kl + mat%ku + i - j + 1 IF( (ib .GT. lda) .OR. (j .GT. n)) THEN WRITE(*,*) 'GETELE: i, j out of range ', i, j STOP '*** Abnormal EXIT in MODULE matrix ***' END IF mat%val(ib,j) = val END SUBROUTINE putele_gb !=========================================================================== SUBROUTINE putele_periodic(mat, i, j, val) ! ! Put element Aij into periodic banded matrix ! TYPE(periodic_mat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i, j DOUBLE PRECISION, INTENT(in) :: val INTEGER :: n, kl, ku ! n = mat%mat%rank kl = mat%mat%kl ku = mat%mat%ku ! IF( i.LE.kl .AND. j.GE.n-kl+1 ) THEN ! ! Put into C(1:kl, 1:kl) = V^T(1:kl, n-kl+1:n) mat%matvt(i,j) = val ! ELSE IF( i.GE.n-ku+1 .AND. j.LE.ku ) THEN ! ! Put into D(1:ku,1:ku) = V^T(kl+1:kl+ku, 1:ku) mat%matvt(i-n+kl+ku,j) = val ! ELSE ! ! Put into the banded matrix CALL putele(mat%mat, i, j, val) ! END IF END SUBROUTINE putele_periodic !=========================================================================== SUBROUTINE putele_zperiodic(mat, i, j, val) ! ! Put element Aij into periodic banded matrix ! TYPE(zperiodic_mat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i, j DOUBLE COMPLEX, INTENT(in) :: val INTEGER :: n, kl, ku ! n = mat%mat%rank kl = mat%mat%kl ku = mat%mat%ku ! IF( i.LE.kl .AND. j.GE.n-kl+1 ) THEN ! ! Put into C(1:kl, 1:kl) = V^T(1:kl, n-kl+1:n) mat%matvt(i,j) = val ! ELSE IF( i.GE.n-ku+1 .AND. j.LE.ku ) THEN ! ! Put into D(1:ku,1:ku) = V^T(kl+1:kl+ku, 1:ku) mat%matvt(i-n+kl+ku,j) = val ! ELSE ! ! Put into the banded matrix CALL putele(mat%mat, i, j, val) ! END IF END SUBROUTINE putele_zperiodic !=========================================================================== SUBROUTINE putele_pb(mat, i, j, val) ! ! Put element (i,j) of matrix ! TYPE(pbmat), INTENT(inout) :: mat DOUBLE PRECISION, INTENT (in) :: val INTEGER, INTENT (IN) :: i, j INTEGER :: lda, n, ib, irow, jcol ! lda = SIZE(mat%val, 1) n = mat%rank IF( i .LE. j ) THEN ! Upper triangular matrix irow = i; jcol = j ELSE ! Lower triangular matrix irow = j; jcol = i END IF ib = mat%ku + irow - jcol + 1 IF( (ib .GT. lda) .OR. (jcol .GT. n)) THEN WRITE(*,*) 'PUTELE: i, j out of range ', i, j STOP '*** Abnormal EXIT in MODULE matrix***' END IF mat%val(ib,jcol) = val END SUBROUTINE putele_pb !=========================================================================== SUBROUTINE putele_zgb(mat, i, j, val) ! ! Put element (i,j) of matrix ! TYPE(zgbmat), INTENT(inout) :: mat DOUBLE COMPLEX, INTENT (in) :: val INTEGER, INTENT (in) :: i, j INTEGER :: lda, n, ib ! lda = SIZE(mat%val, 1) n = mat%rank ib = mat%kl + mat%ku + i - j + 1 IF( (ib .GT. lda) .OR. (j .GT. n)) THEN WRITE(*,*) 'GETELE: i, j out of range ', i, j STOP '*** Abnormal EXIT in MODULE matrix ***' END IF mat%val(ib,j) = val END SUBROUTINE putele_zgb !=========================================================================== SUBROUTINE putele_zpb(mat, i, j, val) ! ! Put element (i,j) of matrix ! TYPE(zpbmat), INTENT(inout) :: mat DOUBLE COMPLEX, INTENT (in) :: val INTEGER, INTENT (IN) :: i, j INTEGER :: lda, n, ib, irow, jcol ! lda = SIZE(mat%val, 1) n = mat%rank IF( i .LE. j ) THEN ! Upper triangular matrix irow = i; jcol = j ib = mat%ku + irow - jcol + 1 IF( (ib .GT. lda) .OR. (jcol .GT. n)) THEN WRITE(*,*) 'GETELE: i, j out of range ', i, j STOP '*** Abnormal EXIT in MODULE matrix***' END IF mat%val(ib,jcol) = val ELSE ! Lower triangular matrix irow = j; jcol = i ib = mat%ku + irow - jcol + 1 IF( (ib .GT. lda) .OR. (jcol .GT. n)) THEN WRITE(*,*) 'PUTELE: i, j out of range ', i, j STOP '*** Abnormal EXIT in MODULE matrix***' END IF mat%val(ib,jcol) = CONJG(val) END IF END SUBROUTINE putele_zpb !=========================================================================== SUBROUTINE getcol_gb(mat, j, arr) ! ! Get a column from matrix ! TYPE(gbmat), INTENT(in) :: mat INTEGER, INTENT(in) :: j DOUBLE PRECISION, DIMENSION(:), INTENT(out) :: arr INTEGER :: m, kl, ku INTEGER :: ibmin, ibmax, imin, imax ! kl = mat%kl ku = mat%ku m = mat%mrows IF( SIZE(arr) .LT. m ) THEN WRITE(*,*) 'GETCOL: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF arr(1:m) = 0.0d0 imin = MAX(1,j-ku) imax = MIN(m, j+kl) ibmin = kl+ku+imin-j+1 ibmax = kl+ku+imax-j+1 arr(imin:imax) = mat%val(ibmin:ibmax,j) END SUBROUTINE getcol_gb !=========================================================================== SUBROUTINE getcol_periodic(mat, j, arr) ! ! Get a column from matrix ! TYPE(periodic_mat), INTENT(in) :: mat INTEGER, INTENT(in) :: j DOUBLE PRECISION, DIMENSION(:), INTENT(out) :: arr INTEGER :: n, kl, ku ! kl = mat%mat%kl ku = mat%mat%ku n = mat%mat%rank ! CALL getcol(mat%mat, j, arr) ! IF( j.GE.n-kl+1 ) THEN arr(1:kl) = mat%matvt(1:kl,j) ELSE IF( j.LE.ku ) THEN arr(n-ku+1:n) = mat%matvt(kl+1:kl+ku,j) END IF END SUBROUTINE getcol_periodic !=========================================================================== SUBROUTINE getcol_zperiodic(mat, j, arr) ! ! Get a column from matrix ! TYPE(zperiodic_mat), INTENT(in) :: mat INTEGER, INTENT(in) :: j DOUBLE COMPLEX, DIMENSION(:), INTENT(out) :: arr INTEGER :: n, kl, ku ! kl = mat%mat%kl ku = mat%mat%ku n = mat%mat%rank ! CALL getcol(mat%mat, j, arr) ! IF( j.GE.n-kl+1 ) THEN arr(1:kl) = mat%matvt(1:kl,j) ELSE IF( j.LE.ku ) THEN arr(n-ku+1:n) = mat%matvt(kl+1:kl+ku,j) END IF END SUBROUTINE getcol_zperiodic !=========================================================================== SUBROUTINE getcol_pb(mat, j, arr) ! ! Get a column from matrix ! TYPE(pbmat), INTENT(in) :: mat INTEGER, INTENT(in) :: j DOUBLE PRECISION, DIMENSION(:), INTENT(out) :: arr INTEGER :: n, ku INTEGER :: i, ib, ibmin, ibmax, imin, imax ! ku = mat%ku n = mat%rank IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'GETCOL: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF arr(1:n) = 0.0d0 ! imin=MAX(1,j-ku); imax=j ! The column in the upper diagonal part ibmin=ku+1+imin-j ; ibmax=ku+1+imax-j arr(imin:imax) = mat%val(ibmin:ibmax,j) ! imin=j+1; imax = MIN(n,j+ku) ! The column in the lower diagonal part DO i=imin,imax ib = ku+1+j-i arr(i) = mat%val(ib,i) END DO END SUBROUTINE getcol_pb !=========================================================================== SUBROUTINE getcol_zgb(mat, j, arr) ! ! Get a column from matrix ! TYPE(zgbmat), INTENT(in) :: mat INTEGER, INTENT(in) :: j DOUBLE COMPLEX, DIMENSION(:), INTENT(out) :: arr INTEGER :: m, kl, ku INTEGER :: ibmin, ibmax, imin, imax ! kl = mat%kl ku = mat%ku m = mat%mrows IF( SIZE(arr) .LT. m ) THEN WRITE(*,*) 'GETCOL: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF arr(1:m) = 0.0d0 imin = MAX(1,j-ku) imax = MIN(m, j+kl) ibmin = kl+ku+imin-j+1 ibmax = kl+ku+imax-j+1 arr(imin:imax) = mat%val(ibmin:ibmax,j) END SUBROUTINE getcol_zgb !=========================================================================== SUBROUTINE getcol_zpb(mat, j, arr) ! ! Get a column from matrix ! TYPE(zpbmat), INTENT(in) :: mat INTEGER, INTENT(in) :: j DOUBLE COMPLEX, DIMENSION(:), INTENT(out) :: arr INTEGER :: n, ku INTEGER :: i, ib, ibmin, ibmax, imin, imax ! ku = mat%ku n = mat%rank IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'GETCOL: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF arr(1:n) = 0.0d0 ! imin=MAX(1,j-ku); imax=j ! The column in the upper diagonal part ibmin=ku+1+imin-j ; ibmax=ku+1+imax-j arr(imin:imax) = mat%val(ibmin:ibmax,j) ! imin=j+1; imax = MIN(n,j+ku) ! The column in the lower diagonal part DO i=imin,imax ib = ku+1+j-i arr(i) = CONJG(mat%val(ib,i)) END DO END SUBROUTINE getcol_zpb !=========================================================================== SUBROUTINE getrow_gb(mat, i, arr) ! ! Get a row from matrix ! TYPE(gbmat), INTENT(in) :: mat INTEGER, INTENT(in) :: i DOUBLE PRECISION, DIMENSION(:), INTENT(out) :: arr INTEGER :: n, kl, ku INTEGER :: j, ib, jmin, jmax ! kl = mat%kl ku = mat%ku n = mat%rank IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'GETROW: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF arr(1:n) = 0.0d0 jmin = MAX(1,i-kl) jmax = MIN(n, i+ku) DO j=jmin,jmax ib = kl+ku+i-j+1 arr(j) = mat%val(ib,j) END DO END SUBROUTINE getrow_gb !=========================================================================== SUBROUTINE getrow_ge(mat, i, arr) ! ! Get a row from matrix ! TYPE(gemat), INTENT(in) :: mat INTEGER, INTENT(in) :: i DOUBLE PRECISION, DIMENSION(:), INTENT(out) :: arr INTEGER :: n ! n = mat%ncols IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'GETROW: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF arr(1:n) = mat%val(i,1:n) END SUBROUTINE getrow_ge !=========================================================================== SUBROUTINE getrow_periodic(mat, i, arr) ! ! Get a row from matrix ! TYPE(periodic_mat), INTENT(in) :: mat INTEGER, INTENT(in) :: i DOUBLE PRECISION, DIMENSION(:), INTENT(out) :: arr INTEGER :: n, kl, ku ! kl = mat%mat%kl ku = mat%mat%ku n = mat%mat%rank ! CALL getrow(mat%mat, i, arr) ! IF( i.LE.kl ) THEN arr(n-kl+1:n) = mat%matvt(i,n-kl+1:n) ELSE IF( i.GE.n-ku+1 ) THEN arr(1:ku) = mat%matvt(i-n+kl+ku,1:ku) END IF END SUBROUTINE getrow_periodic !=========================================================================== SUBROUTINE getrow_zperiodic(mat, i, arr) ! ! Get a row from matrix ! TYPE(zperiodic_mat), INTENT(in) :: mat INTEGER, INTENT(in) :: i DOUBLE COMPLEX, DIMENSION(:), INTENT(out) :: arr INTEGER :: n, kl, ku ! kl = mat%mat%kl ku = mat%mat%ku n = mat%mat%rank ! CALL getrow(mat%mat, i, arr) ! IF( i.LE.kl ) THEN arr(n-kl+1:n) = mat%matvt(i,n-kl+1:n) ELSE IF( i.GE.n-ku+1 ) THEN arr(1:ku) = mat%matvt(i-n+kl+ku,1:ku) END IF END SUBROUTINE getrow_zperiodic !=========================================================================== SUBROUTINE getrow_pb(mat, i, arr) ! ! Get a row from matrix ! TYPE(pbmat), INTENT(in) :: mat INTEGER, INTENT(in) :: i DOUBLE PRECISION, DIMENSION(:), INTENT(out) :: arr INTEGER :: n, ku INTEGER :: j, ib, ibmin, ibmax, jmin, jmax ! ku = mat%ku n = mat%rank IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'GETROW: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF arr(1:n) = 0.0d0 ! jmin=i; jmax=MIN(n,i+ku) DO j=jmin,jmax ib=ku+1+i-j arr(j) = mat%val(ib,j) END DO ! jmin=MAX(1,i-ku); jmax=i-1 DO j=jmin,jmax ib=ku+1+j-i arr(j) = mat%val(ib,i) END DO END SUBROUTINE getrow_pb !=========================================================================== SUBROUTINE getrow_zgb(mat, i, arr) ! ! Get a row from matrix ! TYPE(zgbmat), INTENT(in) :: mat INTEGER, INTENT(in) :: i DOUBLE COMPLEX, DIMENSION(:), INTENT(out) :: arr INTEGER :: n, kl, ku INTEGER :: j, ib, jmin, jmax ! kl = mat%kl ku = mat%ku n = mat%rank IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'GETROW: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF arr(1:n) = 0.0d0 jmin = MAX(1,i-kl) jmax = MIN(n, i+ku) DO j=jmin,jmax ib = kl+ku+i-j+1 arr(j) = mat%val(ib,j) END DO END SUBROUTINE getrow_zgb !=========================================================================== SUBROUTINE getrow_zpb(mat, i, arr) ! ! Get a row from matrix ! TYPE(zpbmat), INTENT(in) :: mat INTEGER, INTENT(in) :: i DOUBLE COMPLEX, DIMENSION(:), INTENT(out) :: arr INTEGER :: n, ku INTEGER :: j, ib, ibmin, ibmax, jmin, jmax ! ku = mat%ku n = mat%rank IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'GETROW: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF arr(1:n) = 0.0d0 ! jmin=i; jmax=MIN(n,i+ku) DO j=jmin,jmax ib=ku+1+i-j arr(j) = mat%val(ib,j) END DO ! jmin=MAX(1,i-ku); jmax=i-1 DO j=jmin,jmax ib=ku+1+j-i arr(j) = CONJG(mat%val(ib,i)) END DO END SUBROUTINE getrow_zpb !=========================================================================== SUBROUTINE putcol_gb(mat, j, arr) ! ! Put a column from matrix ! TYPE(gbmat), INTENT(inout) :: mat INTEGER, INTENT(in) :: j DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: arr INTEGER :: m, kl, ku INTEGER :: ibmin, ibmax, imin, imax ! kl = mat%kl ku = mat%ku m = mat%mrows IF( SIZE(arr) .LT. m ) THEN WRITE(*,*) 'PUTCOL: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF imin = MAX(1,j-ku) imax = MIN(m, j+kl) ibmin = kl+ku+imin-j+1 ibmax = kl+ku+imax-j+1 mat%val(ibmin:ibmax,j) = arr(imin:imax) END SUBROUTINE putcol_gb !=========================================================================== SUBROUTINE putcol_ge(mat, j, arr) ! ! Put a column from matrix ! TYPE(gemat), INTENT(inout) :: mat INTEGER, INTENT(in) :: j DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: arr INTEGER :: m ! m = mat%mrows IF( SIZE(arr) .LT. m ) THEN WRITE(*,*) 'PUTCOL: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF mat%val(:,j) = arr(:) END SUBROUTINE putcol_ge !=========================================================================== SUBROUTINE putrow_periodic(mat, i, arr) ! ! Put a row to matrix ! TYPE(periodic_mat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: arr INTEGER :: n, kl, ku ! kl = mat%mat%kl ku = mat%mat%ku n = mat%mat%rank ! CALL putrow(mat%mat, i, arr) ! IF( i.LE.kl ) THEN mat%matvt(i,n-kl+1:n) = arr(n-kl+1:n) ELSE IF( i.GE.n-ku+1 ) THEN mat%matvt(i-n+kl+ku,1:ku) = arr(1:ku) END IF END SUBROUTINE putrow_periodic !=========================================================================== SUBROUTINE putrow_zperiodic(mat, i, arr) ! ! Put a row to matrix ! TYPE(zperiodic_mat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i DOUBLE COMPLEX, DIMENSION(:), INTENT(in) :: arr INTEGER :: n, kl, ku ! kl = mat%mat%kl ku = mat%mat%ku n = mat%mat%rank ! CALL putrow(mat%mat, i, arr) ! IF( i.LE.kl ) THEN mat%matvt(i,n-kl+1:n) = arr(n-kl+1:n) ELSE IF( i.GE.n-ku+1 ) THEN mat%matvt(i-n+kl+ku,1:ku) = arr(1:ku) END IF END SUBROUTINE putrow_zperiodic !=========================================================================== SUBROUTINE putcol_periodic(mat, j, arr) ! ! Put a column into matrix ! TYPE(periodic_mat), INTENT(inout) :: mat INTEGER, INTENT(in) :: j DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: arr INTEGER :: n, kl, ku ! kl = mat%mat%kl ku = mat%mat%ku n = mat%mat%rank ! CALL putcol(mat%mat, j, arr) ! IF( j.GE.n-kl+1 ) THEN mat%matvt(1:kl,j) = arr(1:kl) ELSE IF( j.LE.ku ) THEN mat%matvt(kl+1:kl+ku,j) = arr(n-ku+1:n) END IF END SUBROUTINE putcol_periodic !=========================================================================== SUBROUTINE putcol_zperiodic(mat, j, arr) ! ! Put a column into matrix ! TYPE(zperiodic_mat), INTENT(inout) :: mat INTEGER, INTENT(in) :: j DOUBLE COMPLEX, DIMENSION(:), INTENT(in) :: arr INTEGER :: n, kl, ku ! kl = mat%mat%kl ku = mat%mat%ku n = mat%mat%rank ! CALL putcol(mat%mat, j, arr) ! IF( j.GE.n-kl+1 ) THEN mat%matvt(1:kl,j) = arr(1:kl) ELSE IF( j.LE.ku ) THEN mat%matvt(kl+1:kl+ku,j) = arr(n-ku+1:n) END IF END SUBROUTINE putcol_zperiodic !=========================================================================== SUBROUTINE putcol_pb(mat, j, arr) ! ! Put a column from matrix ! TYPE(pbmat), INTENT(inout) :: mat INTEGER, INTENT(in) :: j DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: arr INTEGER :: n, ku INTEGER :: i, ib, ibmin, ibmax, imin, imax ! ku = mat%ku n = mat%rank IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'PUTCOL: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF imin = MAX(1,j-ku); imax = j ! The column in the upper diagonal part ibmin = ku+imin-j+1; ibmax = ku+imax-j+1 mat%val(ibmin:ibmax,j) = arr(imin:imax) ! imin=j+1; imax = MIN(n,j+ku) ! The column in the lower diagonal part DO i=imin,imax ib = ku+1+j-i mat%val(ib,i) = arr(i) END DO END SUBROUTINE putcol_pb !=========================================================================== SUBROUTINE putcol_zgb(mat, j, arr) ! ! Put a column from matrix ! TYPE(zgbmat), INTENT(inout) :: mat INTEGER, INTENT(in) :: j DOUBLE COMPLEX, DIMENSION(:), INTENT(in) :: arr INTEGER :: m, kl, ku INTEGER :: ibmin, ibmax, imin, imax ! kl = mat%kl ku = mat%ku m = mat%mrows IF( SIZE(arr) .LT. m ) THEN WRITE(*,*) 'PUTCOL: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF imin = MAX(1,j-ku) imax = MIN(m, j+kl) ibmin = kl+ku+imin-j+1 ibmax = kl+ku+imax-j+1 mat%val(ibmin:ibmax,j) = arr(imin:imax) END SUBROUTINE putcol_zgb !=========================================================================== SUBROUTINE putcol_zpb(mat, j, arr) ! ! Put a column from matrix ! TYPE(zpbmat), INTENT(inout) :: mat INTEGER, INTENT(in) :: j DOUBLE COMPLEX, DIMENSION(:), INTENT(in) :: arr INTEGER :: n, ku, i, ib INTEGER :: ibmin, ibmax, imin, imax ! ku = mat%ku n = mat%rank IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'PUTCOL: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF ! imin=MAX(1,j-ku); imax=j ! The column in the upper diagonal part ibmin=ku+1+imin-j ; ibmax=ku+1+imax-j mat%val(ibmin:ibmax,j) = arr(imin:imax) ! imin=j+1; imax = MIN(n,j+ku) ! The column in the lower diagonal part DO i=imin,imax ib = ku+1+j-i mat%val(ib,i) = CONJG(arr(i)) END DO END SUBROUTINE putcol_zpb !=========================================================================== SUBROUTINE putrow_gb(mat, i, arr) ! ! Put a row from matrix ! TYPE(gbmat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: arr INTEGER :: n, kl, ku INTEGER :: j, ib, jmin, jmax ! kl = mat%kl ku = mat%ku n = mat%rank IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'GETCOL: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF jmin = MAX(1,i-kl) jmax = MIN(n, i+ku) DO j=jmin,jmax ib = kl+ku+i-j+1 mat%val(ib,j) = arr(j) END DO END SUBROUTINE putrow_gb !=========================================================================== SUBROUTINE putrow_ge(mat, i, arr) ! ! Put a row from matrix ! TYPE(gemat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: arr INTEGER :: n, kl, ku INTEGER :: j, ib, jmin, jmax ! n = mat%rank IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'PUTROW: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF mat%val(i,:) = arr(:) END SUBROUTINE putrow_ge !=========================================================================== SUBROUTINE putrow_pb(mat, i, arr) ! ! Put a row from matrix ! TYPE(pbmat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: arr INTEGER :: n, ku INTEGER :: j, ib, jmin, jmax ! ku = mat%ku n = mat%rank IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'PUTROW: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF jmin = i jmax = MIN(n, i+ku) DO j=jmin,jmax ib = ku+i-j+1 mat%val(ib,j) = arr(j) END DO ! jmin=MAX(1,i-ku); jmax=i-1 DO j=jmin,jmax ib=ku+1+j-i mat%val(ib,i) = arr(j) END DO END SUBROUTINE putrow_pb !=========================================================================== SUBROUTINE putrow_zgb(mat, i, arr) ! ! Put a row from matrix ! TYPE(zgbmat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i DOUBLE COMPLEX, DIMENSION(:), INTENT(in) :: arr INTEGER :: n, kl, ku INTEGER :: j, ib, jmin, jmax ! kl = mat%kl ku = mat%ku n = mat%rank IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'PUTROW: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF jmin = MAX(1,i-kl) jmax = MIN(n, i+ku) DO j=jmin,jmax ib = kl+ku+i-j+1 mat%val(ib,j) = arr(j) END DO END SUBROUTINE putrow_zgb !=========================================================================== SUBROUTINE putrow_zpb(mat, i, arr) ! ! Put a row from matrix ! TYPE(zpbmat), INTENT(inout) :: mat INTEGER, INTENT(in) :: i DOUBLE COMPLEX, DIMENSION(:), INTENT(in) :: arr INTEGER :: n, ku INTEGER :: j, ib, jmin, jmax ! ku = mat%ku n = mat%rank IF( SIZE(arr) .LT. n ) THEN WRITE(*,*) 'PUTROW: size of arr too small' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF jmin = i jmax = MIN(n, i+ku) DO j=jmin,jmax ib = ku+i-j+1 mat%val(ib,j) = arr(j) END DO ! jmin=MAX(1,i-ku); jmax=i-1 DO j=jmin,jmax ib=ku+1+j-i mat%val(ib,i) = CONJG(arr(j)) END DO END SUBROUTINE putrow_zpb !=========================================================================== SUBROUTINE factor_gb(mat,flops) ! ! Factor the matrix, using Lapack ! TYPE(gbmat), INTENT(inout) :: mat DOUBLE PRECISION, OPTIONAL, INTENT (OUT) :: flops INTEGER :: lda, n, m, kl, ku INTEGER :: info DOUBLE PRECISION :: dopgb EXTERNAL dopgb ! lda = SIZE(mat%val, 1) kl = mat%kl ku = mat%ku m = mat%mrows n = mat%ncols CALL dgbtrf(m, n, kl, ku, mat%val, lda, mat%piv, info) IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GBTRF ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF IF( PRESENT(flops) ) THEN flops = dopgb('DGBTRF',m, n, kl, ku, mat%piv) END IF END SUBROUTINE factor_gb !=========================================================================== SUBROUTINE factor_periodic(mat) ! ! Factor the periodic GB matrix, using the ! Sherman-Morrisson-Woodburry formula ! TYPE(periodic_mat), INTENT(inout) :: mat TYPE(gemat) :: hmat DOUBLE PRECISION :: one=1.0d0 INTEGER :: bandw, mr, nc, i ! bandw = SIZE(mat%matvt,1) ! ! Factor A CALL factor(mat%mat) ! IF(bandw .EQ. 0 ) RETURN ! No off band terms ! ! U <-- A^(-1) * U CALL bsolve(mat%mat, mat%matu) ! ! H <-- 1 + V^T * U mr = SIZE(mat%matvt, 1) nc = SIZE(mat%matvt, 2) CALL init(mr, 0, hmat) ! hmat is initialized to 0! DO i=1,mr hmat%val(i,i) = one END DO CALL dgemm('N', 'N', mr, mr, nc, one, mat%matvt, mr, & & mat%matu, nc, one, hmat%val, mr) ! ! V^T <-- H^(-1) V^T CALL factor(hmat) CALL bsolve(hmat, mat%matvt) CALL destroy(hmat) ! END SUBROUTINE factor_periodic !=========================================================================== SUBROUTINE factor_zperiodic(mat) ! ! Factor the periodic GB matrix, using the ! Sherman-Morrisson-Woodburry formula ! TYPE(zperiodic_mat), INTENT(inout) :: mat TYPE(zgemat) :: hmat DOUBLE COMPLEX :: one=1.0d0 INTEGER :: bandw, mr, nc, i ! bandw = SIZE(mat%matvt,1) ! ! Factor A CALL factor(mat%mat) ! IF(bandw .EQ. 0 ) RETURN ! No off band terms ! ! U <-- A^(-1) * U CALL bsolve(mat%mat, mat%matu) ! ! H <-- 1 + V^T * U mr = SIZE(mat%matvt, 1) nc = SIZE(mat%matvt, 2) CALL init(mr, 0, hmat) ! hmat is initialized to 0! DO i=1,mr hmat%val(i,i) = one END DO CALL zgemm('N', 'N', mr, mr, nc, one, mat%matvt, mr, & & mat%matu, nc, one, hmat%val, mr) ! ! V^T <-- H^(-1) V^T CALL factor(hmat) CALL bsolve(hmat, mat%matvt) CALL destroy(hmat) ! END SUBROUTINE factor_zperiodic !=========================================================================== SUBROUTINE factor_pb(mat,flops) ! ! Factor the matrix, using Lapack ! TYPE(pbmat), INTENT(inout) :: mat DOUBLE PRECISION, OPTIONAL, INTENT (OUT) :: flops INTEGER :: lda, n, ku INTEGER :: info DOUBLE PRECISION :: dopla EXTERNAL dopla ! lda = SIZE(mat%val, 1) ku = mat%ku n = mat%rank CALL dpbtrf('U', n, ku, mat%val, lda, info) IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from PBTRF ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF IF( PRESENT(flops) ) THEN flops = dopla('DPBTRF', n, n, ku, ku, 1) END IF END SUBROUTINE factor_pb !=========================================================================== SUBROUTINE factor_ge(mat,flops) ! ! Factor the matrix, using Lapack ! TYPE(gemat), INTENT(inout) :: mat DOUBLE PRECISION, OPTIONAL, INTENT (OUT) :: flops INTEGER :: n, m INTEGER :: info DOUBLE PRECISION :: dopla EXTERNAL dopla ! m = mat%mrows n = mat%ncols CALL dgetrf(m, n, mat%val, m, mat%piv, info) IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GETRF ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF IF( PRESENT(flops) ) THEN flops = dopla('DGETRF',m, n, 0, 0, 0) END IF END SUBROUTINE factor_ge !=========================================================================== SUBROUTINE factor_zgb(mat,flops) ! ! Factor the matrix, using Lapack ! TYPE(zgbmat), INTENT(inout) :: mat DOUBLE PRECISION, OPTIONAL, INTENT (OUT) :: flops INTEGER :: lda, n, m, kl, ku INTEGER :: info DOUBLE PRECISION :: dopgb EXTERNAL dopgb ! lda = SIZE(mat%val, 1) kl = mat%kl ku = mat%ku m = mat%mrows n = mat%ncols CALL zgbtrf(m, n, kl, ku, mat%val, lda, mat%piv, info) IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GBTRF ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF IF( PRESENT(flops) ) THEN flops = dopgb('ZGBTRF',m, n, kl, ku, mat%piv) END IF END SUBROUTINE factor_zgb !=========================================================================== SUBROUTINE factor_zpb(mat,flops) ! ! Factor the matrix, using Lapack ! TYPE(zpbmat), INTENT(inout) :: mat DOUBLE PRECISION, OPTIONAL, INTENT (OUT) :: flops INTEGER :: lda, n, ku INTEGER :: info DOUBLE PRECISION :: dopla EXTERNAL dopla ! lda = SIZE(mat%val, 1) ku = mat%ku n = mat%rank CALL zpbtrf('U', n, ku, mat%val, lda, info) IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from PBTRF ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF IF( PRESENT(flops) ) THEN flops = dopla('ZPBTRF', n, n, ku, ku, 1) END IF END SUBROUTINE factor_zpb !=========================================================================== SUBROUTINE factor_zge(mat,flops) ! ! Factor the matrix, using Lapack ! TYPE(zgemat), INTENT(inout) :: mat DOUBLE PRECISION, OPTIONAL, INTENT (OUT) :: flops INTEGER :: n, m INTEGER :: info DOUBLE PRECISION :: dopla EXTERNAL dopla ! m = mat%mrows n = mat%ncols CALL zgetrf(m, n, mat%val, m, mat%piv, info) IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GETRF ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF IF( PRESENT(flops) ) THEN flops = dopla('ZGETRF',m, n, 0, 0, 0) END IF END SUBROUTINE factor_zge !=========================================================================== SUBROUTINE bsolve_gb1(mat, rhs, sol) ! ! Backsolve, using Lapack ! TYPE(gbmat), INTENT(inout) :: mat DOUBLE PRECISION, DIMENSION (:) :: rhs DOUBLE PRECISION, DIMENSION (:), OPTIONAL, INTENT (out) :: sol INTEGER :: lda, n, kl, ku INTEGER :: info !---------------------------------------------------------------------- lda = SIZE(mat%val, 1) kl = mat%kl ku = mat%ku n = mat%rank ! IF( PRESENT(sol) ) THEN sol = rhs CALL dgbtrs('N', n, kl, ku, 1, mat%val, lda, mat%piv, sol, n, info) ELSE CALL dgbtrs('N', n, kl, ku, 1, mat%val, lda, mat%piv, rhs, n, info) END IF IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GBTRS ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF END SUBROUTINE bsolve_gb1 !=========================================================================== SUBROUTINE bsolve_periodic1(mat, rhs, sol) ! ! Backsolve, using the Sherman-Morrison-Woodburry formula ! TYPE(periodic_mat), INTENT(inout) :: mat DOUBLE PRECISION, DIMENSION (:) :: rhs DOUBLE PRECISION, DIMENSION (:), OPTIONAL, INTENT (out) :: sol DOUBLE PRECISION :: one=1.0d0, zero=0.0d0, minus1=-1.0d0 DOUBLE PRECISION, ALLOCATABLE :: tarr(:,:) INTEGER :: rank, bandw, nrhs INTEGER :: info !---------------------------------------------------------------------- rank = mat%mat%rank bandw = SIZE(mat%matvt,1) nrhs = 1 ! ! Solve Ay = f IF( PRESENT(sol) ) THEN CALL bsolve(mat%mat, rhs, sol) ELSE CALL bsolve(mat%mat, rhs) END IF ! IF(bandw .EQ. 0 ) RETURN ! No off band terms ! ! t = V^T*y ( = W^T*y ) ALLOCATE(tarr(bandw,nrhs)) IF( PRESENT(sol) ) THEN CALL dgemm('N', 'N', bandw, nrhs, rank, one, mat%matvt, bandw, sol, & & rank, zero, tarr, bandw) ELSE CALL dgemm('N', 'N', bandw, nrhs, rank, one, mat%matvt, bandw, rhs, & & rank, zero, tarr, bandw) END IF ! ! y = y - U*t ( = y-Z*t) IF( PRESENT(sol) ) THEN CALL dgemm('N', 'N', rank, nrhs, bandw, minus1, mat%matu, rank, tarr, & & bandw, one, sol, rank) ELSE CALL dgemm('N', 'N', rank, nrhs, bandw, minus1, mat%matu, rank, tarr, & & bandw, one, rhs, rank) END IF ! DEALLOCATE(tarr) END SUBROUTINE bsolve_periodic1 !=========================================================================== SUBROUTINE bsolve_zperiodic1(mat, rhs, sol) ! ! Backsolve, using the Sherman-Morrison-Woodburry formula ! TYPE(zperiodic_mat), INTENT(inout) :: mat DOUBLE COMPLEX, DIMENSION (:) :: rhs DOUBLE COMPLEX, DIMENSION (:), OPTIONAL, INTENT (out) :: sol DOUBLE COMPLEX :: one=1.0d0, zero=0.0d0, minus1=-1.0d0 DOUBLE COMPLEX, ALLOCATABLE :: tarr(:,:) INTEGER :: rank, bandw, nrhs INTEGER :: info !---------------------------------------------------------------------- rank = mat%mat%rank bandw = SIZE(mat%matvt,1) nrhs = 1 ! ! Solve Ay = f IF( PRESENT(sol) ) THEN CALL bsolve(mat%mat, rhs, sol) ELSE CALL bsolve(mat%mat, rhs) END IF ! IF(bandw .EQ. 0 ) RETURN ! No off band terms ! ! t = V^T*y ( = W^T*y ) ALLOCATE(tarr(bandw,nrhs)) IF( PRESENT(sol) ) THEN CALL zgemm('N', 'N', bandw, nrhs, rank, one, mat%matvt, bandw, sol, & & rank, zero, tarr, bandw) ELSE CALL zgemm('N', 'N', bandw, nrhs, rank, one, mat%matvt, bandw, rhs, & & rank, zero, tarr, bandw) END IF ! ! y = y - U*t ( = y-Z*t) IF( PRESENT(sol) ) THEN CALL zgemm('N', 'N', rank, nrhs, bandw, minus1, mat%matu, rank, tarr, & & bandw, one, sol, rank) ELSE CALL zgemm('N', 'N', rank, nrhs, bandw, minus1, mat%matu, rank, tarr, & & bandw, one, rhs, rank) END IF ! DEALLOCATE(tarr) END SUBROUTINE bsolve_zperiodic1 !=========================================================================== SUBROUTINE bsolve_pb1(mat, rhs, sol) ! ! Backsolve, using Lapack ! TYPE(pbmat), INTENT(inout) :: mat DOUBLE PRECISION, DIMENSION (:) :: rhs DOUBLE PRECISION, DIMENSION (:), OPTIONAL, INTENT (out) :: sol INTEGER :: lda, n, ku INTEGER :: info !---------------------------------------------------------------------- lda = SIZE(mat%val, 1) ku = mat%ku n = mat%rank ! IF( PRESENT(sol) ) THEN sol = rhs CALL dpbtrs('U', n, ku, 1, mat%val, lda, sol, n, info) ELSE CALL dpbtrs('U', n, ku, 1, mat%val, lda, rhs, n, info) END IF IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from PBTRS ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF END SUBROUTINE bsolve_pb1 !=========================================================================== SUBROUTINE bsolve_ge1(mat, rhs, sol) ! ! Backsolve, using Lapack ! TYPE(gemat), INTENT(inout) :: mat DOUBLE PRECISION, DIMENSION (:) :: rhs DOUBLE PRECISION, DIMENSION (:), OPTIONAL, INTENT (out) :: sol INTEGER :: n INTEGER :: info !---------------------------------------------------------------------- n = mat%rank ! IF( PRESENT(sol) ) THEN sol = rhs CALL dgetrs('N', n, 1, mat%val, n, mat%piv, sol, n, info) ELSE CALL dgetrs('N', n, 1, mat%val, n, mat%piv, rhs, n, info) END IF IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GETRS ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF END SUBROUTINE bsolve_ge1 !=========================================================================== SUBROUTINE bsolve_gbn(mat, rhs, sol) ! ! Backsolve, using Lapack ! TYPE(gbmat), INTENT(inout) :: mat DOUBLE PRECISION, DIMENSION (:,:) :: rhs DOUBLE PRECISION, DIMENSION (:,:), OPTIONAL, INTENT (out) :: sol INTEGER :: lda, n, nrhs, kl, ku INTEGER :: info !---------------------------------------------------------------------- lda = SIZE(mat%val, 1) kl = mat%kl ku = mat%ku n = mat%rank nrhs = SIZE(rhs,2) ! IF( PRESENT(sol) ) THEN sol(:,1:nrhs) = rhs(:,1:nrhs) CALL dgbtrs('N', n, kl, ku, nrhs, mat%val, lda, mat%piv, sol, n, info) ELSE CALL dgbtrs('N', n, kl, ku, nrhs, mat%val, lda, mat%piv, rhs, n, info) END IF IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GBTRS ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF END SUBROUTINE bsolve_gbn !=========================================================================== SUBROUTINE bsolve_periodicn(mat, rhs, sol) ! ! Backsolve, using the Sherman-Morrison-Woodburry formula ! TYPE(periodic_mat), INTENT(inout) :: mat DOUBLE PRECISION, DIMENSION (:,:) :: rhs DOUBLE PRECISION, DIMENSION (:,:), OPTIONAL, INTENT (out) :: sol DOUBLE PRECISION :: one=1.0d0, zero=0.0d0, minus1=-1.0d0 DOUBLE PRECISION, ALLOCATABLE :: tarr(:,:) INTEGER :: rank, bandw, nrhs INTEGER :: info !---------------------------------------------------------------------- rank = mat%mat%rank bandw = SIZE(mat%matvt,1) nrhs = SIZE(rhs,2) ! ! Solve Ay = f IF( PRESENT(sol) ) THEN CALL bsolve(mat%mat, rhs, sol) ELSE CALL bsolve(mat%mat, rhs) END IF ! IF(bandw .EQ. 0 ) RETURN ! No off band terms ! ! t = V^T*y ( = W^T*y ) ALLOCATE(tarr(bandw,nrhs)) IF( PRESENT(sol) ) THEN CALL dgemm('N', 'N', bandw, nrhs, rank, one, mat%matvt, bandw, sol, & & rank, zero, tarr, bandw) ELSE CALL dgemm('N', 'N', bandw, nrhs, rank, one, mat%matvt, bandw, rhs, & & rank, zero, tarr, bandw) END IF ! ! y = y - U*t ( = y-Z*t) IF( PRESENT(sol) ) THEN CALL dgemm('N', 'N', rank, nrhs, bandw, minus1, mat%matu, rank, tarr, & & bandw, one, sol, rank) ELSE CALL dgemm('N', 'N', rank, nrhs, bandw, minus1, mat%matu, rank, tarr, & & bandw, one, rhs, rank) END IF ! DEALLOCATE(tarr) END SUBROUTINE bsolve_periodicn !=========================================================================== SUBROUTINE bsolve_zperiodicn(mat, rhs, sol) ! ! Backsolve, using the Sherman-Morrison-Woodburry formula ! TYPE(zperiodic_mat), INTENT(inout) :: mat DOUBLE COMPLEX, DIMENSION (:,:) :: rhs DOUBLE COMPLEX, DIMENSION (:,:), OPTIONAL, INTENT (out) :: sol DOUBLE COMPLEX :: one=1.0d0, zero=0.0d0, minus1=-1.0d0 DOUBLE COMPLEX, ALLOCATABLE :: tarr(:,:) INTEGER :: rank, bandw, nrhs INTEGER :: info !---------------------------------------------------------------------- rank = mat%mat%rank bandw = SIZE(mat%matvt,1) nrhs = SIZE(rhs,2) ! ! Solve Ay = f IF( PRESENT(sol) ) THEN CALL bsolve(mat%mat, rhs, sol) ELSE CALL bsolve(mat%mat, rhs) END IF ! IF(bandw .EQ. 0 ) RETURN ! No off band terms ! ! t = V^T*y ( = W^T*y ) ALLOCATE(tarr(bandw,nrhs)) IF( PRESENT(sol) ) THEN CALL zgemm('N', 'N', bandw, nrhs, rank, one, mat%matvt, bandw, sol, & & rank, zero, tarr, bandw) ELSE CALL zgemm('N', 'N', bandw, nrhs, rank, one, mat%matvt, bandw, rhs, & & rank, zero, tarr, bandw) END IF ! ! y = y - U*t ( = y-Z*t) IF( PRESENT(sol) ) THEN CALL zgemm('N', 'N', rank, nrhs, bandw, minus1, mat%matu, rank, tarr, & & bandw, one, sol, rank) ELSE CALL zgemm('N', 'N', rank, nrhs, bandw, minus1, mat%matu, rank, tarr, & & bandw, one, rhs, rank) END IF ! DEALLOCATE(tarr) END SUBROUTINE bsolve_zperiodicn !=========================================================================== SUBROUTINE bsolve_pbn(mat, rhs, sol) ! ! Backsolve, using Lapack ! TYPE(pbmat), INTENT(inout) :: mat DOUBLE PRECISION, DIMENSION (:,:) :: rhs DOUBLE PRECISION, DIMENSION (:,:), OPTIONAL, INTENT (out) :: sol INTEGER :: lda, n, nrhs, ku INTEGER :: info !---------------------------------------------------------------------- lda = SIZE(mat%val, 1) ku = mat%ku n = mat%rank nrhs = SIZE(rhs,2) ! IF( PRESENT(sol) ) THEN sol(:,1:nrhs) = rhs(:,1:nrhs) CALL dpbtrs('U', n, ku, nrhs, mat%val, lda, sol, n, info) ELSE CALL dpbtrs('U', n, ku, nrhs, mat%val, lda, rhs, n, info) END IF IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GBTRS ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF END SUBROUTINE bsolve_pbn !=========================================================================== SUBROUTINE bsolve_gen(mat, rhs, sol) ! ! Backsolve, using Lapack ! TYPE(gemat), INTENT(inout) :: mat DOUBLE PRECISION, DIMENSION (:,:) :: rhs DOUBLE PRECISION, DIMENSION (:,:), OPTIONAL, INTENT (out) :: sol INTEGER :: n, nrhs INTEGER :: info !---------------------------------------------------------------------- n = mat%rank nrhs = SIZE(rhs,2) ! IF( PRESENT(sol) ) THEN sol(:,1:nrhs) = rhs CALL dgetrs('N', n, nrhs, mat%val, n, mat%piv, sol, n, info) ELSE CALL dgetrs('N', n, nrhs, mat%val, n, mat%piv, rhs, n, info) END IF IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GETRS ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF END SUBROUTINE bsolve_gen !=========================================================================== SUBROUTINE bsolve_zgb1(mat, rhs, sol) ! ! Backsolve, using Lapack ! TYPE(zgbmat), INTENT(inout) :: mat DOUBLE COMPLEX, DIMENSION (:) :: rhs DOUBLE COMPLEX, DIMENSION (:), OPTIONAL, INTENT (out) :: sol INTEGER :: lda, n, kl, ku INTEGER :: info !---------------------------------------------------------------------- lda = SIZE(mat%val, 1) kl = mat%kl ku = mat%ku n = mat%rank ! IF( PRESENT(sol) ) THEN sol = rhs CALL zgbtrs('N', n, kl, ku, 1, mat%val, lda, mat%piv, sol, n, info) ELSE CALL zgbtrs('N', n, kl, ku, 1, mat%val, lda, mat%piv, rhs, n, info) END IF IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GBTRS ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF END SUBROUTINE bsolve_zgb1 !=========================================================================== SUBROUTINE bsolve_zpb1(mat, rhs, sol) ! ! Backsolve, using Lapack ! TYPE(zpbmat), INTENT(inout) :: mat DOUBLE COMPLEX, DIMENSION (:) :: rhs DOUBLE COMPLEX, DIMENSION (:), OPTIONAL, INTENT (out) :: sol INTEGER :: lda, n, ku INTEGER :: info !---------------------------------------------------------------------- lda = SIZE(mat%val, 1) ku = mat%ku n = mat%rank ! IF( PRESENT(sol) ) THEN sol = rhs CALL zpbtrs('U', n, ku, 1, mat%val, lda, sol, n, info) ELSE CALL zpbtrs('U', n, ku, 1, mat%val, lda, rhs, n, info) END IF IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from PBTRS ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF END SUBROUTINE bsolve_zpb1 !=========================================================================== SUBROUTINE bsolve_zge1(mat, rhs, sol) ! ! Backsolve, using Lapack ! TYPE(zgemat), INTENT(inout) :: mat DOUBLE COMPLEX, DIMENSION (:) :: rhs DOUBLE COMPLEX, DIMENSION (:), OPTIONAL, INTENT (out) :: sol INTEGER :: n INTEGER :: info !---------------------------------------------------------------------- n = mat%rank ! IF( PRESENT(sol) ) THEN sol = rhs CALL zgetrs('N', n, 1, mat%val, n, mat%piv, sol, n, info) ELSE CALL zgetrs('N', n, 1, mat%val, n, mat%piv, rhs, n, info) END IF IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GETRS ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF END SUBROUTINE bsolve_zge1 !=========================================================================== SUBROUTINE bsolve_zgbn(mat, rhs, sol) ! ! Backsolve, using Lapack ! TYPE(zgbmat), INTENT(inout) :: mat DOUBLE COMPLEX, DIMENSION (:,:) :: rhs DOUBLE COMPLEX, DIMENSION (:,:), OPTIONAL, INTENT (out) :: sol INTEGER :: lda, n, nrhs, kl, ku INTEGER :: info !---------------------------------------------------------------------- lda = SIZE(mat%val, 1) kl = mat%kl ku = mat%ku n = mat%rank nrhs = SIZE(rhs,2) ! IF( PRESENT(sol) ) THEN sol(:,1:nrhs) = rhs(:,1:nrhs) CALL zgbtrs('N', n, kl, ku, nrhs, mat%val, lda, mat%piv, sol, n, info) ELSE CALL zgbtrs('N', n, kl, ku, nrhs, mat%val, lda, mat%piv, rhs, n, info) END IF IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GBTRS ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF END SUBROUTINE bsolve_zgbn !=========================================================================== SUBROUTINE bsolve_zpbn(mat, rhs, sol) ! ! Backsolve, using Lapack ! TYPE(zpbmat), INTENT(inout) :: mat DOUBLE COMPLEX, DIMENSION (:,:) :: rhs DOUBLE COMPLEX, DIMENSION (:,:), OPTIONAL, INTENT (out) :: sol INTEGER :: lda, n, nrhs, ku INTEGER :: info !---------------------------------------------------------------------- lda = SIZE(mat%val, 1) ku = mat%ku n = mat%rank nrhs = SIZE(rhs,2) ! IF( PRESENT(sol) ) THEN sol(:,1:nrhs) = rhs(:,1:nrhs) CALL zpbtrs('U', n, ku, nrhs, mat%val, lda, sol, n, info) ELSE CALL zpbtrs('U', n, ku, nrhs, mat%val, lda, rhs, n, info) END IF IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GBTRS ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF END SUBROUTINE bsolve_zpbn !=========================================================================== SUBROUTINE bsolve_zgen(mat, rhs, sol) ! ! Backsolve, using Lapack ! TYPE(zgemat), INTENT(inout) :: mat DOUBLE COMPLEX, DIMENSION (:,:) :: rhs DOUBLE COMPLEX, DIMENSION (:,:), OPTIONAL, INTENT (out) :: sol INTEGER :: n, nrhs INTEGER :: info !---------------------------------------------------------------------- n = mat%rank nrhs = SIZE(rhs,2) ! IF( PRESENT(sol) ) THEN sol(:,1:nrhs) = rhs CALL zgetrs('N', n, nrhs, mat%val, n, mat%piv, sol, n, info) ELSE CALL zgetrs('N', n, nrhs, mat%val, n, mat%piv, rhs, n, info) END IF IF( info .NE. 0) THEN WRITE(*,*) 'FACTOR: info from GETRS ', info STOP '*** Abnormal EXIT in MODULE matrix ***' END IF END SUBROUTINE bsolve_zgen !=========================================================================== FUNCTION vmx_gb(mat, x, trans) RESULT(vmx) ! ! Return product mat*x ! TYPE(gbmat), INTENT(in) :: mat DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: x CHARACTER(len=1), OPTIONAL :: trans DOUBLE PRECISION, ALLOCATABLE :: vmx(:) DOUBLE PRECISION :: one=1.0d0, zero=0.0d0 INTEGER :: lda, kl, ku, m, n, j, imin, imax, ibmin, ibmax CHARACTER(len=1) :: trans_loc ! lda = SIZE(mat%val, 1) kl = mat%kl ku = mat%ku m = mat%mrows n = mat%ncols trans_loc = 'N' IF(PRESENT(trans)) trans_loc = trans ! IF(trans_loc.EQ.'N') THEN ALLOCATE(vmx(m)) ELSE ALLOCATE(vmx(n)) END IF ! CALL dgbmv(trans_loc, m, n, kl, ku, one, mat%val(kl+1,1), lda, x, 1, zero,& & vmx, 1) END FUNCTION vmx_gb !=========================================================================== FUNCTION vmx_ge(mat, x, trans) RESULT(vmx) ! ! Return product mat*x ! TYPE(gemat), INTENT(in) :: mat DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: x CHARACTER(len=1), OPTIONAL :: trans DOUBLE PRECISION, ALLOCATABLE :: vmx(:) DOUBLE PRECISION :: one=1.0d0, zero=0.0d0 INTEGER :: lda, m, n CHARACTER(len=1) :: trans_loc ! lda = SIZE(mat%val, 1) m = mat%mrows n = mat%ncols trans_loc = 'N' IF(PRESENT(trans)) trans_loc = trans ! IF(trans_loc.EQ.'N') THEN ALLOCATE(vmx(m)) ELSE ALLOCATE(vmx(n)) END IF ! CALL dgemv(trans_loc, m, n, one, mat%val, lda, x, 1, zero, vmx, 1) END FUNCTION vmx_ge !=========================================================================== FUNCTION vmx_gen(mat, x, trans) RESULT(vmx) ! ! Return product mat*x ! TYPE(gemat), INTENT(in) :: mat DOUBLE PRECISION, DIMENSION(:,:), INTENT(in) :: x CHARACTER(len=1), OPTIONAL :: trans DOUBLE PRECISION, ALLOCATABLE :: vmx(:,:) DOUBLE PRECISION :: one=1.0d0, zero=0.0d0 INTEGER :: lda, ldb, m, n, k CHARACTER(len=1) :: trans_loc ! lda = SIZE(mat%val, 1) ldb = SIZE(x,1) trans_loc = 'N' IF(PRESENT(trans)) trans_loc = trans ! IF(trans_loc.EQ.'N') THEN m = mat%mrows n = SIZE(x,2) k = mat%ncols ALLOCATE(vmx(m,n)) ELSE m = mat%ncols n = SIZE(x,2) k = mat%mrows ALLOCATE(vmx(m,n)) END IF ! CALL dgemm(trans_loc, 'N', m, n, k, one, mat%val, lda, x, ldb, zero, vmx, & & lda) ! END FUNCTION vmx_gen !=========================================================================== FUNCTION vmx_zge(mat, x, trans) RESULT(vmx) ! ! Return product mat*x ! TYPE(zgemat), INTENT(in) :: mat DOUBLE COMPLEX, DIMENSION(:), INTENT(in) :: x CHARACTER(len=1), OPTIONAL :: trans DOUBLE COMPLEX, ALLOCATABLE :: vmx(:) DOUBLE COMPLEX :: one=1.0d0, zero=0.0d0 INTEGER :: lda, m, n CHARACTER(len=1) :: trans_loc ! lda = SIZE(mat%val, 1) m = mat%mrows n = mat%ncols trans_loc = 'N' IF(PRESENT(trans)) trans_loc = trans ! IF(trans_loc.EQ.'N') THEN ALLOCATE(vmx(m)) ELSE ALLOCATE(vmx(n)) END IF ! CALL zgemv(trans_loc, m, n, one, mat%val, lda, x, 1, zero, vmx, 1) END FUNCTION vmx_zge !=========================================================================== FUNCTION vmx_zgen(mat, x, trans) RESULT(vmx) ! ! Return product mat*x ! TYPE(zgemat), INTENT(in) :: mat DOUBLE COMPLEX, DIMENSION(:,:), INTENT(in) :: x CHARACTER(len=1), OPTIONAL :: trans DOUBLE COMPLEX, ALLOCATABLE :: vmx(:,:) DOUBLE COMPLEX :: one=1.0d0, zero=0.0d0 INTEGER :: lda, ldb, m, n, k CHARACTER(len=1) :: trans_loc ! lda = SIZE(mat%val, 1) ldb = SIZE(x,1) trans_loc = 'N' IF(PRESENT(trans)) trans_loc = trans ! IF(trans_loc.EQ.'N') THEN m = mat%mrows n = SIZE(x,2) k = mat%ncols ALLOCATE(vmx(m,n)) ELSE m = mat%ncols n = SIZE(x,2) k = mat%mrows ALLOCATE(vmx(m,n)) END IF ! CALL zgemm(trans_loc, 'N', m, n, k, one, mat%val, lda, x, ldb, zero, vmx, & & lda) ! END FUNCTION vmx_zgen !=========================================================================== FUNCTION vmx_periodic(mat, x) ! ! Return product mat*x ! TYPE(periodic_mat), INTENT(in) :: mat DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: x DOUBLE PRECISION, DIMENSION(SIZE(x)) :: vmx_periodic INTEGER :: kl, ku, n, i, ii ! kl = mat%mat%kl ku = mat%mat%ku n = mat%mat%rank ! vmx_periodic = vmx(mat%mat, x) ! DO i=1,kl vmx_periodic(i) = vmx_periodic(i) + & & DOT_PRODUCT(mat%matvt(i,n-kl+1:n), x(n-kl+1:n)) END DO ! DO i=n-ku+1,n ii = i-n+ku+kl vmx_periodic(i) = vmx_periodic(i) + & & DOT_PRODUCT(mat%matvt(ii,1:ku), x(1:ku)) END DO END FUNCTION vmx_periodic !=========================================================================== FUNCTION vmx_zperiodic(mat, x) ! ! Return product mat*x ! TYPE(zperiodic_mat), INTENT(in) :: mat DOUBLE COMPLEX, DIMENSION(:), INTENT(in) :: x DOUBLE COMPLEX, DIMENSION(SIZE(x)) :: vmx_zperiodic INTEGER :: kl, ku, n, i, ii ! kl = mat%mat%kl ku = mat%mat%ku n = mat%mat%rank ! vmx_zperiodic = vmx(mat%mat, x) ! DO i=1,kl vmx_zperiodic(i) = vmx_zperiodic(i) + & & DOT_PRODUCT(mat%matvt(i,n-kl+1:n), x(n-kl+1:n)) END DO ! DO i=n-ku+1,n ii = i-n+ku+kl vmx_zperiodic(i) = vmx_zperiodic(i) + & & DOT_PRODUCT(mat%matvt(ii,1:ku), x(1:ku)) END DO END FUNCTION vmx_zperiodic !=========================================================================== FUNCTION vmx_gbn(mat, x, trans) RESULT(vmx) ! ! Return product mat*x ! TYPE(gbmat), INTENT(in) :: mat DOUBLE PRECISION, DIMENSION(:,:), INTENT(in) :: x CHARACTER(len=1), OPTIONAL :: trans DOUBLE PRECISION, ALLOCATABLE :: vmx(:,:) DOUBLE PRECISION :: one=1.0d0, zero=0.0d0 INTEGER :: lda, kl, ku, m, n, j, k, imin, imax, ibmin, ibmax CHARACTER(len=1) :: trans_loc ! lda = SIZE(mat%val, 1) kl = mat%kl ku = mat%ku m = mat%mrows n = mat%ncols trans_loc = 'N' IF(PRESENT(trans)) trans_loc = trans ! IF(trans_loc.EQ.'N') THEN ALLOCATE(vmx(m,SIZE(x,2))) ELSE ALLOCATE(vmx(n,SIZE(x,2))) END IF ! DO k=1,SIZE(x,2) CALL dgbmv(trans_loc, m, n, kl, ku, one, mat%val(kl+1,1), lda, & & x(1,k), 1, zero, vmx(1,k), 1) END DO END FUNCTION vmx_gbn !=========================================================================== FUNCTION vmx_pb(mat, x) ! ! Return product mat*x ! TYPE(pbmat), INTENT(in) :: mat DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: x DOUBLE PRECISION, DIMENSION(SIZE(x)) :: vmx_pb INTEGER :: lda, ku, n, i, j, imin, imax, ib, ibmin, ibmax ! lda = SIZE(mat%val, 1) ku = mat%ku n = mat%rank ! vmx_pb = 0.0d0 DO j=1,n imin = MAX(1,j-ku); imax = j ! The column in the upper diagonal part ibmin = ku+imin-j+1; ibmax = ku+imax-j+1 vmx_pb(imin:imax) = vmx_pb(imin:imax) + mat%val(ibmin:ibmax,j)*x(j) ! imin=j+1; imax = MIN(n,j+ku) ! The column in the lower diagonal part DO i=imin,imax ib = ku+1+j-i vmx_pb(i) = vmx_pb(i) + mat%val(ib,i)*x(j) END DO END DO END FUNCTION vmx_pb !=========================================================================== FUNCTION vmx_pbn(mat, x) ! ! Return product mat*x ! TYPE(pbmat), INTENT(in) :: mat DOUBLE PRECISION, DIMENSION(:,:), INTENT(in) :: x DOUBLE PRECISION, DIMENSION(SIZE(x,1),SIZE(x,2)) :: vmx_pbn INTEGER :: lda, ku, n, i, j, k, imin, imax, ib, ibmin, ibmax ! lda = SIZE(mat%val, 1) ku = mat%ku n = mat%rank ! vmx_pbn = 0.0d0 DO j=1,n imin = MAX(1,j-ku); imax = j ! The column in the upper diagonal part ibmin = ku+imin-j+1; ibmax = ku+imax-j+1 DO k=1,SIZE(x,2) vmx_pbn(imin:imax,k) = vmx_pbn(imin:imax,k) + & & mat%val(ibmin:ibmax,j)*x(j,k) END DO ! imin=j+1; imax = MIN(n,j+ku) ! The column in the lower diagonal part DO i=imin,imax ib = ku+1+j-i vmx_pbn(i,:) = vmx_pbn(i,:) + mat%val(ib,i)*x(j,:) END DO END DO END FUNCTION vmx_pbn !=========================================================================== FUNCTION vmx_zgb(mat, x, trans) RESULT(vmx) ! ! Return product mat*x ! TYPE(zgbmat), INTENT(in) :: mat DOUBLE COMPLEX, DIMENSION(:), INTENT(in) :: x CHARACTER(len=1), OPTIONAL :: trans DOUBLE COMPLEX, ALLOCATABLE :: vmx(:) DOUBLE COMPLEX :: one=1.0d0, zero=0.0d0 INTEGER :: lda, kl, ku, m, n, j, imin, imax, ibmin, ibmax CHARACTER(len=1) :: trans_loc ! lda = SIZE(mat%val, 1) kl = mat%kl ku = mat%ku m = mat%mrows n = mat%ncols trans_loc = 'N' IF(PRESENT(trans)) trans_loc = trans ! IF(trans_loc.EQ.'N') THEN ALLOCATE(vmx(m)) ELSE ALLOCATE(vmx(n)) END IF ! CALL zgbmv(trans_loc, m, n, kl, ku, one, mat%val(kl+1,1), lda, x, 1, zero,& & vmx, 1) END FUNCTION vmx_zgb !=========================================================================== FUNCTION vmx_zgbn(mat, x, trans) RESULT(vmx) ! ! Return product mat*x ! TYPE(zgbmat), INTENT(in) :: mat DOUBLE COMPLEX, DIMENSION(:,:), INTENT(in) :: x CHARACTER(len=1), OPTIONAL :: trans DOUBLE COMPLEX, ALLOCATABLE :: vmx(:,:) DOUBLE COMPLEX :: one=1.0d0, zero=0.0d0 INTEGER :: lda, kl, ku, m, n, j, k, imin, imax, ibmin, ibmax CHARACTER(len=1) :: trans_loc ! lda = SIZE(mat%val, 1) kl = mat%kl ku = mat%ku m = mat%mrows n = mat%ncols trans_loc = 'N' IF(PRESENT(trans)) trans_loc = trans ! IF(trans_loc.EQ.'N') THEN ALLOCATE(vmx(m,SIZE(x,2))) ELSE ALLOCATE(vmx(n,SIZE(x,2))) END IF ! DO k=1,SIZE(x,2) CALL zgbmv(trans_loc, m, n, kl, ku, one, mat%val(kl+1,1), lda, & & x(1,k), 1, zero, vmx(1,k), 1) END DO END FUNCTION vmx_zgbn !=========================================================================== FUNCTION vmx_zpb(mat, x) ! ! Return product mat*x ! TYPE(zpbmat), INTENT(in) :: mat DOUBLE COMPLEX, DIMENSION(:), INTENT(in) :: x DOUBLE COMPLEX, DIMENSION(SIZE(x)) :: vmx_zpb INTEGER :: lda, ku, n, i, j, imin, imax, ib, ibmin, ibmax ! lda = SIZE(mat%val, 1) ku = mat%ku n = mat%rank ! vmx_zpb = 0.0d0 DO j=1,n imin = MAX(1,j-ku); imax = j ! The column in the upper diagonal part ibmin = ku+imin-j+1; ibmax = ku+imax-j+1 vmx_zpb(imin:imax) = vmx_zpb(imin:imax) + mat%val(ibmin:ibmax,j)*x(j) ! imin=j+1; imax = MIN(n,j+ku) ! The column in the lower diagonal part DO i=imin,imax ib = ku+1+j-i vmx_zpb(i) = vmx_zpb(i) + CONJG(mat%val(ib,i))*x(j) END DO END DO END FUNCTION vmx_zpb !=========================================================================== FUNCTION vmx_zpbn(mat, x) ! ! Return product mat*x ! TYPE(zpbmat), INTENT(in) :: mat DOUBLE COMPLEX, DIMENSION(:,:), INTENT(in) :: x DOUBLE COMPLEX, DIMENSION(SIZE(x,1),SIZE(x,2)) :: vmx_zpbn INTEGER :: lda, ku, n, i, j, k, imin, imax, ib, ibmin, ibmax ! lda = SIZE(mat%val, 1) ku = mat%ku n = mat%rank ! vmx_zpbn = 0.0d0 DO j=1,n imin = MAX(1,j-ku); imax = j ! The column in the upper diagonal part ibmin = ku+imin-j+1; ibmax = ku+imax-j+1 DO k=1,SIZE(x,2) vmx_zpbn(imin:imax,k) = vmx_zpbn(imin:imax,k) + & & mat%val(ibmin:ibmax,j)*x(j,k) END DO ! imin=j+1; imax = MIN(n,j+ku) ! The column in the lower diagonal part DO i=imin,imax ib = ku+1+j-i vmx_zpbn(i,:) = vmx_zpbn(i,:) + CONJG(mat%val(ib,i))*x(j,:) END DO END DO END FUNCTION vmx_zpbn !=========================================================================== SUBROUTINE determinant_ge(mat, base, pow) ! ! Return the determinant of mat ! TYPE(gemat) :: mat INTEGER :: pow, i DOUBLE PRECISION :: base ! CALL factor(mat) base = 1.0d0 pow = 0 DO i=1,mat%rank IF( mat%piv(i) .NE. i) base = -base base = mat%val(i,i)*base IF( base .EQ. 0.0d0 ) THEN WRITE(*,*) 'DETERMINANT_GE: matrix is singular' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF DO IF( ABS(base) .GE. 1.0d0 ) EXIT base = 10.0d0*base pow = pow - 1 END DO DO IF( ABS(base) .LT. 10.0d0 ) EXIT base = base/10.0d0 pow = pow + 1 END DO END DO END SUBROUTINE determinant_ge !=========================================================================== SUBROUTINE determinant_gb(mat, base, pow) ! ! Return the determinant of mat ! TYPE(gbmat) :: mat INTEGER :: pow, i, ib DOUBLE PRECISION :: base ! CALL factor(mat) base = 1.0d0 pow = 0 ib=mat%kl + mat%ku + 1 DO i=1,mat%rank IF( mat%piv(i) .NE. i) base = -base base = mat%val(ib,i)*base IF( base .EQ. 0.0d0 ) THEN WRITE(*,*) 'DETERMINANT_GB: matrix is singular' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF DO IF( ABS(base) .GE. 1.0d0 ) EXIT base = 10.0d0*base pow = pow - 1 END DO DO IF( ABS(base) .LT. 10.0d0 ) EXIT base = base/10.0d0 pow = pow + 1 END DO END DO END SUBROUTINE determinant_gb !=========================================================================== SUBROUTINE determinant_pb(mat, base, pow) ! ! Return the determinant of mat ! TYPE(pbmat) :: mat INTEGER :: pow, i, ib DOUBLE PRECISION :: base ! CALL factor(mat) base = 1.0d0 pow = 0 ib = mat%ku + 1 DO i=1,mat%rank base = mat%val(ib,i)*base IF( base .EQ. 0.0d0 ) THEN WRITE(*,*) 'DETERMINANT_PB: matrix is singular' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF DO IF( ABS(base) .GE. 1.0d0 ) EXIT base = 10.0d0*base pow = pow - 1 END DO DO IF( ABS(base) .LT. 10.0d0 ) EXIT base = base/10.0d0 pow = pow + 1 END DO END DO base=base**2 pow=pow*2 END SUBROUTINE determinant_pb !=========================================================================== SUBROUTINE determinant_zge(mat, base, pow) ! ! Return the determinant of mat ! TYPE(zgemat) :: mat INTEGER :: pow, i DOUBLE COMPLEX :: base ! CALL factor(mat) base = 1.0d0 pow = 0 DO i=1,mat%rank IF( mat%piv(i) .NE. i) base = -base base = mat%val(i,i)*base IF( base .EQ. 0.0d0 ) THEN WRITE(*,*) 'DETERMINANT_ZGE: matrix is singular' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF DO IF( ABS(base) .GE. 1.0d0 ) EXIT base = 10.0d0*base pow = pow - 1 END DO DO IF( ABS(base) .LT. 10.0d0 ) EXIT base = base/10.0d0 pow = pow + 1 END DO END DO END SUBROUTINE determinant_zge !=========================================================================== SUBROUTINE determinant_zgb(mat, base, pow) ! ! Return the determinant of mat ! TYPE(zgbmat) :: mat INTEGER :: pow, i, ib DOUBLE COMPLEX :: base ! CALL factor(mat) base = 1.0d0 pow = 0 ib=mat%kl + mat%ku + 1 DO i=1,mat%rank IF( mat%piv(i) .NE. i) base = -base base = mat%val(ib,i)*base IF( base .EQ. 0.0d0 ) THEN WRITE(*,*) 'DETERMINANT_GB: matrix is singular' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF DO IF( ABS(base) .GE. 1.0d0 ) EXIT base = 10.0d0*base pow = pow - 1 END DO DO IF( ABS(base) .LT. 10.0d0 ) EXIT base = base/10.0d0 pow = pow + 1 END DO END DO END SUBROUTINE determinant_zgb !=========================================================================== SUBROUTINE determinant_zpb(mat, base, pow) ! ! Return the determinant of mat ! TYPE(zpbmat) :: mat INTEGER :: pow, i, ib DOUBLE COMPLEX :: base ! CALL factor(mat) base = 1.0d0 pow = 0 ib = mat%ku + 1 DO i=1,mat%rank base = mat%val(ib,i)*base IF( base .EQ. 0.0d0 ) THEN WRITE(*,*) 'DETERMINANT_PB: matrix is singular' STOP '*** Abnormal EXIT in MODULE matrix ***' END IF DO IF( ABS(base) .GE. 1.0d0 ) EXIT base = 10.0d0*base pow = pow - 1 END DO DO IF( ABS(base) .LT. 10.0d0 ) EXIT base = base/10.0d0 pow = pow + 1 END DO END DO base=base**2 pow=pow*2 END SUBROUTINE determinant_zpb !=========================================================================== SUBROUTINE putmat_gb(fid, label, mat, str) ! ! Write GB matrix in hdf5 file ! USE futils INTEGER, INTENT(in) :: fid CHARACTER(len=*), INTENT(in) :: label TYPE(gbmat) :: mat CHARACTER(len=*), OPTIONAL, INTENT(in) :: str IF(PRESENT(str)) THEN CALL putarr(fid, label, mat%val, str) ELSE CALL putarr(fid, label, mat%val) END IF CALL attach(fid, label, 'KL', mat%kl) CALL attach(fid, label, 'KU', mat%ku) CALL attach(fid, label, 'RANK', mat%rank) END SUBROUTINE putmat_gb !=========================================================================== SUBROUTINE getmat_gb(fid, label, mat, str) ! ! Read in GB matrix from hdf5 file ! USE futils INTEGER, INTENT(in) :: fid CHARACTER(len=*), INTENT(in) :: label TYPE(gbmat) :: mat CHARACTER(len=*), OPTIONAL, INTENT(in) :: str CALL getatt(fid, label, 'KL', mat%kl) CALL getatt(fid, label, 'KU', mat%ku) CALL getatt(fid, label, 'RANK', mat%rank) CALL getarr(fid, label, mat%val) END SUBROUTINE getmat_gb !=========================================================================== SUBROUTINE kron_ge(mata, matb, matc) ! ! Krocnecker product of 2 dense matrices ! TYPE(gemat), INTENT(in) :: mata, matb TYPE(gemat), INTENT(out) :: matc ! INTEGER :: i1, j1, i3, j3, m1, n1, m2, n2, m3, n3 ! m1 = mata%mrows n1 = mata%ncols m2 = matb%mrows n2 = matb%ncols m3 = m1*m2 n3 = n1*n2 ! CALL init(n3, 0, matc, mrows=m3) DO i1=1,m1 i3 = (i1-1)*m2 DO j1=1,n1 j3 = (j1-1)*n2 matc%val(i3+1:i3+m2,j3+1:j3+n2) = mata%val(i1,j1)*matb%val(1:m2,1:n2) END DO END DO END SUBROUTINE kron_ge !=========================================================================== END MODULE matrix