#include "../config.h"
MODULE DirectSolve
USE CRSMatrix
USE BandMatrix
USE SParIterSolve
IMPLICIT NONE
CONTAINS
SUBROUTINE ComplexBandSolver( A,x,b, Free_fact )
LOGICAL, OPTIONAL :: Free_Fact
TYPE(Matrix_t) :: A
REAL(KIND=dp) :: x(*),b(*)
INTEGER :: i,j,k,istat,Subband,N
COMPLEX(KIND=dp), ALLOCATABLE :: BA(:,:)
REAL(KIND=dp), POINTER CONTIG :: Values(:)
INTEGER, POINTER CONTIG :: Rows(:), Cols(:), Diag(:)
SAVE BA
IF ( PRESENT(Free_Fact) ) THEN
IF ( Free_Fact ) THEN
IF ( ALLOCATED(BA) ) DEALLOCATE(BA)
RETURN
END IF
END IF
Rows => A % Rows
Cols => A % Cols
Diag => A % Diag
Values => A % Values
n = A % NumberOfRows
x(1:n) = b(1:n)
n = n / 2
IF ( A % Format == MATRIX_CRS .AND. .NOT. A % Symmetric ) THEN
Subband = 0
DO i=1,N
DO j=Rows(2*i-1),Rows(2*i)-1,2
Subband = MAX(Subband,ABS((Cols(j)+1)/2-i))
END DO
END DO
IF ( .NOT.ALLOCATED( BA ) ) THEN
ALLOCATE( BA(3*SubBand+1,N),stat=istat )
IF ( istat /= 0 ) THEN
CALL Fatal( 'ComplexBandSolver', 'Memory allocation error.' )
END IF
ELSE IF ( SIZE(BA,1) /= 3*Subband+1 .OR. SIZE(BA,2) /= N ) THEN
DEALLOCATE( BA )
ALLOCATE( BA(3*SubBand+1,N),stat=istat )
IF ( istat /= 0 ) THEN
CALL Fatal( 'ComplexBandSolver', 'Memory allocation error.' )
END IF
END IF
BA = 0.0D0
DO i=1,N
DO j=Rows(2*i-1),Rows(2*i)-1,2
k = i - (Cols(j)+1)/2 + 2*Subband + 1
BA(k,(Cols(j)+1)/2) = CMPLX(Values(j), -Values(j+1), KIND=dp )
END DO
END DO
CALL SolveComplexBandLapack( N,1,BA,x,Subband,3*Subband+1 )
ELSE IF ( A % Format == MATRIX_CRS ) THEN
Subband = 0
DO i=1,N
DO j=Rows(2*i-1),Diag(2*i-1)
Subband = MAX(Subband,ABS((Cols(j)+1)/2-i))
END DO
END DO
IF ( .NOT.ALLOCATED( BA ) ) THEN
ALLOCATE( BA(SubBand+1,N),stat=istat )
IF ( istat /= 0 ) THEN
CALL Fatal( 'ComplexBandSolver', 'Memory allocation error.' )
END IF
ELSE IF ( SIZE(BA,1) /= Subband+1 .OR. SIZE(BA,2) /= N ) THEN
DEALLOCATE( BA )
ALLOCATE( BA(SubBand+1,N),stat=istat )
IF ( istat /= 0 ) THEN
CALL Fatal( 'ComplexBandSolver', 'Direct solver memory allocation error.' )
END IF
END IF
BA = 0.0D0
DO i=1,N
DO j=Rows(2*i-1),Diag(2*i-1)
k = i - (Cols(j)+1)/2 + 1
BA(k,(Cols(j)+1)/2) = CMPLX(Values(j), -Values(j+1), KIND=dp )
END DO
END DO
CALL SolveComplexSBandLapack( N,1,BA,x,Subband,Subband+1 )
END IF
END SUBROUTINE ComplexBandSolver
SUBROUTINE BandSolver( A,x,b,Free_Fact )
LOGICAL, OPTIONAL :: Free_Fact
TYPE(Matrix_t) :: A
REAL(KIND=dp) :: x(*),b(*)
INTEGER :: i,j,k,istat,Subband,N
REAL(KIND=dp), ALLOCATABLE :: BA(:,:)
REAL(KIND=dp), POINTER CONTIG :: Values(:)
INTEGER, POINTER CONTIG :: Rows(:), Cols(:), Diag(:)
SAVE BA
IF ( PRESENT(Free_Fact) ) THEN
IF ( Free_Fact ) THEN
IF ( ALLOCATED(BA) ) DEALLOCATE(BA)
RETURN
END IF
END IF
N = A % NumberOfRows
x(1:n) = b(1:n)
Rows => A % Rows
Cols => A % Cols
Diag => A % Diag
Values => A % Values
IF ( A % Format == MATRIX_CRS ) THEN
Subband = 0
DO i=1,N
DO j=Rows(i),Rows(i+1)-1
Subband = MAX(Subband,ABS(Cols(j)-i))
END DO
END DO
IF ( .NOT.ALLOCATED( BA ) ) THEN
ALLOCATE( BA(3*SubBand+1,N),stat=istat )
IF ( istat /= 0 ) THEN
CALL Fatal( 'BandSolver', 'Memory allocation error.' )
END IF
ELSE IF ( SIZE(BA,1) /= 3*Subband+1 .OR. SIZE(BA,2) /= N ) THEN
DEALLOCATE( BA )
ALLOCATE( BA(3*SubBand+1,N),stat=istat )
IF ( istat /= 0 ) THEN
CALL Fatal( 'BandSolver', 'Memory allocation error.' )
END IF
END IF
BA = 0.0D0
DO i=1,N
DO j=Rows(i),Rows(i+1)-1
k = i - Cols(j) + 2*Subband + 1
BA(k,Cols(j)) = Values(j)
END DO
END DO
CALL SolveBandLapack( N,1,BA,x,Subband,3*Subband+1 )
ELSE IF ( A % Format == MATRIX_CRS ) THEN
Subband = 0
DO i=1,N
DO j=Rows(i),Diag(i)
Subband = MAX(Subband,ABS(Cols(j)-i))
END DO
END DO
IF ( .NOT.ALLOCATED( BA ) ) THEN
ALLOCATE( BA(SubBand+1,N),stat=istat )
IF ( istat /= 0 ) THEN
CALL Fatal( 'BandSolver', 'Memory allocation error.' )
END IF
ELSE IF ( SIZE(BA,1) /= Subband+1 .OR. SIZE(BA,2) /= N ) THEN
DEALLOCATE( BA )
ALLOCATE( BA(SubBand+1,N),stat=istat )
IF ( istat /= 0 ) THEN
CALL Fatal( 'BandSolver', 'Memory allocation error.' )
END IF
END IF
BA = 0.0D0
DO i=1,N
DO j=Rows(i),Diag(i)
k = i - Cols(j) + 1
BA(k,Cols(j)) = Values(j)
END DO
END DO
CALL SolveSBandLapack( N,1,BA,x,Subband,Subband+1 )
ELSE IF ( A % Format == MATRIX_BAND ) THEN
CALL SolveBandLapack( N,1,Values,x,Subband,3*Subband+1 )
ELSE IF ( A % Format == MATRIX_SBAND ) THEN
CALL SolveSBandLapack( N,1,Values,x,Subband,Subband+1 )
END IF
END SUBROUTINE BandSolver
SUBROUTINE UMFPack_SolveSystem( Solver,A,x,b,Free_Fact )
LOGICAL, OPTIONAL :: Free_Fact
TYPE(Matrix_t) :: A
TYPE(Solver_t) :: Solver
REAL(KIND=dp), TARGET :: x(*), b(*)
REAL(KIND=dp), POINTER CONTIG :: Values(:)
INTEGER, POINTER CONTIG :: Rows(:), Cols(:), Diag(:)
#include "../config.h"
#ifdef HAVE_UMFPACK
#ifdef ARCH_32_BITS
#define CAddrInt c_int32_t
#else
#define CAddrInt c_int64_t
#endif
INTERFACE
SUBROUTINE umf4def( control ) &
BIND(C,name='umf4def')
USE, INTRINSIC :: ISO_C_BINDING
REAL(C_DOUBLE) :: control(*)
END SUBROUTINE umf4def
SUBROUTINE umf4sym( m,n,rows,cols,values,symbolic,control,iinfo ) &
BIND(C,name='umf4sym')
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: m,n,rows(*),cols(*)
INTEGER(CAddrInt) :: symbolic
REAL(C_DOUBLE) :: Values(*), control(*),iinfo(*)
END SUBROUTINE umf4sym
SUBROUTINE umf4num( rows,cols,values,symbolic,numeric, control,iinfo ) &
BIND(C,name='umf4num')
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: rows(*),cols(*)
INTEGER(CAddrInt) :: numeric, symbolic
REAL(C_DOUBLE) :: Values(*), control(*),iinfo(*)
END SUBROUTINE umf4num
SUBROUTINE umf4sol( sys, x, b, numeric, control, iinfo ) &
BIND(C,name='umf4sol')
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: sys
INTEGER(CAddrInt) :: numeric
REAL(C_DOUBLE) :: x(*), b(*), control(*), iinfo(*)
END SUBROUTINE umf4sol
SUBROUTINE umf4fsym(symbolic) &
BIND(C,name='umf4fsym')
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(CAddrInt) :: symbolic
END SUBROUTINE umf4fsym
SUBROUTINE umf4fnum(numeric) &
BIND(C,name='umf4fnum')
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(CAddrInt) :: numeric
END SUBROUTINE umf4fnum
END INTERFACE
INTERFACE
SUBROUTINE umf4_l_def( control ) &
BIND(C,name='umf4_l_def')
USE, INTRINSIC :: ISO_C_BINDING
REAL(C_DOUBLE) :: control(*)
END SUBROUTINE umf4_l_def
SUBROUTINE umf4_l_sym( m,n,rows,cols,values,symbolic,control,iinfo ) &
BIND(C,name='umf4_l_sym')
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(UMFPACK_LONG_FORTRAN_TYPE) :: m,n,rows(*),cols(*)
INTEGER(CAddrInt) :: symbolic
REAL(C_DOUBLE) :: Values(*), control(*),iinfo(*)
END SUBROUTINE umf4_l_sym
SUBROUTINE umf4_l_num( rows,cols,values,symbolic,numeric, control,iinfo ) &
BIND(C,name='umf4_l_num')
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(UMFPACK_LONG_FORTRAN_TYPE) :: rows(*),cols(*)
INTEGER(CAddrInt) :: numeric, symbolic
REAL(C_DOUBLE) :: Values(*), control(*),iinfo(*)
END SUBROUTINE umf4_l_num
SUBROUTINE umf4_l_sol( sys, x, b, numeric, control, iinfo ) &
BIND(C,name='umf4_l_sol')
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(UMFPACK_LONG_FORTRAN_TYPE) :: sys
INTEGER(CAddrInt) :: numeric
REAL(C_DOUBLE) :: x(*), b(*), control(*), iinfo(*)
END SUBROUTINE umf4_l_sol
SUBROUTINE umf4_l_fnum(numeric) &
BIND(C,name='umf4_l_fnum')
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(CAddrInt) :: numeric
END SUBROUTINE umf4_l_fnum
SUBROUTINE umf4_l_fsym(symbolic) &
BIND(C,name='umf4_l_fsym')
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(CAddrInt) :: symbolic
END SUBROUTINE umf4_l_fsym
END INTERFACE
INTEGER :: i, n, status, sys
REAL(KIND=dp) :: iInfo(90), Control(20)
INTEGER(KIND=AddrInt) :: symbolic, zero=0
INTEGER(KIND=UMFPACK_LONG_FORTRAN_TYPE) :: ln, lsys
INTEGER(KIND=UMFPACK_LONG_FORTRAN_TYPE), ALLOCATABLE :: LRows(:), LCols(:)
SAVE iInfo, Control
LOGICAL :: Factorize, FreeFactorize, stat, BigMode
IF ( PRESENT(Free_Fact) ) THEN
IF ( Free_Fact ) THEN
IF ( A % UMFPack_Numeric/=0 ) THEN
CALL umf4fnum(A % UMFPack_Numeric)
A % UMFPack_Numeric = 0
END IF
RETURN
END IF
END IF
BigMode = ListGetString( Solver % Values, &
'Linear System Direct Method' ) == 'big umfpack'
Factorize = ListGetLogical( Solver % Values, &
'Linear System Refactorize', stat )
IF ( .NOT. stat ) Factorize = .TRUE.
n = A % NumberofRows
Rows => A % Rows
Cols => A % Cols
Diag => A % Diag
Values => A % Values
IF ( Factorize .OR. A% UmfPack_Numeric==0 ) THEN
IF ( A % UMFPack_Numeric /= 0 ) THEN
IF( BigMode ) THEN
CALL umf4_l_fnum( A % UMFPack_Numeric )
ELSE
CALL umf4fnum( A % UMFPack_Numeric )
END IF
A % UMFPack_Numeric = 0
END IF
IF ( BigMode ) THEN
ALLOCATE( LRows(SIZE(Rows)), LCols(SIZE(Cols)) )
DO i=1,n+1
LRows(i) = Rows(i)-1
END DO
DO i=1,SIZE(Cols)
LCols(i) = Cols(i)-1
END DO
ln = n
CALL umf4_l_def( Control )
CALL umf4_l_sym( ln,ln, LRows, LCols, Values, Symbolic, Control, iInfo )
ELSE
Rows = Rows-1
Cols = Cols-1
CALL umf4def( Control )
CALL umf4sym( n,n, Rows, Cols, Values, Symbolic, Control, iInfo )
END IF
IF (iInfo(1)<0) THEN
PRINT *, 'Error occurred in umf4sym: ', iInfo(1)
STOP EXIT_ERROR
END IF
IF ( BigMode ) THEN
CALL umf4_l_num(LRows, LCols, Values, Symbolic, A % UMFPack_Numeric, Control, iInfo )
ELSE
CALL umf4num( Rows, Cols, Values, Symbolic, A % UMFPack_Numeric, Control, iInfo )
END IF
IF (iinfo(1)<0) THEN
PRINT*, 'Error occurred in umf4num: ', iinfo(1)
STOP EXIT_ERROR
ENDIF
IF ( BigMode ) THEN
DEALLOCATE( LRows, LCols )
CALL umf4_l_fsym( Symbolic )
ELSE
A % Rows = A % Rows+1
A % Cols = A % Cols+1
CALL umf4fsym( Symbolic )
END IF
END IF
IF ( BigMode ) THEN
lsys = 2
CALL umf4_l_sol( lsys, x, b, A % UMFPack_Numeric, Control, iInfo )
ELSE
sys = 2
CALL umf4sol( sys, x, b, A % UMFPack_Numeric, Control, iInfo )
END IF
IF (iinfo(1)<0) THEN
PRINT*, 'Error occurred in umf4sol: ', iinfo(1)
STOP EXIT_ERROR
END IF
FreeFactorize = ListGetLogical( Solver % Values, &
'Linear System Free Factorization', stat )
IF ( .NOT. stat ) FreeFactorize = .TRUE.
IF ( Factorize .AND. FreeFactorize ) THEN
IF ( BigMode ) THEN
CALL umf4_l_fnum(A % UMFPack_Numeric)
ELSE
CALL umf4fnum(A % UMFPack_Numeric)
END IF
A % UMFPack_Numeric = 0
END IF
#else
CALL Fatal( 'UMFPack_SolveSystem', 'UMFPACK Solver has not been installed.' )
#endif
END SUBROUTINE UMFPack_SolveSystem
SUBROUTINE Cholmod_SolveSystem( Solver,A,x,b,Free_fact)
LOGICAL, OPTIONAL :: Free_Fact
TYPE(Matrix_t) :: A
TYPE(Solver_t) :: Solver
REAL(KIND=dp) :: x(*), b(*)
INTERFACE
SUBROUTINE cholmod_ffree(chol) BIND(c,NAME="cholmod_ffree")
USE Types
INTEGER(KIND=AddrInt) :: chol
END SUBROUTINE cholmod_ffree
FUNCTION cholmod_ffactorize(n,rows,cols,vals,cmplx) RESULT(chol) BIND(c,NAME="cholmod_ffactorize")
USE Types
INTEGER :: n, cmplx, Rows(*), Cols(*)
REAL(KIND=dp) :: Vals(*)
INTEGER(KIND=dp) :: chol
END FUNCTION cholmod_ffactorize
SUBROUTINE cholmod_fsolve(chol, n, x,b) BIND(c,NAME="cholmod_fsolve")
USE Types
REAL(KIND=dp) :: x(*), b(*)
INTEGER :: n
INTEGER(KIND=dp) :: chol
END SUBROUTINE cholmod_fsolve
END INTERFACE
LOGICAL :: Factorize, FreeFactorize, Found
INTEGER :: i
REAL(KIND=dp), POINTER CONTIG :: Vals(:)
INTEGER, POINTER CONTIG :: Rows(:), Cols(:), Diag(:)
#ifdef HAVE_CHOLMOD
IF ( PRESENT(Free_Fact) ) THEN
IF ( Free_Fact ) THEN
IF ( A % Cholmod/=0 ) THEN
CALL cholmod_ffree(A % cholmod)
A % cholmod = 0
END IF
RETURN
END IF
END IF
Factorize = ListGetLogical( Solver % Values, &
'Linear System Refactorize', Found )
IF ( .NOT. Found ) Factorize = .TRUE.
IF ( Factorize .OR. A% cholmod==0 ) THEN
IF ( A % cholmod/=0 ) THEN
CALL cholmod_ffree(A % cholmod)
A % cholmod = 0
END IF
Rows => A % Rows
Cols => A % Cols
Vals => A % Values
Rows=Rows-1; Cols=Cols-1
i=0
IF(A % Complex) i=1
A % Cholmod=cholmod_ffactorize(A % NumberOfRows, Rows, Cols, Vals, i)
Rows=Rows+1; Cols=Cols+1
END IF
CALL cholmod_fsolve(A % cholmod, A % NumberOfRows, x, b);
FreeFactorize = ListGetLogical( Solver % Values, &
'Linear System Free Factorization', Found )
IF ( .NOT. Found ) FreeFactorize = .TRUE.
IF ( Factorize .AND. FreeFactorize ) THEN
CALL cholmod_ffree(A % cholmod)
A % cholmod = 0
END IF
#else
CALL Fatal( 'Cholmod_SolveSystem', 'Cholmod Solver has not been installed.' )
#endif
END SUBROUTINE Cholmod_SolveSystem
SUBROUTINE SPQR_SolveSystem( Solver,A,x,b,Free_fact)
LOGICAL, OPTIONAL :: Free_Fact
TYPE(Matrix_t) :: A
TYPE(Solver_t) :: Solver
REAL(KIND=dp) :: x(*), b(*)
INTEGER :: i
LOGICAL :: Factorize, FreeFactorize, Found
REAL(KIND=dp), POINTER CONTIG :: Vals(:)
INTEGER, POINTER CONTIG :: Rows(:), Cols(:), Diag(:)
INTERFACE
FUNCTION spqr_ffree(chol) RESULT(stat) BIND(c,NAME="spqr_ffree")
USE Types
INTEGER :: stat
INTEGER(KIND=AddrInt) :: chol
END FUNCTION spqr_ffree
FUNCTION spqr_ffactorize(n,rows,cols,vals) RESULT(chol) BIND(c,NAME="spqr_ffactorize")
USE Types
INTEGER :: n, rows(*), cols(*)
REAL(KIND=dp) :: vals(*)
INTEGER(KIND=AddrInt) :: chol
END FUNCTION spqr_ffactorize
SUBROUTINE spqr_fsolve(chol, n, x,b) BIND(c,NAME="spqr_fsolve")
USE Types
REAL(KIND=dp) :: x(*), b(*)
INTEGER :: n
INTEGER(KIND=AddrInt) :: chol
END SUBROUTINE spqr_fsolve
END INTERFACE
#ifdef HAVE_CHOLMOD
IF ( PRESENT(Free_Fact) ) THEN
IF ( Free_Fact ) THEN
IF ( A % Cholmod/=0 ) THEN
IF(spqr_ffree(A % cholmod)==0) A % Cholmod=0
END IF
RETURN
END IF
END IF
Factorize = ListGetLogical( Solver % Values, &
'Linear System Refactorize', Found )
IF ( .NOT. Found ) Factorize = .TRUE.
IF ( Factorize .OR. A% cholmod==0 ) THEN
IF ( A % cholmod/=0 ) THEN
i=spqr_ffree(A % cholmod)
A % cholmod = 0
END IF
Rows => A % Rows
Cols => A % Cols
Vals => A % Values
Rows=Rows-1; Cols=Cols-1
A % Cholmod=spqr_ffactorize(A % NumberOfRows, Rows, Cols, Vals)
Rows=Rows+1; Cols=Cols+1
END IF
CALL spqr_fsolve(A % cholmod, A % NumberOfRows, x, b);
FreeFactorize = ListGetLogical( Solver % Values, &
'Linear System Free Factorization', Found )
IF ( .NOT. Found ) FreeFactorize = .TRUE.
IF ( Factorize .AND. FreeFactorize ) THEN
i=spqr_ffree(A % cholmod)
A % cholmod = 0
END IF
#else
CALL Fatal( 'SPQR_SolveSystem', 'SPQR Solver has not been installed.' )
#endif
END SUBROUTINE SPQR_SolveSystem
SUBROUTINE Mumps_SolveSystem( Solver,A,x,b,Free_Fact )
#ifdef HAVE_MUMPS
# if defined(ELMER_HAVE_MPI_MODULE)
USE mpi
# endif
#endif
LOGICAL, OPTIONAL :: Free_Fact
TYPE(Matrix_t) :: A
TYPE(Solver_t) :: Solver
REAL(KIND=dp), TARGET :: x(*), b(*)
#ifdef HAVE_MUMPS
# if defined(ELMER_HAVE_MPIF_HEADER)
INCLUDE 'mpif.h'
# endif
INTEGER, ALLOCATABLE :: Owner(:)
INTEGER :: i,j,n,ip,ierr,icntlft,nzloc
LOGICAL :: Factorize, FreeFactorize, stat, matsym, matspd, scaled
INTEGER, ALLOCATABLE :: memb(:)
INTEGER :: Comm_active, Group_active, Group_world
REAL(KIND=dp), ALLOCATABLE :: dbuf(:)
IF ( PRESENT(Free_Fact) ) THEN
IF ( Free_Fact ) THEN
IF ( ASSOCIATED(A % MumpsID) ) THEN
DEALLOCATE( A % MumpsID % irn_loc, &
A % MumpsID % jcn_loc, A % MumpsID % rhs, &
A % MumpsID % isol_loc, A % MumpsID % sol_loc, A % Gorder)
A % Gorder=>Null()
A % MumpsID % job = -2
CALL DMumps(A % MumpsID)
DEALLOCATE(A % MumpsID)
END IF
RETURN
END IF
END IF
Factorize = ListGetLogical( Solver % Values, &
'Linear System Refactorize', stat )
IF ( .NOT. stat ) Factorize = .TRUE.
IF ( Factorize .OR. .NOT.ASSOCIATED(A % MumpsID) ) THEN
IF ( ASSOCIATED(A % MumpsID) ) THEN
DEALLOCATE( A % MumpsID % irn_loc, &
A % MumpsID % jcn_loc, A % MumpsID % Rhs, &
A % MumpsID % isol_loc, A % MumpsID % sol_loc, A % Gorder)
A % MumpsID % job = -2
CALL DMumps(A % MumpsID)
DEALLOCATE(A % MumpsID)
END IF
ALLOCATE(A % MumpsID)
A % MumpsID % Comm = A % Comm
A % MumpsID % par = 1
A % MumpsID % job = -1
A % MumpsID % Keep = 0
matsym = ListGetLogical( Solver % Values, 'Linear System Symmetric', stat)
matspd = ListGetLogical( Solver % Values, 'Linear System Positive Definite', stat)
scaled = ListGetLogical( Solver % Values, 'Linear System Scaling', stat)
IF(.NOT.stat) scaled = .TRUE.
IF(scaled) THEN
IF(ListGetLogical( Solver % Values, 'Linear System Row Equilibration',stat)) matsym=.FALSE.
END IF
IF(matsym) THEN
IF ( matspd) THEN
A % MumpsID % sym = 1
ELSE
A % MumpsID % sym = 0
END IF
ELSE
A % MumpsID % sym = 0
END IF
CALL DMumps(A % MumpsID)
IF(ASSOCIATED(A % Gorder)) DEALLOCATE(A % Gorder)
IF(ASSOCIATED(A % ParallelInfo)) THEN
n = SIZE(A % ParallelInfo % GlobalDOFs)
ALLOCATE( A % Gorder(n), Owner(n) )
CALL ContinuousNumbering( A % ParallelInfo, &
A % Perm, A % Gorder, Owner )
CALL MPI_ALLREDUCE( SUM(Owner), A % MumpsID % n, &
1, MPI_INTEGER, MPI_SUM, A % MumpsID % Comm, ierr )
DEALLOCATE(Owner)
ELSE
CALL MPI_ALLREDUCE( A % NumberOfRows, A % MumpsId % n, &
1, MPI_INTEGER, MPI_MAX, A % Comm, ierr )
ALLOCATE(A % Gorder(A % NumberOFrows))
DO i=1,A % NumberOFRows
A % Gorder(i) = i
END DO
END IF
IF (A % mumpsID % sym == 0) THEN
A % MumpsID % nz_loc = A % Rows(A % NumberOfRows+1)-1
ALLOCATE( A % MumpsID % irn_loc(A % MumpsID % nz_loc) )
DO i=1,A % NumberOfRows
ip = A % Gorder(i)
DO j=A % Rows(i),A % Rows(i+1)-1
A % MumpsID % irn_loc(j) = ip
END DO
END DO
ALLOCATE( A % MumpsID % jcn_loc(A % MumpsId % nz_loc) )
DO i=1,A % MumpsID % nz_loc
A % MumpsID % jcn_loc(i) = A % Gorder(A % Cols(i))
END DO
A % MumpsID % a_loc => A % values
ELSE
nzloc = 0
DO i=1,A % NumberOfRows
DO j=A % Rows(i),A % Diag(i)
nzloc = nzloc + 1
END DO
END DO
A % MumpsID % nz_loc = nzloc
ALLOCATE( A % MumpsID % irn_loc(A % MumpsID % nz_loc) )
ALLOCATE( A % MumpsID % jcn_loc(A % MumpsId % nz_loc) )
ALLOCATE( A % MumpsID % A_loc(A % MumpsId % nz_loc) )
nzloc = 0
DO i=1,A % NumberOfRows
DO j=A % Rows(i),A % Diag(i)
nzloc = nzloc + 1
A % mumpsID % IRN_loc(nzloc) = A % Gorder(i)
A % mumpsID % A_loc(nzloc) = A % Values(j)
A % mumpsID % JCN_loc(nzloc) = A % Gorder(A % Cols(j))
END DO
END DO
END IF
ALLOCATE(A % MumpsID % rhs(A % MumpsId % n))
A % MumpsID % icntl(2) = 0
A % MumpsID % icntl(3) = 0
A % MumpsID % icntl(4) = 1
A % MumpsID % icntl(5) = 0
icntlft = ListGetInteger(Solver % Values, &
'mumps percentage increase working space', stat)
IF (stat) THEN
A % MumpsID % icntl(14) = icntlft
END IF
A % MumpsID % icntl(18) = 3
A % MumpsID % icntl(21) = 1
A % MumpsID % job = 4
CALL DMumps(A % MumpsID)
CALL Flush(6)
A % MumpsID % lsol_loc = A % mumpsid % info(23)
ALLOCATE(A % MumpsID % sol_loc(A % MumpsId % lsol_loc))
ALLOCATE(A % MumpsID % isol_loc(A % MumpsId % lsol_loc))
END IF
A % MumpsID % RHS = 0
DO i=1,A % NumberOfRows
ip = A % Gorder(i)
A % MumpsId % RHS(ip) = b(i)
END DO
ALLOCATE( dbuf(A % MumpsID % n) )
dbuf = A % MumpsId % RHS
CALL MPI_ALLREDUCE( dbuf, A % MumpsID % RHS, &
A % MumpsID % n, MPI_DOUBLE_PRECISION, MPI_SUM, A % MumpsID % Comm, ierr )
A % MumpsID % job = 3
CALL DMumps(A % MumpsID)
A % MumpsId % Rhs = 0
DO i=1,A % MumpsID % lsol_loc
A % MumpsID % RHS(A % MumpsID % isol_loc(i)) = &
A % MumpsID % sol_loc(i)
END DO
dbuf = A % MumpsId % RHS
CALL MPI_ALLREDUCE( dbuf, A % MumpsID % RHS, &
A % MumpsID % N, MPI_DOUBLE_PRECISION, MPI_SUM,A % MumpsID % Comm, ierr )
DEALLOCATE(dbuf)
DO i=1,A % NumberOfRows
ip = A % Gorder(i)
x(i) = A % MumpsId % RHS(ip)
END DO
FreeFactorize = ListGetLogical( Solver % Values, &
'Linear System Free Factorization', stat )
IF ( .NOT. stat ) FreeFactorize = .TRUE.
IF ( Factorize .AND. FreeFactorize ) THEN
DEALLOCATE( A % MumpsID % irn_loc, &
A % MumpsID % jcn_loc, A % MumpsID % Rhs, &
A % MumpsID % isol_loc, A % MumpsID % sol_loc, A % Gorder)
IF ( A % MumpsID % Sym/=0 ) DEALLOCATE( A % MumpsID % A_loc )
A % Gorder=>Null()
A % MumpsID % job = -2
CALL DMumps(A % MumpsID)
DEALLOCATE(A % MumpsID)
A % MumpsId => NULL()
END IF
#else
CALL Fatal( 'Mumps_SolveSystem', 'MUMPS Solver has not been installed.' )
#endif
END SUBROUTINE Mumps_SolveSystem
SUBROUTINE MumpsLocal_SolveSystem( Solver, A, x, b, Free_Fact )
IMPLICIT NONE
TYPE(Matrix_t) :: A
TYPE(Solver_t) :: Solver
REAL(KIND=dp), TARGET :: x(*), b(*)
LOGICAL, OPTIONAL :: Free_Fact
INTEGER :: i
LOGICAL :: Factorize, FreeFactorize, stat
#ifdef HAVE_MUMPS
IF (PRESENT(Free_Fact)) THEN
IF (Free_Fact) THEN
CALL MumpsLocal_Free(A)
RETURN
END IF
END IF
Factorize = ListGetLogical( Solver % Values, &
'Linear System Refactorize', stat )
IF (.NOT. stat) Factorize = .TRUE.
IF (Factorize .OR. .NOT. ASSOCIATED(A % mumpsIDL)) THEN
CALL MumpsLocal_Factorize(Solver, A)
END IF
A % mumpsIDL % NRHS = 1
A % mumpsIDL % LRHS = A % mumpsIDL % n
DO i=1,A % NumberOfRows
A % mumpsIDL % RHS(i) = b(i)
END DO
A % mumpsIDL % job = 3
CALL DMumps(A % mumpsIDL)
DO i=1,A % NumberOfRows
x(i)=A % mumpsIDL % RHS(i)
END DO
FreeFactorize = ListGetLogical( Solver % Values, &
'Linear System Free Factorization', stat )
IF (.NOT. stat) FreeFactorize = .TRUE.
IF (Factorize .AND. FreeFactorize) CALL MumpsLocal_Free(A)
#else
CALL Fatal( 'MumpsLocal_SolveSystem', 'MUMPS Solver has not been installed.' )
#endif
END SUBROUTINE MumpsLocal_SolveSystem
SUBROUTINE MumpsLocal_Factorize(Solver, A)
#ifdef HAVE_MUMPS
# if defined(ELMER_HAVE_MPI_MODULE)
USE mpi
# endif
#endif
IMPLICIT NONE
TYPE(Solver_t) :: Solver
TYPE(Matrix_t) :: A
#ifdef HAVE_MUMPS
# if defined(ELMER_HAVE_MPIF_HEADER)
INCLUDE 'mpif.h'
# endif
INTEGER :: i, j, n, nz, allocstat, icntlft, ptype, nzloc
LOGICAL :: matpd, matsym, nullpiv, stat
IF ( ASSOCIATED(A % mumpsIDL) ) THEN
CALL MumpsLocal_Free(A)
END IF
ALLOCATE(A % mumpsIDL)
A % mumpsIDL % COMM = MPI_COMM_SELF
A % mumpsIDL % PAR = 1
matsym = ListGetLogical(Solver % Values, &
'Linear System Symmetric', stat)
matpd = ListGetLogical(Solver % Values, &
'Linear System Positive Definite', stat)
A % mumpsIDL % SYM = 0
IF (matsym) THEN
IF (matpd) THEN
A % mumpsIDL % SYM = 1
ELSE
A % mumpsIDL % SYM = 2
END IF
ELSE
A % mumpsIDL % SYM = 0
END IF
A % mumpsIDL % JOB = -1
CALL DMumps(A % mumpsIDL)
A % mumpsIDL % ICNTL(1) = 6
A % mumpsIDL % ICNTL(2) = -1
A % mumpsIDL % ICNTL(3) = -1
A % mumpsIDL % ICNTL(4) = 1
A % mumpsIDL % ICNTL(5) = 0
A % mumpsIDL % ICNTL(18) = 0
A % mumpsIDL % ICNTL(21) = 0
A % mumpsIDL % ICNTL(24) = 0
nullpiv = ListGetLogical(Solver % Values, &
'Mumps Solve Singular', stat)
IF (nullpiv) THEN
A % mumpsIDL % ICNTL(24) = 1
A % mumpsIDL % CNTL(1) = 1D-2
A % mumpsIDL % CNTL(3) = 1D-9
A % mumpsIDL % CNTL(5) = 1D6
A % mumpsIDL % CNTL(13) = 1
END IF
ptype = ListGetInteger(Solver % Values, &
'Mumps Permutation Type', stat)
IF (stat) THEN
A % mumpsIDL % ICNTL(6) = ptype
END IF
n = A % NumberofRows
nz = A % Rows(A % NumberOfRows+1)-1
A % mumpsIDL % N = n
A % mumpsIDL % NZ = nz
ALLOCATE( A % mumpsIDL % IRN(nz), &
A % mumpsIDL % JCN(nz), &
A % mumpsIDL % A(nz), STAT=allocstat)
IF (allocstat /= 0) THEN
CALL Fatal('MumpsLocal_Factorize', &
'Memory allocation for MUMPS row and column indices failed.')
END IF
IF (A % mumpsIDL % sym == 0) THEN
DO i=1,A % NumberOfRows
DO j=A % Rows(i),A % Rows(i+1)-1
A % mumpsIDL % IRN(j) = i
END DO
END DO
DO i=1,A % mumpsIDL % nz
A % mumpsIDL % JCN(i) = A % Cols(i)
END DO
DO i=1,A % mumpsIDL % nz
A % mumpsIDL % A(i) = A % Values(i)
END DO
ELSE
nzloc = 0
DO i=1,A % NumberOfRows
DO j=A % Rows(i),A % Rows(i+1)-1
IF (i<=A % Cols(j)) THEN
nzloc = nzloc + 1
A % mumpsIDL % IRN(nzloc) = i
A % mumpsIDL % JCN(nzloc) = A % Cols(j)
A % mumpsIDL % A(nzloc) = A % Values(j)
END IF
END DO
END DO
END IF
icntlft = ListGetInteger(Solver % Values, 'mumps percentage increase working space', stat)
IF (stat) THEN
A % mumpsIDL % ICNTL(14) = icntlft
END IF
A % mumpsIDL % JOB = 1
CALL DMumps(A % mumpsIDL)
CALL Flush(6)
IF (A % mumpsIDL % INFO(1)<0) THEN
CALL Fatal('MumpsLocal_Factorize','Mumps analysis phase failed')
END IF
A % mumpsIDL % JOB = 2
CALL DMumps(A % mumpsIDL)
CALL Flush(6)
IF (A % mumpsIDL % INFO(1)<0) THEN
CALL Fatal('MumpsLocal_Factorize','Mumps factorize phase failed')
END IF
ALLOCATE(A % mumpsIDL % RHS(A % mumpsIDL % N), STAT=allocstat)
IF (allocstat /= 0) THEN
CALL Fatal('MumpsLocal_Factorize', &
'Memory allocation for MUMPS solution vector and RHS failed.' )
END IF
#else
CALL Fatal( 'MumpsLocal_Factorize', 'MUMPS Solver has not been installed.' )
#endif
END SUBROUTINE MumpsLocal_Factorize
SUBROUTINE MumpsLocal_SolveNullSpace(Solver, A, z, nz)
#ifdef HAVE_MUMPS
# if defined(ELMER_HAVE_MPI_MODULE)
USE mpi
# endif
#endif
IMPLICIT NONE
TYPE(Solver_t) :: Solver
TYPE(Matrix_t) :: A
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:,:), TARGET :: z
INTEGER :: nz, nrhs
#ifdef HAVE_MUMPS
# if defined(ELMER_HAVE_MPIF_HEADER)
INCLUDE 'mpif.h'
# endif
INTEGER :: j,k,n, allocstat
LOGICAL :: Factorize, FreeFactorize, stat
REAL(KIND=dp), DIMENSION(:), POINTER :: rhs_tmp, nspace
Factorize = ListGetLogical( Solver % Values,&
'Linear System Refactorize', stat )
IF (.NOT. stat) Factorize = .TRUE.
IF ( Factorize .OR. (.NOT. ASSOCIATED(A % mumpsIDL)) ) THEN
CALL MumpsLocal_Factorize(Solver, A)
END IF
IF (.NOT. (A % mumpsIDL % sym == 1 .OR. A % mumpsIDL % sym == 2)) THEN
CALL Fatal( 'MumpsLocal_SolveNullSpace', &
'Mumps null space computation not supported for unsymmetric matrices.')
END IF
n = A % NumberOfRows
nz = A % mumpsIDL % INFOG(28)
IF (nz == 0) THEN
ALLOCATE(z(nz,n))
RETURN
END IF
ALLOCATE(nspace(n*nz), STAT=allocstat)
IF (allocstat /= 0) THEN
CALL Fatal( 'MumpsLocal_SolveNullSpace', &
'Storage allocation for local nullspace failed.')
END IF
rhs_tmp => A % mumpsIDL % RHS
nrhs = A % mumpsIDL % NRHS
A % mumpsIDL % RHS => nspace
A % mumpsIDL % NRHS = nz
A % mumpsIDL % JOB = 3
A % mumpsIDL % ICNTL(25) = -1
CALL DMumps(A % mumpsIDL)
IF (A % mumpsIDL % INFO(1)<0) THEN
CALL Fatal('MumpsLocal_SolveNullSpace','Mumps nullspace solution failed')
END IF
A % mumpsIDL % ICNTL(25) = 0
A % mumpsIDL % RHS => rhs_tmp
A % mumpsIDL % NRHS = nrhs
FreeFactorize = ListGetLogical( Solver % Values, &
'Linear System Free Factorization', stat )
IF (.NOT. stat) FreeFactorize = .TRUE.
IF (Factorize .AND. FreeFactorize) THEN
CALL MumpsLocal_Free(A)
END IF
ALLOCATE(z(nz,n), STAT=allocstat)
IF (allocstat /= 0) THEN
CALL Fatal( 'MumpsLocal_SolveNullSpace', &
'Storage allocation for local nullspace failed.')
END IF
DO j=1,nz
DO k=1,n
z(j,k)=nspace(n*(j-1)+k)
END DO
END DO
DEALLOCATE(nspace)
#else
CALL Fatal( 'MumpsLocal_SolveNullSpace', 'MUMPS Solver has not been installed.' )
#endif
END SUBROUTINE MumpsLocal_SolveNullSpace
SUBROUTINE MumpsLocal_Free(A)
IMPLICIT NONE
TYPE(Matrix_t) :: A
#ifdef HAVE_MUMPS
IF (ASSOCIATED(A % mumpsIDL)) THEN
DEALLOCATE( A % mumpsIDL % irn, A % mumpsIDL % jcn, &
A % mumpsIDL % a, A % mumpsIDL % rhs)
A % mumpsIDL % job = -2
CALL DMumps(A % mumpsIDL)
DEALLOCATE(A % mumpsIDL)
A % mumpsIDL => Null()
END IF
#else
CALL Fatal( 'MumpsLocal_Free', 'MUMPS Solver has not been installed.' )
#endif
END SUBROUTINE MumpsLocal_Free
SUBROUTINE SuperLU_SolveSystem( Solver,A,x,b,Free_Fact )
LOGICAL, OPTIONAL :: Free_fact
TYPE(Matrix_t) :: A
TYPE(Solver_t) :: Solver
REAL(KIND=dp), TARGET :: x(*), b(*)
#ifdef HAVE_SUPERLU
LOGICAL :: stat, Factorize, FreeFactorize
integer :: n, nnz, nrhs, iinfo, iopt, nprocs
interface
subroutine solve_superlu( iopt, nprocs, n, nnz, nrhs, values, cols, &
rows, b, ldb, factors, iinfo )
use types
integer :: iopt, nprocs, n, nnz, nrhs, cols(*), rows(*), ldb, iinfo
real(kind=dp) :: values(*), b(*)
integer(kind=addrint) :: factors
end subroutine solve_superlu
end interface
IF ( PRESENT(Free_Fact) ) THEN
IF ( Free_Fact ) THEN
IF ( A % SuperLU_Factors/= 0 ) THEN
iopt = 3
CALL Solve_SuperLU( iopt, nprocs, n, nnz, nrhs, A % Values, &
A % Cols, A % Rows, x, n, A % SuperLU_Factors, iinfo )
A % SuperLU_Factors = 0
END IF
RETURN
END IF
END IF
n = A % NumberOfRows
nrhs = 1
x(1:n) = b(1:n)
nnz = A % Rows(n+1)-1
nprocs = ListGetInteger( Solver % Values, &
'Linear System Number of Threads', stat )
IF ( .NOT. stat ) nprocs = 1
Factorize = ListGetLogical( Solver % Values, &
'Linear System Refactorize', stat )
IF ( .NOT. stat ) Factorize = .TRUE.
IF ( Factorize .OR. A % SuperLU_Factors==0 ) THEN
IF ( A % SuperLU_Factors/= 0 ) THEN
iopt = 3
call Solve_SuperLU( iopt, nprocs, n, nnz, nrhs, A % Values, A % Cols, &
A % Rows, x, n, A % SuperLU_Factors, iinfo )
A % SuperLU_Factors=0
END IF
iopt = 1
call Solve_SuperLU( iopt, nprocs, n, nnz, nrhs, A % Values, A % Cols, &
A % Rows, x, n, A % SuperLU_Factors, iinfo )
if (iinfo .eq. 0) then
write (*,*) 'Factorization succeeded'
else
write(*,*) 'INFO from factorization = ', iinfo
endif
END IF
iopt = 2
call Solve_SuperLU( iopt, nprocs, n, nnz, nrhs, A % Values, A % Cols, &
A % Rows, x, n, A % SuperLU_Factors, iinfo )
if (iinfo .eq. 0) then
write (*,*) 'Solve succeeded'
else
write(*,*) 'INFO from triangular solve = ', iinfo
endif
FreeFactorize = ListGetLogical( Solver % Values, &
'Linear System Free Factorization', stat )
IF ( .NOT. stat ) FreeFactorize = .TRUE.
IF ( Factorize .AND. FreeFactorize ) THEN
iopt = 3
call Solve_SuperLU( iopt, nprocs, n, nnz, nrhs, A % Values, A % Cols, &
A % Rows, x, n, A % SuperLU_Factors, iinfo )
A % SuperLU_Factors = 0
END IF
#endif
END SUBROUTINE SuperLU_SolveSystem
SUBROUTINE Permon_SolveSystem( Solver,A,x,b,Free_Fact )
#ifdef HAVE_FETI4I
USE feti4i
# if defined(ELMER_HAVE_MPI_MODULE)
USE mpi
# endif
#endif
LOGICAL, OPTIONAL :: Free_Fact
TYPE(Matrix_t) :: A
TYPE(Solver_t) :: Solver
REAL(KIND=dp), TARGET :: x(*), b(*)
#ifdef HAVE_FETI4I
# if defined(ELMER_HAVE_MPIF_HEADER)
INCLUDE 'mpif.h'
# endif
INTEGER, ALLOCATABLE :: Owner(:)
INTEGER :: i,j,n,nd,ip,ierr,icntlft,nzloc
LOGICAL :: Factorize, FreeFactorize, stat, matsym, matspd, scaled
INTEGER :: n_dof_partition
INTEGER, ALLOCATABLE :: memb(:), DirichletInds(:), Neighbours(:), IntOptions(:)
REAL(KIND=dp), ALLOCATABLE :: DirichletVals(:), RealOptions(:)
INTEGER :: Comm_active, Group_active, Group_world
REAL(KIND=dp), ALLOCATABLE :: dbuf(:)
n_dof_partition = A % NumberOfRows
IF ( PRESENT(Free_Fact) ) THEN
IF ( Free_Fact ) THEN
RETURN
END IF
END IF
Factorize = ListGetLogical( Solver % Values, 'Linear System Refactorize', stat )
IF ( .NOT. stat ) Factorize = .TRUE.
IF ( Factorize .OR. .NOT.C_ASSOCIATED(A % PermonSolverInstance) ) THEN
IF ( C_ASSOCIATED(A % PermonSolverInstance) ) THEN
CALL Fatal( 'Permon', 're-entry not implemented' )
END IF
nd = COUNT(A % ConstrainedDOF)
ALLOCATE(DirichletInds(nd), DirichletVals(nd))
j = 0
DO i=1,A % NumberOfRows
IF(A % ConstrainedDOF(i)) THEN
j = j + 1
DirichletInds(j) = i; DirichletVals(j) = A % Dvalues(i)
END IF
END DO
n = 0
ALLOCATE(neighbours(Parenv % PEs))
DO i=1,ParEnv % PEs
IF( ParEnv % IsNeighbour(i) .AND. i-1/=ParEnv % myPE) THEN
n = n + 1
neighbours(n) = i-1
END IF
END DO
IF( n_dof_partition /= SIZE(A % ParallelInfo % GlobalDOFs) ) THEN
CALL Fatal( 'Permon', &
'inconsistency: A % NumberOfRows /= SIZE(A % ParallelInfo % GlobalDOFs' )
END IF
ALLOCATE(IntOptions(10))
ALLOCATE(RealOptions(1))
CALL FETI4ISetDefaultIntegerOptions(IntOptions)
CALL FETI4ISetDefaultRealOptions(RealOptions)
CALL FETI4ICreateInstance(A % PermonSolverInstance, A % PermonMatrix, &
A % NumberOfRows, b, A % ParallelInfo % GlobalDOFs, &
n, neighbours, &
nd, DirichletInds, DirichletVals, &
IntOptions, RealOptions)
END IF
CALL FETI4ISolve(A % PermonSolverInstance, n_dof_partition, x)
#else
CALL Fatal( 'Permon_SolveSystem', 'Permon Solver has not been installed.' )
#endif
END SUBROUTINE Permon_SolveSystem
SUBROUTINE Pardiso_SolveSystem( Solver,A,x,b,Free_fact )
IMPLICIT NONE
TYPE(Solver_t) :: Solver
TYPE(Matrix_t) :: A
REAL(KIND=dp), TARGET :: x(*), b(*)
LOGICAL, OPTIONAL :: Free_fact
#if defined(HAVE_MKL)
INTERFACE
SUBROUTINE pardiso(pt, maxfct, mnum, mtype, phase, n, &
values, rows, cols, perm, nrhs, iparm, msglvl, b, x, ierror)
USE Types
IMPLICIT NONE
REAL(KIND=dp) :: values(*), b(*), x(*)
INTEGER(KIND=AddrInt) :: pt(*)
INTEGER :: perm(*), nrhs, iparm(*), msglvl, ierror
INTEGER :: maxfct, mnum, mtype, phase, n, rows(*), cols(*)
END SUBROUTINE pardiso
SUBROUTINE pardisoinit(pt, mtype, iparm)
USE Types
IMPLICIT NONE
INTEGER(KIND=AddrInt) :: pt(*)
INTEGER :: mtype
INTEGER :: iparm(*)
END SUBROUTINE pardisoinit
END INTERFACE
INTEGER maxfct, mnum, mtype, phase, n, nrhs, ierror, msglvl
INTEGER, POINTER :: Iparm(:)
INTEGER i, j, k, nz, idum(1), nzutd
LOGICAL :: Found, matsym, matpd
REAL*8 :: ddum(1)
LOGICAL :: Factorize, FreeFactorize
INTEGER :: tlen, allocstat
CHARACTER(:), ALLOCATABLE :: mat_type
REAL(KIND=dp), POINTER :: values(:)
INTEGER, POINTER :: rows(:), cols(:)
Factorize = ListGetLogical( Solver % Values, &
'Linear System Refactorize', Found )
IF ( .NOT. Found ) Factorize = .TRUE.
mat_type = ListGetString(Solver % Values,'Linear System Matrix Type',Found)
IF (Found) THEN
SELECT CASE(mat_type)
CASE('positive definite')
mtype = 2
CASE('symmetric indefinite')
mtype = -2
CASE('structurally symmetric')
mtype = 1
CASE('nonsymmetric', 'general')
mtype = 11
CASE DEFAULT
mtype = 11
END SELECT
ELSE
matsym = ListGetLogical(Solver % Values, &
'Linear System Symmetric', Found)
matpd = ListGetLogical(Solver % Values, &
'Linear System Positive Definite', Found)
IF (matsym) THEN
IF (matpd) THEN
mtype = 2
ELSE
mtype = 1
END IF
ELSE
mtype = 11
END IF
END IF
IF ( PRESENT(Free_Fact) ) THEN
IF ( Free_Fact ) THEN
IF(ASSOCIATED(A % PardisoId)) THEN
phase = -1
n = A % NumberOfRows
maxfct = 1
mnum = 1
nrhs = 1
msglvl = 0
CALL pardiso(A % PardisoId, maxfct, mnum, mtype, phase, n, &
ddum, idum, idum, idum, nrhs, A % PardisoParam, msglvl, ddum, ddum, ierror)
DEALLOCATE(A % PardisoId, A % PardisoParam)
A % PardisoId => NULL()
A % PardisoParam => NULL()
END IF
RETURN
END IF
END IF
n = A % Numberofrows
nz = A % Rows(n+1)-1
IF ( ABS(mtype) == 2 ) THEN
nzutd = 0
DO i=1,n
nzutd = nzutd + A % Rows(i+1)-A % Diag(i)
END DO
ALLOCATE( values(nzutd), cols(nzutd), rows(n+1), STAT=allocstat)
IF (allocstat /= 0) THEN
CALL Fatal('Pardiso_SolveSystem', &
'Memory allocation for row and column indices failed')
END IF
Rows(1)=1
DO i=1,n
nzutd = A % Rows(i+1)-A % Diag(i)
Rows(i+1) = Rows(i)+nzutd
DO j=0,nzutd-1
Cols(Rows(i)+j)=A % Cols(A%Diag(i)+j)
Values(Rows(i)+j)=A % Values(A%Diag(i)+j)
END DO
END DO
ELSE
Cols => A % Cols
Rows => A % Rows
Values => A % Values
END IF
msglvl = 0
maxfct = 1
mnum = 1
nrhs = 1
iparm => A % PardisoParam
IF ( Factorize .OR. .NOT.ASSOCIATED(A % PardisoID) ) THEN
IF (ASSOCIATED(A % PardisoId)) THEN
phase = -1
CALL pardiso (A % PardisoId, maxfct, mnum, mtype, phase, n, &
ddum, idum, idum, idum, nrhs, iparm, msglvl, ddum, ddum, ierror)
DEALLOCATE(A % PardisoId, A % PardisoParam)
A % PardisoId => NULL()
A % PardisoParam => NULL()
END IF
ALLOCATE(A % PardisoId(64), A % PardisoParam(64), STAT=allocstat)
IF (allocstat /= 0) THEN
CALL Fatal('Pardiso_SolveSystem', &
'Memory allocation for Pardiso failed')
END IF
iparm => A % PardisoParam
iparm = 0
A % PardisoId = 0
CALL pardisoinit(A % PardisoId, mtype, iparm)
iparm(1)=1
iparm(2)=2
iparm(3)=0
iparm(4)=0
iparm(5)=0
iparm(6)=0
iparm(8)=5
iparm(18)=-1
iparm(19)=0
iparm(27)=0
iparm(35)=0
iparm(60)=0
phase = 11
CALL pardiso(A % PardisoId, maxfct, mnum, mtype, phase, n, &
values, rows, cols, idum, nrhs, iparm, msglvl, ddum, ddum, ierror)
IF (ierror /= 0) THEN
WRITE(*,'(A,I0)') 'MKL Pardiso: ERROR=', ierror
CALL Fatal('Pardiso_SolveSystem','Error during analysis phase')
END IF
phase = 22
CALL pardiso (A % pardisoId, maxfct, mnum, mtype, phase, n, &
values, rows, cols, idum, nrhs, iparm, msglvl, ddum, ddum, ierror)
IF (ierror /= 0) THEN
WRITE(*,'(A,I0)') 'MKL Pardiso: ERROR=', ierror
CALL Fatal('Pardiso_SolveSystem','Error during factorization phase')
END IF
END IF
phase = 33
CALL pardiso(A % PardisoId, maxfct, mnum, mtype, phase, n, &
values, rows, cols, idum, nrhs, iparm, msglvl, b, x, ierror)
IF (ierror /= 0) THEN
WRITE(*,'(A,I0)') 'MKL Pardiso: ERROR=', ierror
CALL Fatal('Pardiso_SolveSystem','Error during solve phase')
END IF
FreeFactorize = ListGetLogical( Solver % Values, &
'Linear System Free Factorization', Found )
IF ( .NOT. Found ) FreeFactorize = .TRUE.
IF ( Factorize .AND. FreeFactorize ) THEN
phase = -1
CALL pardiso (A % PardisoId, maxfct, mnum, mtype, phase, n, &
ddum, idum, idum, idum, nrhs, iparm, msglvl, ddum, ddum, ierror)
DEALLOCATE(A % PardisoId, A % PardisoParam)
A % PardisoId => NULL()
A % PardisoParam => NULL()
END IF
IF (ABS(mtype) == 2) DEALLOCATE(Values, Rows, Cols)
#elif defined(HAVE_PARDISO)
INTERFACE
SUBROUTINE pardiso(pt, maxfct, mnum, mtype, phase, n, &
values, rows, cols, idum, nrhs, iparm, msglvl, b, x, ierror, dparm)
USE Types
REAL(KIND=dp) :: values(*), b(*), x(*), dparm(*)
INTEGER(KIND=AddrInt) :: pt(*)
INTEGER :: idum(*), nrhs, iparm(*), msglvl, ierror
INTEGER :: maxfct, mnum, mtype, phase, n, rows(*), cols(*)
END SUBROUTINE pardiso
SUBROUTINE pardisoinit(pt,mtype,solver,iparm,dparm,ierror)
USE Types
INTEGER :: mtype, iparm(*),ierror,solver
REAL(KIND=dp) :: dparm(*)
INTEGER(KIND=AddrInt) :: pt(*)
END SUBROUTINE pardisoinit
END INTERFACE
INTEGER maxfct, mnum, mtype, phase, n, nrhs, ierror, msglvl
INTEGER, POINTER :: Iparm(:)
INTEGER i, j, k, nz, idum(1)
LOGICAL :: Found, Symm, Posdef
REAL*8 waltime1, waltime2, ddum(1), dparm(64)
LOGICAL :: Factorize, FreeFactorize
INTEGER :: tlen
CHARACTER(LEN=16) :: threads
REAL(KIND=dp), POINTER :: values(:)
INTEGER, POINTER :: rows(:), cols(:)
IF ( PRESENT(Free_Fact) ) THEN
IF ( Free_Fact ) THEN
IF(ASSOCIATED(A % PardisoId)) THEN
phase = -1
n = A % NumberOfRows
mtype = 11
maxfct = 1
mnum = 1
nrhs = 1
msglvl = 0
CALL pardiso(A % PardisoId, maxfct, mnum, mtype, phase, n, &
ddum, idum, idum, idum, nrhs, A % PardisoParam, msglvl, ddum, ddum, ierror,dparm)
DEALLOCATE(A % PardisoId, A % PardisoParam)
A % PardisoId => NULL()
A % PardisoParam => NULL()
END IF
RETURN
END IF
END IF
Factorize = ListGetLogical( Solver % Values, &
'Linear System Refactorize', Found )
IF ( .NOT. Found ) Factorize = .TRUE.
symm = ListGetLogical( Solver % Values, &
'Linear System Symmetric', Found )
posdef = ListGetLogical( Solver % Values, &
'Linear System Positive Definite', Found )
mtype = 11
cols => a % cols
rows => a % rows
values => a % values
n = A % Numberofrows
IF ( posdef ) THEN
nz = A % rows(n+1)-1
allocate( values(nz), cols(nz), rows(n+1) )
k = 1
do i=1,n
rows(i)=k
do j=a % rows(i), a % rows(i+1)-1
if ( a % cols(j)>=i .and. a % values(j) /= 0._dp ) then
cols(k) = a % cols(j)
values(k) = a % values(j)
k = k + 1
end if
end do
end do
rows(n+1)=k
mtype = 2
ELSE IF ( symm ) THEN
mtype = 1
END IF
msglvl = 0
maxfct = 1
mnum = 1
nrhs = 1
iparm => A % PardisoParam
IF ( Factorize .OR. .NOT.ASSOCIATED(A % PardisoID) ) THEN
IF(ASSOCIATED(A % PardisoId)) THEN
phase = -1
CALL pardiso (A % PardisoId, maxfct, mnum, mtype, phase, n, &
ddum, idum, idum, idum, nrhs, iparm, msglvl, ddum, ddum, ierror,dparm)
DEALLOCATE(A % PardisoId, A % PardisoParam)
A % PardisoId => NULL()
A % PardisoParam => NULL()
END IF
ALLOCATE(A % PardisoId(64), A % PardisoParam(64))
iparm => A % PardisoParam
CALL pardisoinit(A % PardisoId, mtype, 0, iparm, dparm, ierror )
phase = 11
msglvl = 0
maxfct = 1
mnum = 1
nrhs = 1
CALL envir( 'OMP_NUM_THREADS', threads, tlen )
iparm(3) = 1
IF ( tlen>0 ) &
READ(threads(1:tlen),*) iparm(3)
IF (iparm(3)<=0) Iparm(3) = 1
CALL pardiso(A % PardisoId, maxfct, mnum, mtype, phase, n, &
values, rows, cols, idum, nrhs, iparm, msglvl, ddum, ddum, ierror, dparm)
IF (ierror /= 0) THEN
WRITE(*,*) 'The following ERROR was detected: ', ierror
STOP EXIT_ERROR
END IF
phase = 22
CALL pardiso (A % pardisoId, maxfct, mnum, mtype, phase, n, &
values, rows, cols, idum, nrhs, iparm, msglvl, ddum, ddum, ierror, dparm)
IF (ierror /= 0) THEN
WRITE(*,*) 'The following ERROR was detected: ', ierror
STOP EXIT_ERROR
ENDIF
END IF
phase = 33
iparm(8) = 0
CALL pardiso(A % PardisoId, maxfct, mnum, mtype, phase, n, &
values, rows, cols, idum, nrhs, iparm, msglvl, b, x, ierror, dparm)
FreeFactorize = ListGetLogical( Solver % Values, &
'Linear System Free Factorization', Found )
IF ( .NOT. Found ) FreeFactorize = .TRUE.
IF ( Factorize .AND. FreeFactorize ) THEN
phase = -1
CALL pardiso (A % PardisoId, maxfct, mnum, mtype, phase, n, &
ddum, idum, idum, idum, nrhs, iparm, msglvl, ddum, ddum, ierror, dparm)
DEALLOCATE(A % PardisoId, A % PardisoParam)
A % PardisoId => NULL()
A % PardisoParam => NULL()
END IF
IF(posdef) DEALLOCATE( values, rows, cols )
#else
CALL Fatal( 'Parsido_SolveSystem', 'Pardiso solver has not been installed.' )
#endif
END SUBROUTINE Pardiso_SolveSystem
SUBROUTINE CPardiso_SolveSystem( Solver,A,x,b,Free_fact )
IMPLICIT NONE
TYPE(Solver_t) :: Solver
TYPE(Matrix_t) :: A
REAL(KIND=dp), TARGET :: x(*), b(*)
LOGICAL, OPTIONAL :: Free_fact
#if defined(HAVE_MKL) && defined(HAVE_CPARDISO)
INTERFACE
SUBROUTINE cluster_sparse_solver(pt, maxfct, mnum, mtype, phase, n, &
values, rows, cols, perm, nrhs, iparm, msglvl, b, x, comm, ierror)
USE Types
REAL(KIND=dp) :: values(*), b(*), x(*)
INTEGER(KIND=AddrInt) :: pt(*)
INTEGER :: perm(*), nrhs, iparm(*), msglvl, ierror
INTEGER :: maxfct, mnum, mtype, phase, n, rows(*), cols(*), comm
END SUBROUTINE cluster_sparse_solver
END INTERFACE
INTEGER :: phase, n, ierror
INTEGER, POINTER :: Iparm(:)
INTEGER i, j, k, nz, nzutd, idum(1), nl, nt
LOGICAL :: Found, matsym, matpd
REAL(kind=dp) :: ddum(1)
REAL(kind=dp), POINTER, DIMENSION(:) :: dbuf
LOGICAL :: Factorize, FreeFactorize
INTEGER :: tlen, allocstat
REAL(KIND=dp), POINTER CONTIG :: values(:)
INTEGER, POINTER CONTIG :: rows(:), cols(:)
IF ( PRESENT(Free_Fact) ) THEN
IF ( Free_Fact ) THEN
CALL CPardiso_Free(A)
END IF
RETURN
END IF
Factorize = ListGetLogical( Solver % Values, &
'Linear System Refactorize', Found )
IF ( .NOT. Found ) Factorize = .TRUE.
IF ( Factorize .OR. .NOT.ASSOCIATED(A % CPardisoID) ) THEN
CALL CPardiso_Factorize(Solver, A)
END IF
nl = A % CPardisoId % iparm(41)
nt = A % CPardisoId % iparm(42)
A % CPardisoId % rhs = 0D0
DO i=1,A % NumberOfRows
A % CPardisoId % rhs(A % Gorder(i)-nl+1) = b(i)
END DO
phase = 33
CALL cluster_sparse_solver(A % CPardisoId % ID, &
A % CPardisoId % maxfct, A % CPardisoId % mnum, &
A % CPardisoId % mtype, phase, A % CPardisoId % n, &
A % CPardisoID % aa, A % CPardisoID % ia, A % CPardisoID % ja, idum, &
A % CPardisoId % nrhs, A % CPardisoID % iparm, &
A % CPardisoId % msglvl, A % CPardisoId % rhs, &
A % CPardisoId % x, A % Comm, ierror)
IF (ierror /= 0) THEN
WRITE(*,'(A,I0)') 'MKL CPardiso: ERROR=', ierror
CALL Fatal('CPardiso_SolveSystem','Error during solve phase')
END IF
DO i=1,A % NumberOfRows
x(i)=A % CPardisoId % x(A % Gorder(i)-nl+1)
END DO
FreeFactorize = ListGetLogical( Solver % Values, &
'Linear System Free Factorization', Found )
IF ( .NOT. Found ) FreeFactorize = .TRUE.
IF ( Factorize .AND. FreeFactorize ) THEN
CALL CPardiso_Free(A)
END IF
#else
CALL Fatal( 'CParsido_SolveSystem', 'Cluster Pardiso solver has not been installed.' )
#endif
END SUBROUTINE CPardiso_SolveSystem
#if defined(HAVE_MKL) && defined(HAVE_CPARDISO)
SUBROUTINE CPardiso_Factorize(Solver, A)
IMPLICIT NONE
TYPE(Solver_t) :: Solver
TYPE(Matrix_t) :: A
INTERFACE
SUBROUTINE cluster_sparse_solver(pt, maxfct, mnum, mtype, phase, n, &
values, rows, cols, perm, nrhs, iparm, msglvl, b, x, comm, ierror)
USE Types
REAL(KIND=dp) :: values(*), b(*), x(*)
INTEGER(KIND=AddrInt) :: pt(*)
INTEGER :: perm(*), nrhs, iparm(*), msglvl, ierror
INTEGER :: maxfct, mnum, mtype, phase, n, rows(*), cols(*), comm
END SUBROUTINE cluster_sparse_solver
END INTERFACE
LOGICAL :: matsym, matpd, Found
INTEGER :: i, j, k, rind, lrow, rptr, rsize, lind, tind
INTEGER :: allocstat, n, nz, nzutd, nl, nt, nOwned, nhalo, ierror
INTEGER :: phase, idum(1)
REAL(kind=dp) :: ddum(1)
REAL(kind=dp), DIMENSION(:), POINTER :: aa
INTEGER, DIMENSION(:), POINTER CONTIG :: iparm, ia, ja, owner, dsize, iperm, Order
INTEGER :: fid
CHARACTER(:), ALLOCATABLE :: mat_type
IF (ASSOCIATED(A % CPardisoId)) THEN
CALL CPardiso_Free(A)
END IF
ALLOCATE(A % CPardisoId, STAT=allocstat)
IF (allocstat /= 0) THEN
CALL Fatal('CPardiso_Factorize', &
'Memory allocation for CPardiso failed')
END IF
ALLOCATE(A % CPardisoId% ID(64), A % CPardisoId % IParm(64), STAT=allocstat)
IF (allocstat /= 0) THEN
CALL Fatal('CPardiso_Factorize', &
'Memory allocation for CPardiso failed')
END IF
iparm => A % CPardisoId % IParm
DO i=1,64
iparm(i)=0
END DO
DO i=1,64
A % CPardisoId % ID(i)=0
END DO
mat_type = ListGetString(Solver % Values,'Linear System Matrix Type',Found)
IF (Found) THEN
SELECT CASE(mat_type)
CASE('positive definite')
A % CPardisoID % mtype = 2
CASE('symmetric indefinite')
A % CPardisoID % mtype = -2
CASE('structurally symmetric')
A % CPardisoID % mtype = 1
CASE('nonsymmetric', 'general')
A % CPardisoID % mtype = 11
CASE DEFAULT
A % CPardisoID % mtype = 11
END SELECT
ELSE
matsym = ListGetLogical(Solver % Values, &
'Linear System Symmetric', Found)
matpd = ListGetLogical(Solver % Values, &
'Linear System Positive Definite', Found)
IF (matsym) THEN
IF (matpd) THEN
A % CPardisoID % mtype = 2
ELSE
A % CPardisoID % mtype = 1
END IF
ELSE
A % CPardisoID % mtype = 11
END IF
END IF
n = SIZE(A % ParallelInfo % GlobalDOFs)
ALLOCATE(A % Gorder(n), Owner(n), STAT=allocstat)
IF (allocstat /= 0) THEN
CALL Fatal('CPardiso_Factorize', &
'Memory allocation for CPardiso global numbering failed')
END IF
CALL ContinuousNumbering(A % ParallelInfo, A % Perm, A % Gorder, Owner, nOwn=nOwned)
CALL MPI_ALLREDUCE(nOwned, A % CPardisoId % n, &
1, MPI_INTEGER, MPI_SUM, A % Comm, ierror)
DEALLOCATE(Owner)
nl = A % Gorder(1)
nt = A % Gorder(1)
DO i=2,n
rind = A % Gorder(i)
nl = MIN(rind, nl)
nt = MAX(rind, nt)
END DO
ALLOCATE(Order(n), iperm(n), STAT=allocstat)
IF (allocstat /= 0) THEN
CALL Fatal('CPardiso_Factorize', &
'Memory allocation for CPardiso global numbering failed')
END IF
Order(1:n) = A % Gorder(1:n)
DO i=1,n
iperm(i)=i
END DO
CALL SortI(n, Order, iperm)
nhalo = (nt-nl+1)-n
nz = A % Rows(A % NumberOfRows+1)-1
IF (ABS(A % CPardisoID % mtype) == 2) THEN
nzutd = ((nz-n)/2)+1 + n
ALLOCATE(A % CPardisoID % ia(nt-nl+2), &
A % CPardisoId % ja(nzutd+nhalo), &
A % CPardisoId % aa(nzutd+nhalo), &
STAT=allocstat)
ELSE
ALLOCATE(A % CPardisoID % ia(nt-nl+2), &
A % CPardisoId % ja(nz+nhalo), &
A % CPardisoId % aa(nz+nhalo), &
STAT=allocstat)
END IF
IF (allocstat /= 0) THEN
CALL Fatal('CPardiso_Factorize', &
'Memory allocation for CPardiso matrix failed')
END IF
ia => A % CPardisoId % ia
ja => A % CPardisoId % ja
aa => A % CPardisoId % aa
ia(1) = 1
lrow = 1
rptr = 1
lind = Order(1)-1
DO i=1,n
tind = Order(i)
rsize = (tind-lind)-1
DO j=1,rsize
ia(lrow+j)=rptr+j
ja(rptr+(j-1))=lind+j
aa(rptr+(j-1))=0D0
END DO
rptr = rptr + rsize
lrow = lrow + rsize
rind = iperm(i)
lind = A % rows(rind)
tind = A % rows(rind+1)
IF (ABS(A % CPardisoId % mtype) == 2) THEN
rsize = 0
DO j=lind, tind-1
IF (A % Gorder(A % Cols(j)) >= Order(i)) THEN
ja(rptr+rsize)=A % Gorder(A % Cols(j))
aa(rptr+rsize)=A % values(j)
rsize = rsize + 1
END IF
END DO
ELSE
rsize = tind-lind
DO j=lind, tind-1
ja(rptr+(j-lind))=A % Gorder(A % Cols(j))
aa(rptr+(j-lind))=A % values(j)
END DO
END IF
CALL SortF(rsize, ja(rptr:rptr+rsize), aa(rptr:rptr+rsize))
rptr = rptr + rsize
lrow = lrow + 1
ia(lrow) = rptr
lind = Order(i)
END DO
DEALLOCATE(Order, iperm)
A % CPardisoId % msglvl = 0
A % CPardisoId % maxfct = 1
A % CPardisoId % mnum = 1
A % CPardisoId % nrhs = 1
ALLOCATE(A % CPardisoId % rhs(nt-nl+1), &
A % CPardisoId % x(nt-nl+1), STAT=allocstat)
IF (allocstat /= 0) THEN
CALL Fatal('CPardiso_Factorize', &
'Memory allocation for CPardiso rhs and solution vector x failed')
END IF
iparm(1)=1
iparm(2)=2
iparm(5)=0
iparm(6)=0
iparm(8)=0
IF (A % CPardisoID % mtype ==11 .OR. &
A % CPardisoID % mtype == 13) THEN
iparm(10)=13
iparm(11)=1
iparm(13)=1
ELSE
iparm(10)=8
iparm(11)=0
iparm(13)=0
END IF
iparm(21)=1
iparm(27)=0
iparm(28)=0
iparm(35)=0
iparm(40) = 2
iparm(41) = nl
iparm(42) = nt
phase = 11
CALL cluster_sparse_solver(A % CPardisoId % ID, &
A % CPardisoId % maxfct, A % CPardisoId % mnum, &
A % CPardisoId % mtype, phase, A % CPardisoId % n, &
aa, ia, ja, idum, A % CPardisoId % nrhs, iparm, &
A % CPardisoId % msglvl, &
ddum, ddum, A % Comm, ierror)
IF (ierror /= 0) THEN
WRITE(*,'(A,I0)') 'MKL CPardiso: ERROR=', ierror
CALL Fatal('CPardiso_SolveSystem','Error during analysis phase')
END IF
phase = 22
CALL cluster_sparse_solver(A % CPardisoId % ID, &
A % CPardisoId % maxfct, A % CPardisoId % mnum, &
A % CPardisoId % mtype, phase, A % CPardisoId % n, &
aa, ia, ja, idum, A % CPardisoId % nrhs, iparm, &
A % CPardisoId % msglvl, &
ddum, ddum, A % Comm, ierror)
IF (ierror /= 0) THEN
WRITE(*,'(A,I0)') 'MKL CPardiso: ERROR=', ierror
CALL Fatal('CPardiso_SolveSystem','Error during factorization phase')
END IF
END SUBROUTINE CPardiso_Factorize
SUBROUTINE CPardiso_Free(A)
IMPLICIT NONE
TYPE(Matrix_t) :: A
INTERFACE
SUBROUTINE cluster_sparse_solver(pt, maxfct, mnum, mtype, phase, n, &
values, rows, cols, perm, nrhs, iparm, &
msglvl, b, x, comm, ierror)
USE Types
REAL(KIND=dp) :: values(*), b(*), x(*)
INTEGER(KIND=AddrInt) :: pt(*)
INTEGER :: perm(*), nrhs, iparm(*), msglvl, ierror
INTEGER :: maxfct, mnum, mtype, phase, n, rows(*), cols(*), comm
END SUBROUTINE cluster_sparse_solver
END INTERFACE
INTEGER :: ierror, phase, idum(1)
REAL(kind=dp) :: ddum(1)
IF(ASSOCIATED(A % CPardisoId)) THEN
phase = -1
CALL cluster_sparse_solver(A % CPardisoId % ID, &
A % CPardisoID % maxfct, A % CPardisoID % mnum, &
A % CPardisoID % mtype, phase, A % CPardisoID % n, &
A % CPardisoId % aa, A % CPardisoId % ia, A % CPardisoId % ja, &
idum, A % CPardisoID % nrhs, A % CPardisoID % IParm, &
A % CPardisoID % msglvl, ddum, ddum, A % Comm, ierror)
DEALLOCATE(A % Gorder)
DEALLOCATE(A % CPardisoId % ID)
DEALLOCATE(A % CPardisoID % IParm)
DEALLOCATE(A % CPardisoId % ia, A % CPardisoId % ja, &
A % CPardisoId % aa, A % CPardisoID % rhs, &
A % CPardisoID % x)
DEALLOCATE(A % CPardisoID)
END IF
END SUBROUTINE CPardiso_Free
#endif
SUBROUTINE DirectSolver( A,x,b,Solver,Free_Fact )
TYPE(Solver_t) :: Solver
REAL(KIND=dp) :: x(*),b(*)
TYPE(Matrix_t) :: A
LOGICAL, OPTIONAL :: Free_Fact
LOGICAL :: GotIt
CHARACTER(:), ALLOCATABLE :: Method
IF ( PRESENT(Free_Fact) ) THEN
IF ( Free_Fact ) THEN
CALL BandSolver( A, x, b, Free_Fact )
CALL ComplexBandSolver( A, x, b, Free_Fact )
#ifdef HAVE_MUMPS
CALL Mumps_SolveSystem( Solver, A, x, b, Free_Fact )
CALL MumpsLocal_SolveSystem( Solver, A, x, b, Free_Fact )
#endif
#if defined(HAVE_MKL) || defined(HAVE_PARDISO)
CALL Pardiso_SolveSystem( Solver, A, x, b, Free_Fact )
#endif
#if defined(HAVE_MKL) && defined(HAVE_CPARDISO)
CALL CPardiso_SolveSystem( Solver, A, x, b, Free_Fact )
#endif
#ifdef HAVE_SUPERLU
CALL SuperLU_SolveSystem( Solver, A, x, b, Free_Fact )
#endif
#ifdef HAVE_UMFPACK
CALL Umfpack_SolveSystem( Solver, A, x, b, Free_Fact )
#endif
#ifdef HAVE_CHOLMOD
CALL SPQR_SolveSystem( Solver, A, x, b, Free_Fact )
CALL Cholmod_SolveSystem( Solver, A, x, b, Free_Fact )
#endif
#ifdef HAVE_FETI4I
CALL Permon_SolveSystem( Solver, A, x, b, Free_Fact )
#endif
RETURN
RETURN
END IF
END IF
Method=ListGetString(Solver % Values,'Linear System Direct Method',GotIt)
IF ( .NOT. GotIt ) Method = 'banded'
CALL Info('DirectSolver','Using direct method: '//Method,Level=9)
#if
IF ( Method == 'umfpack' .OR. Method == 'big umfpack' ) THEN
CALL Warn( 'CheckLinearSolverOptions', 'UMFPACK solver not installed, using MUMPS instead!' )
Method = 'mumps'
END IF
#endif
SELECT CASE(Method)
CASE( 'banded', 'symmetric banded' )
IF ( .NOT. A % Complex ) THEN
CALL BandSolver( A, x, b )
ELSE
CALL ComplexBandSolver( A, x, b )
END IF
CASE( 'umfpack', 'big umfpack' )
CALL Umfpack_SolveSystem( Solver, A, x, b )
CASE( 'cholmod' )
CALL Cholmod_SolveSystem( Solver, A, x, b )
CASE( 'spqr' )
CALL SPQR_SolveSystem( Solver, A, x, b )
CASE( 'mumps' )
CALL Mumps_SolveSystem( Solver, A, x, b )
CASE( 'mumpslocal' )
CALL MumpsLocal_SolveSystem( Solver, A, x, b )
CASE( 'superlu' )
CALL SuperLU_SolveSystem( Solver, A, x, b )
CASE( 'permon' )
CALL Permon_SolveSystem( Solver, A, x, b )
CASE( 'pardiso' )
CALL Pardiso_SolveSystem( Solver, A, x, b )
CASE( 'cpardiso' )
CALL CPardiso_SolveSystem( Solver, A, x, b )
CASE DEFAULT
CALL Fatal( 'DirectSolver', 'Unknown direct solver method.' )
END SELECT
IF( ASSOCIATED( Solver % Variable ) ) THEN
Solver % Variable % LinConverged = 1
END IF
END SUBROUTINE DirectSolver
END MODULE DirectSolve