MODULE ListMatrix
USE CRSMatrix
USE GeneralUtils
IMPLICIT NONE
INTEGER, PARAMETER :: LISTMATRIX_GROWTH = 1000
CONTAINS
FUNCTION List_AllocateMatrix(N) RESULT(Matrix)
INTEGER :: i,n,istat
TYPE(ListMatrix_t), POINTER :: Matrix(:)
ALLOCATE( Matrix(n), STAT=istat )
IF( istat /= 0 ) THEN
CALL Fatal('List_AllocateMatrix','Allocation error for ListMatrix of size: '//I2S(n))
END IF
DO i=1,n
Matrix(i) % Head => NULL()
Matrix(i) % Level = 0
Matrix(i) % Degree = 0
END DO
END FUNCTION List_AllocateMatrix
SUBROUTINE List_FreeMatrix( N, List )
TYPE(ListMatrix_t), POINTER :: List(:)
INTEGER :: N
TYPE(ListMatrixEntry_t), POINTER :: p,p1
INTEGER :: i
IF ( .NOT. ASSOCIATED(List) ) RETURN
DO i=1,N
p => List(i) % Head
DO WHILE( ASSOCIATED(p) )
p1 => p % Next
DEALLOCATE( p )
p => p1
END DO
END DO
DEALLOCATE( List )
END SUBROUTINE List_FreeMatrix
FUNCTION List_EnlargeMatrix(Matrix,N) RESULT(NewMatrix)
INTEGER :: i,n
TYPE(ListMatrix_t), POINTER :: Matrix(:), NewMatrix(:)
NewMatrix => List_AllocateMatrix(n)
IF ( ASSOCIATED(Matrix) ) THEN
DO i=1,SIZE(Matrix)
NewMatrix(i)=Matrix(i)
END DO
DEALLOCATE(Matrix)
END IF
END FUNCTION List_EnlargeMatrix
SUBROUTINE List_ToCRS(L,Rows,Cols,Diag)
TYPE(ListMatrix_t) :: L(:)
INTEGER :: i,j,n,istat
TYPE(Matrix_t), POINTER :: A
TYPE(ListMatrixEntry_t), POINTER :: P
INTEGER, POINTER CONTIG :: Rows(:),Cols(:),Diag(:)
DO n=SIZE(L),1,-1
IF ( L(n) % Degree>0 ) EXIT
END DO
ALLOCATE( Rows(n+1), Diag(n), STAT=istat)
IF(istat /= 0 ) THEN
CALL Fatal('List_ToCRS','Could not allocate memory for CRS Rows of size '//I2S(n))
END IF
Rows(1) = 1
DO i=1,n
Rows(i+1) = Rows(i) + L(i) % Degree
END DO
ALLOCATE( Cols(Rows(i+1)-1), Stat=istat)
IF(istat /= 0 ) THEN
CALL Fatal('List_ToCRS','Could not allocate memory for CRS Cols of size '//I2S(Rows(i+1)-1))
END IF
j = 0
DO i=1,n
P => L(i) % Head
DO WHILE(ASSOCIATED(P))
j = j + 1
Cols(j) = P % Index
P => P % Next
END DO
END DO
CALL Info('List_ToCRS',&
'Number of entries in CRS matrix: '//I2S(Rows(n+1)-1),Level=8)
A => AllocateMatrix()
A % NumberOfRows = n
A % Rows => Rows
A % Diag => Diag
A % Cols => Cols
CALL CRS_SortMatrix(A)
DEALLOCATE(A)
END SUBROUTINE List_ToCRS
SUBROUTINE List_ToCRSMatrix(A)
TYPE(Matrix_t) :: A
TYPE(ListMatrix_t), POINTER :: L(:)
INTEGER :: i,j,k,n,m,istat
TYPE(ListMatrixEntry_t), POINTER :: P
INTEGER, POINTER CONTIG :: Rows(:),Cols(:),Diag(:)
REAL(KIND=dp), POINTER CONTIG :: Values(:)
IF( A % FORMAT /= MATRIX_LIST ) THEN
CALL Warn('List_ToCRSMatrix','The initial matrix type is not List')
RETURN
END IF
L => A % ListMatrix
IF( .NOT. ASSOCIATED( L ) ) THEN
A % FORMAT = MATRIX_CRS
A % NumberOfRows = 0
RETURN
END IF
DO n=SIZE(L),1,-1
IF ( L(n) % Degree > 0 ) EXIT
END DO
CALL Info('List_ToCRSMatrix','List size '//I2S(SIZE(L))//' vs. active rows '//I2S(n),Level=25)
ALLOCATE( Rows(n+1), Diag(n), STAT=istat)
IF(istat /= 0 ) THEN
CALL Fatal('List_ToCRSMatrix','Could not allocate memory for CRS Rows of size '//I2S(n))
END IF
Diag = 0
Rows(1) = 1
DO i=1,n
Rows(i+1) = Rows(i) + L(i) % Degree
END DO
m = Rows(n+1)-1
CALL Info('List_ToCRSMatrix',&
'Changing matrix type with number of non-zeros: '//I2S(m),Level=8)
ALLOCATE( Cols(m),Values(m),STAT=istat)
IF(istat /= 0 ) THEN
CALL Fatal('List_ToCRS','Could not allocate memory for CRS Cols & Values of size '//I2S(m))
END IF
j = 0
DO i=1,n
P => L(i) % Head
DO WHILE(ASSOCIATED(P))
j = j + 1
Cols(j) = P % Index
Values(j) = P % Val
P => P % Next
END DO
END DO
A % NumberOfRows = n
A % Rows => Rows
A % Diag => Diag
A % Cols => Cols
A % Values => Values
A % Ordered=.FALSE.
CALL CRS_SortMatrix( A )
CALL List_FreeMatrix( SIZE(L), L )
A % ListMatrix => NULL()
A % FORMAT = MATRIX_CRS
CALL Info('List_ToCRSMatrix','Matrix format changed from List to CRS', Level=12)
END SUBROUTINE List_ToCRSMatrix
SUBROUTINE List_ToListMatrix(A,Truncate)
TYPE(Matrix_t) :: A
LOGICAL, OPTIONAL :: Truncate
INTEGER :: i,j,n
LOGICAL :: Trunc
TYPE(ListMatrixEntry_t), POINTER :: CList
Trunc=.FALSE.
IF(PRESENT(Truncate)) Trunc=Truncate
A % ListMatrix => List_AllocateMatrix(A % NumberOfRows)
DO i=1,A % NumberOfRows
A % ListMatrix(i) % Level = 0
A % ListMatrix(i) % Degree = 0
IF(A % Rows(i) == A % Rows(i+1)) THEN
A % ListMatrix(i) % Head => NULL()
CYCLE
END IF
ALLOCATE(A % ListMatrix(i) % Head)
Clist => A % ListMatrix(i) % Head
Clist % Next => NULL()
DO j=A % Rows(i), A % Rows(i+1)-1
IF(Trunc) THEN
IF (A % Cols(j) > A % NumberOfRows) EXIT
END IF
IF (j>A % Rows(i)) THEN
IF ( Clist % Index >= A % Cols(j) ) THEN
CALL Warn( 'List_ToListMatrix()', 'Input matrix not ordered ? ')
GOTO 100
END IF
ALLOCATE(Clist % Next)
Clist => Clist % Next
CList % Next => NULL()
END IF
CList % Val = A % Values(j)
CList % Index = A % Cols(j)
A % ListMatrix(i) % Degree = A % ListMatrix(i) % Degree + 1
END DO
END DO
GOTO 200
100 CONTINUE
CALL List_FreeMatrix(i,A % ListMatrix)
A % ListMatrix => Null()
DO i=1,A % NumberOfRows
DO j=A % Rows(i+1)-1,A % Rows(i),-1
IF(Trunc) THEN
IF (A % Cols(j) > A % NumberOfRows) CYCLE
END IF
CALL List_SetMatrixElement(A % ListMatrix,i,A % Cols(j),A % Values(j))
END DO
END DO
200 CONTINUE
A % FORMAT = MATRIX_LIST
IF( ASSOCIATED( A % Rows ) ) DEALLOCATE( A % Rows )
IF( ASSOCIATED( A % Cols ) ) DEALLOCATE( A % Cols )
IF( ASSOCIATED( A % Diag ) ) DEALLOCATE( A % Diag )
IF( ASSOCIATED( A % Values ) ) DEALLOCATE( A % Values )
A % Rows => Null()
A % Cols => Null()
A % Diag => Null()
A % Values => NULL()
A % ndeg = -1
CALL Info('List_ToListMatrix','Matrix format changed from CRS to List', Level=7)
END SUBROUTINE List_ToListMatrix
FUNCTION List_GetMatrixIndex(List,k1,k2 ) RESULT(Entry)
TYPE(ListMatrix_t), POINTER :: List(:)
INTEGER :: k1,k2
TYPE(ListMatrixEntry_t), POINTER :: CList,Prev, Entry, Dummy
INTEGER :: i, istat
IF ( .NOT. ASSOCIATED(List) ) List=>List_AllocateMatrix(k1)
IF ( k1>SIZE(List) ) THEN
List => List_EnlargeMatrix(List,MAX(k1, &
SIZE(List)+LISTMATRIX_GROWTH) )
END IF
Clist => List(k1) % Head
IF ( .NOT. ASSOCIATED(Clist) ) THEN
Dummy => NULL()
Entry => List_GetMatrixEntry(k2, Dummy )
List(k1) % Degree = 1
List(k1) % Head => Entry
RETURN
END IF
NULLIFY( Prev )
DO WHILE( ASSOCIATED(CList) )
IF ( Clist % INDEX >= k2 ) EXIT
Prev => Clist
CList => CList % Next
END DO
IF ( ASSOCIATED( CList ) ) THEN
IF ( CList % INDEX == k2 ) THEN
Entry => Clist
RETURN
END IF
END IF
Entry => List_GetMatrixEntry(k2, CList)
IF ( ASSOCIATED( Prev ) ) THEN
Prev % Next => Entry
ELSE
List(k1) % Head => Entry
END IF
List(k1) % Degree = List(k1) % Degree + 1
END FUNCTION List_GetMatrixIndex
SUBROUTINE List_AddMatrixIndexes(List,k1,nk2,Ind)
IMPLICIT NONE
TYPE(ListMatrix_t) :: List(:)
INTEGER, INTENT(IN) :: k1, nk2
INTEGER, INTENT(IN) :: Ind(nk2)
TYPE(ListMatrixEntry_t), POINTER :: RowPtr, PrevPtr, Entry, Dummy
INTEGER :: i,k2,k2i,j, k,prevind
IF (k1>SIZE(List)) THEN
CALL Fatal('List_AddMatrixIndexes','Row index out of bounds: '//TRIM(I2S(k1)))
END IF
RowPtr => List(k1) % Head
IF (.NOT. ASSOCIATED(RowPtr)) THEN
Dummy => NULL()
Entry => List_GetMatrixEntry(Ind(1),Dummy)
List(k1) % Degree = 1
List(k1) % Head => Entry
k2i = 2
prevind = ind(1)
ELSE IF (RowPtr % Index > Ind(1)) THEN
Entry => List_GetMatrixEntry(Ind(1),RowPtr)
List(k1) % Degree = List(k1) % Degree + 1
List(k1) % Head => Entry
k2i = 2
prevind = ind(1)
ELSE IF (RowPtr % Index == Ind(1)) THEN
k2i = 2
prevind = ind(1)
ELSE
k2i = 1
prevind = -1
END IF
PrevPtr => List(k1) % Head
RowPtr => List(k1) % Head % Next
DO i=k2i,nk2
k2=Ind(i)
if (k2 == prevind) cycle
DO WHILE( ASSOCIATED(RowPtr) )
IF (RowPtr % Index >= k2) EXIT
PrevPtr => RowPtr
RowPtr => RowPtr % Next
END DO
IF (ASSOCIATED(RowPtr)) THEN
IF (RowPtr % Index /= k2) THEN
Entry => List_GetMatrixEntry(k2,RowPtr)
PrevPtr % Next => Entry
List(k1) % Degree = List(k1) % Degree + 1
PrevPtr => Entry
ELSE
PrevPtr => RowPtr
RowPtr => RowPtr % Next
END IF
ELSE
EXIT
END IF
prevind = k2
END DO
DO j=i,nk2
k2 = Ind(j)
if (k2 == prevind) cycle
prevind = k2
Dummy => NULL()
Entry => List_GetMatrixEntry(k2,Dummy)
PrevPtr % Next => Entry
PrevPtr => PrevPtr % Next
List(k1) % Degree = List(k1) % Degree + 1
END DO
END SUBROUTINE List_AddMatrixIndexes
SUBROUTINE List_AddMatrixRow(List,k1,nk2,Ind,Vals,SortedInput)
IMPLICIT NONE
TYPE(ListMatrix_t) :: List(:)
LOGICAL, INTENT(IN), OPTIONAL :: SortedInput
INTEGER, INTENT(IN) :: k1, nk2
INTEGER, INTENT(INOUT) :: Ind(nk2)
REAL(KIND=dp), INTENT(INOUT) :: Vals(nk2)
TYPE(ListMatrixEntry_t), POINTER :: RowPtr, PrevPtr, Entry, Dummy
INTEGER :: i,k2,k2i,j, k,prevind
IF (k1>SIZE(List)) THEN
CALL Fatal('List_AddMatrixIndexes','Row index out of bounds: '//TRIM(I2S(k1)))
END IF
IF( PRESENT(SortedInput) ) THEN
IF ( .NOT. SortedInput ) CALL SortF(nk2, Ind, Vals)
ELSE
CALL SortF(nk2, Ind, Vals)
END IF
RowPtr => List(k1) % Head
IF (.NOT. ASSOCIATED(RowPtr)) THEN
Dummy => NULL()
Entry => List_GetMatrixEntry(Ind(1),Dummy)
Entry % Val = Vals(1)
List(k1) % Degree = 1
List(k1) % Head => Entry
k2i = 2
prevind = ind(1)
ELSE IF (RowPtr % Index > Ind(1)) THEN
Entry => List_GetMatrixEntry(Ind(1),RowPtr)
Entry % Val = Vals(1)
List(k1) % Degree = List(k1) % Degree + 1
List(k1) % Head => Entry
k2i = 2
prevind = IND(1)
ELSE IF (RowPtr % Index == Ind(1)) THEN
k2i = 2
prevind = ind(1)
RowPtr % Val = RowPtr % Val + Vals(1)
ELSE
k2i = 1
prevind = -1
END IF
PrevPtr => List(k1) % Head
RowPtr => List(k1) % Head % Next
DO i=k2i,nk2
k2 = Ind(i)
IF(k2 == prevind) THEN
CYCLE
END IF
DO WHILE( ASSOCIATED(RowPtr) )
IF (RowPtr % Index >= k2) EXIT
PrevPtr => RowPtr
RowPtr => RowPtr % Next
END DO
IF (ASSOCIATED(RowPtr)) THEN
IF (RowPtr % Index /= k2) THEN
Entry => List_GetMatrixEntry(k2,RowPtr)
Entry % Val = Vals(i)
PrevPtr % Next => Entry
List(k1) % Degree = List(k1) % Degree + 1
PrevPtr => Entry
ELSE
RowPtr % Val = RowPtr % Val + Vals(i)
PrevPtr => RowPtr
RowPtr => RowPtr % Next
END IF
ELSE
EXIT
END IF
prevind = k2
END DO
DO j=i,nk2
k2 = Ind(j)
IF (k2 == prevind) THEN
cycle
END IF
prevind = k2
Dummy => NULL()
Entry => List_GetMatrixEntry(k2,Dummy)
Entry % Val = Vals(j)
PrevPtr % Next => Entry
PrevPtr => PrevPtr % Next
List(k1) % Degree = List(k1) % Degree + 1
END DO
END SUBROUTINE List_AddMatrixRow
FUNCTION List_GetMatrixEntry(ind, next) RESULT(ListEntry)
IMPLICIT NONE
INTEGER, INTENT(IN) :: ind
TYPE(ListMatrixEntry_t), POINTER, INTENT(IN) :: next
TYPE(ListMatrixEntry_t), POINTER :: ListEntry
INTEGER :: istat
ALLOCATE(ListEntry, STAT=istat)
IF( istat /= 0 ) THEN
CALL Fatal('List_GetMatrixEntry','Could not allocate entry!')
END IF
ListEntry % Val = REAL(0,dp)
ListEntry % INDEX = ind
ListEntry % Next => next
END FUNCTION List_GetMatrixEntry
SUBROUTINE List_DeleteMatrixElement(List,k1,k2)
INTEGER :: k1,k2
TYPE(ListMatrix_t) :: List(:)
TYPE(ListMatrixEntry_t), POINTER :: Clist,Prev
Prev => NULL()
Clist => List(k1) % Head
DO WHILE(ASSOCIATED(Clist))
IF (Clist % Index >= k2) EXIT
Prev => Clist
Clist => Clist % Next
END DO
IF (.NOT.ASSOCIATED(Clist)) RETURN
IF (Clist % Index /= k2) RETURN
IF (ASSOCIATED(Prev)) THEN
Prev % Next => Clist % Next
ELSE
List(k1) % Head => Clist % Next
END IF
DEALLOCATE(Clist)
List(k1) % Degree = MAX(List(k1) % Degree-1,0)
END SUBROUTINE List_DeleteMatrixElement
SUBROUTINE List_DeleteRow(List,k1,Keep)
INTEGER :: k1,k2
LOGICAL, OPTIONAL :: Keep
TYPE(ListMatrix_t) :: List(:)
LOGICAL :: lKeep
INTEGER::n
TYPE(ListMatrixEntry_t), POINTER :: Clist,Next
n = SIZE(List)
IF(k1<=0.OR.k1>n) RETURN
Clist=>List(k1) % Head
DO WHILE(ASSOCIATED(Clist))
Next=>Clist % Next
DEALLOCATE(Clist)
Clist=>Next
END DO
lKeep = .FALSE.
IF(PRESENT(Keep)) lKeep = Keep
IF(lKeep) THEN
List(k1) % Degree=0
List(k1) % Head=>NULL()
ELSE
List(k1:n-1)=List(k1+1:n)
List(n) % Degree=0
List(n) % Head=>NULL()
END IF
END SUBROUTINE List_DeleteRow
SUBROUTINE List_DeleteCol(List,k1)
INTEGER :: k1
TYPE(ListMatrix_t) :: List(:)
INTEGER::i,n
TYPE(ListMatrixEntry_t), POINTER :: Clist,Prev
n=SIZE(List)
DO i=1,n
Prev => NULL()
Clist => List(i) % Head
DO WHILE(ASSOCIATED(Clist))
IF(Clist % Index>=k1) EXIT
Prev => Clist
Clist => Clist % Next
END DO
IF(.NOT.ASSOCIATED(Clist)) CYCLE
IF (Clist % Index==k1) THEN
IF(ASSOCIATED(Prev)) THEN
Prev % Next => Clist % Next
ELSE
List(i) % Head => Clist % Next
END IF
List(i) % Degree = MAX(List(i) % Degree-1,0)
DEALLOCATE(Clist)
END IF
END DO
END SUBROUTINE List_DeleteCol
SUBROUTINE List_AddToMatrixElement( List,k1,k2,Val,SetVal )
TYPE(ListMatrix_t), POINTER :: List(:)
INTEGER :: k1,k2
REAL(KIND=dp) :: Val
LOGICAL, OPTIONAL :: SetVal
TYPE(ListMatrixEntry_t), POINTER :: CList,Prev, Entry
LOGICAL :: Set
Set = .FALSE.
IF( PRESENT(SetVal)) Set = SetVal
Entry => List_GetMatrixIndex(List,k1,k2)
IF ( Set ) THEN
Entry % Val = Val
ELSE
Entry % Val = Entry % Val + Val
END IF
END SUBROUTINE List_AddToMatrixElement
SUBROUTINE List_AddMatrixIndex( List,k1,k2 )
TYPE(ListMatrix_t), POINTER :: List(:)
INTEGER :: k1,k2
TYPE(ListMatrixEntry_t), POINTER :: CList,Prev, Entry
LOGICAL :: Set
Entry => List_GetMatrixIndex(List,k1,k2)
END SUBROUTINE List_AddMatrixIndex
SUBROUTINE List_SetMatrixElement( List,k1,k2,Val,SetVal )
TYPE(ListMatrix_t), POINTER :: List(:)
INTEGER :: k1,k2
TYPE(ListMatrixEntry_t), POINTER :: CList,Prev, Entry
REAL(KIND=dp) :: Val
LOGICAL, OPTIONAL :: SetVal
CALL List_AddToMatrixElement( List,k1,k2,Val,.TRUE.)
END SUBROUTINE List_SetMatrixElement
FUNCTION List_GetMatrixElement( List,k1,k2 ) RESULT ( Val )
TYPE(ListMatrix_t), POINTER :: List(:)
INTEGER :: k1,k2
TYPE(ListMatrixEntry_t), POINTER :: CList,Prev, Entry
REAL(KIND=dp) :: Val
Val = 0.0_dp
IF ( .NOT. ASSOCIATED(List) ) RETURN
IF ( k1>SIZE(List) ) RETURN
Clist => List(k1) % Head
IF ( .NOT. ASSOCIATED(Clist) ) RETURN
NULLIFY( Prev )
DO WHILE( ASSOCIATED(CList) )
IF ( Clist % INDEX == k2 ) Val = CList % Val
IF ( Clist % INDEX >= k2 ) RETURN
Prev => Clist
CList => CList % Next
END DO
END FUNCTION List_GetMatrixElement
SUBROUTINE List_ZeroRow( List,k1 )
TYPE(ListMatrix_t), POINTER :: List(:)
INTEGER :: k1
TYPE(ListMatrixEntry_t), POINTER :: CList
IF ( .NOT. ASSOCIATED(List) ) THEN
CALL Warn('List_ZeroRow','No List matrix present!')
RETURN
END IF
IF ( k1 > SIZE(List) ) THEN
CALL Warn('List_ZeroRow','No such row!')
RETURN
END IF
Clist => List(k1) % Head
IF ( .NOT. ASSOCIATED(Clist) ) THEN
CALL Warn('List_ZeroRow','Row not associated!')
RETURN
END IF
DO WHILE( ASSOCIATED(CList) )
Clist % Val = 0.0_dp
CList => CList % Next
END DO
END SUBROUTINE List_ZeroRow
SUBROUTINE List_MoveRow( List,n1,n2,coeff,staycoeff )
TYPE(ListMatrix_t), POINTER :: List(:)
INTEGER :: n1, n2
REAL(KIND=dp), OPTIONAL :: coeff, staycoeff
INTEGER :: k2
REAL(KIND=dp) :: val, c, d
TYPE(ListMatrixEntry_t), POINTER :: CList
IF( PRESENT(coeff)) THEN
c = coeff
ELSE
c = 1.0_dp
END IF
IF( PRESENT(staycoeff)) THEN
d = staycoeff
ELSE
d = 0.0_dp
END IF
IF ( .NOT. ASSOCIATED(List) ) THEN
CALL Warn('List_MoveRow','No List matrix present!')
RETURN
END IF
IF ( n1 > SIZE(List) ) THEN
CALL Warn('List_MoveRow','No row to move!')
RETURN
END IF
Clist => List(n1) % Head
IF ( .NOT. ASSOCIATED(Clist) ) THEN
CALL Warn('List_MoveRow','Row not associated!')
RETURN
END IF
DO WHILE( ASSOCIATED(CList) )
k2 = Clist % Index
Val = Clist % Val
Clist % VAL = d * Val
CALL List_AddToMatrixElement(List,n2,k2,c*Val)
CList => CList % Next
END DO
END SUBROUTINE List_MoveRow
SUBROUTINE List_ExchangeRowStructure( List,n1,n2 )
TYPE(ListMatrix_t), POINTER :: List(:)
INTEGER :: n1, n2
INTEGER :: k1, k2
TYPE(ListMatrixEntry_t), POINTER :: CList1, CList2, Lptr
IF ( .NOT. ASSOCIATED(List) ) THEN
CALL Warn('List_ExchangeRowStructure','No List matrix present!')
RETURN
END IF
Clist1 => List(n1) % Head
IF ( .NOT. ASSOCIATED(Clist1) ) THEN
CALL Warn('List__ExchangeRowStructure','Row1 not associated!')
RETURN
END IF
Clist2 => List(n2) % Head
IF ( .NOT. ASSOCIATED(Clist2) ) THEN
CALL Warn('List__ExchangeRowStructure','Row2 not associated!')
RETURN
END IF
DO WHILE( ASSOCIATED(CList1) )
k1 = Clist1 % Index
Lptr => List_GetMatrixIndex( List,n2,k1 )
CList1 => CList1 % Next
END DO
DO WHILE( ASSOCIATED(CList2) )
k2 = Clist2 % Index
Lptr => List_GetMatrixIndex( List,n1,k2 )
CList2 => CList2 % Next
END DO
END SUBROUTINE List_ExchangeRowStructure
SUBROUTINE List_GlueLocalMatrix( A,N,Dofs,Indexes,LocalMatrix )
TYPE(ListMatrix_t), POINTER :: A(:)
INTEGER :: N,DOFs, Indexes(:)
REAL(KIND=dp) :: LocalMatrix(:,:)
REAL(KIND=dp) :: Val
INTEGER :: i,j,k,l,c,Row,Col
DO i=1,n
IF (Indexes(i)<=0) CYCLE
DO k=0,Dofs-1
Row = Dofs*Indexes(i)-k
DO j=1,n
IF (Indexes(j)<=0) CYCLE
DO l=0,Dofs-1
Col = Dofs * Indexes(j) - l
Val = LocalMatrix(Dofs*i-k,Dofs*j-l)
CALL List_AddToMatrixElement(A,Row,Col,Val)
END DO
END DO
END DO
END DO
END SUBROUTINE List_GlueLocalMatrix
SUBROUTINE List_GlueLocalSubMatrix( List,row0,col0,Nrow,Ncol, &
RowInds,ColInds,RowDofs,ColDofs,LocalMatrix )
TYPE(ListMatrix_t), POINTER :: List(:)
INTEGER :: Nrow,Ncol,RowDofs,ColDofs,Col0,Row0,RowInds(:),ColInds(:)
REAL(KIND=dp) :: LocalMatrix(:,:)
REAL(KIND=dp) :: Val
INTEGER :: i,j,k,l,c,Row,Col
DO i=1,Nrow
DO k=0,RowDofs-1
IF ( RowInds(i) <= 0 ) CYCLE
Row = Row0 + RowDofs * RowInds(i) - k
DO j=1,Ncol
DO l=0,ColDofs-1
IF ( ColInds(j) <= 0 ) CYCLE
Col = Col0 + ColDofs * ColInds(j) - l
Val = LocalMatrix(RowDofs*i-k,ColDofs*j-l)
CALL List_AddToMatrixElement(List,Row,Col,Val)
END DO
END DO
END DO
END DO
END SUBROUTINE List_GlueLocalSubMatrix
END MODULE ListMatrix