MODULE ListMatrixArray
USE Messages
USE Types
USE GeneralUtils, ONLY : I2S
IMPLICIT NONE
CONTAINS
SUBROUTINE ListMatrixArray_Allocate(ListMatrixArray, N, PoolSize, Atomic)
IMPLICIT NONE
TYPE(ListMatrixArray_t) :: ListMatrixArray
INTEGER,INTENT(IN) :: N
INTEGER, OPTIONAL :: PoolSize
LOGICAL, OPTIONAL :: Atomic
INTEGER :: i,istat, nthr, TID, psize
LOGICAL :: InitLocks
psize = 1024
IF (PRESENT(PoolSize)) psize = PoolSize
InitLocks = .FALSE.
IF (PRESENT(Atomic)) InitLocks = Atomic
nthr = 1
ALLOCATE( ListMatrixArray % Rows(n), &
ListMatrixArray % Pool(nthr), STAT=istat )
IF( istat /= 0 ) THEN
CALL Fatal('ListMatrixArray_AllocateMatrix',&
'Allocation error for ListMatrix of size: '//I2S(n))
END IF
IF (InitLocks) CALL ListMatrixArray_InitializeAtomic(ListMatrixArray)
TID = 1
CALL ListMatrixPool_Initialize(ListMatrixArray % Pool(TID), psize)
DO i=1,N
ListMatrixArray % Rows(i) % Head => NULL()
ListMatrixArray % Rows(i) % Level = 0
ListMatrixArray % Rows(i) % Degree = 0
END DO
END SUBROUTINE ListMatrixArray_Allocate
SUBROUTINE ListMatrixArray_Free( ListMatrixArray )
IMPLICIT NONE
TYPE(ListMatrixArray_t) :: ListMatrixArray
TYPE(ListMatrixEntryPool_t), POINTER :: p, p1
INTEGER :: N,TID
N = SIZE(ListMatrixArray % Pool)
DO TID=1,N
CALL ListMatrixPool_Free(ListMatrixArray % Pool(TID))
END DO
CALL ListMatrixArray_FreeAtomic(ListMatrixArray)
DEALLOCATE(ListMatrixArray % Rows, ListMatrixArray % Pool)
END SUBROUTINE ListMatrixArray_Free
SUBROUTINE ListMatrixArray_InitializeAtomic(ListMatrixArray)
IMPLICIT NONE
TYPE(ListMatrixArray_t) :: ListMatrixArray
INTEGER :: i, N, istat
#ifdef _OPENMP
N = SIZE(ListMatrixArray % Rows)
ALLOCATE( ListMatrixArray % RowLocks(n), STAT=istat )
IF( istat /= 0 ) THEN
CALL Fatal('ListMatrixArray_InitializeAtomic',&
'Allocation error for ListMatrix row locks of size: '//I2S(n))
END IF
DO i=1,N
CALL omp_init_lock(ListMatrixArray % RowLocks(i))
END DO
#endif
END SUBROUTINE ListMatrixArray_InitializeAtomic
SUBROUTINE ListMatrixArray_FreeAtomic(ListMatrixArray)
IMPLICIT NONE
TYPE(ListMatrixArray_t) :: ListMatrixArray
INTEGER :: i, N
#ifdef _OPENMP
IF (ALLOCATED(ListMatrixArray % RowLocks)) THEN
N = SIZE(ListMatrixArray % RowLocks)
DO i=1,N
CALL omp_destroy_lock(ListMatrixArray % RowLocks(i))
END DO
DEALLOCATE(ListMatrixArray % RowLocks)
END IF
#endif
END SUBROUTINE ListMatrixArray_FreeAtomic
SUBROUTINE ListMatrixArray_LockRow(ListMatrixArray, row, Atomic)
IMPLICIT NONE
TYPE(ListMatrixArray_t) :: ListMatrixArray
INTEGER, INTENT(IN) :: row
LOGICAL, OPTIONAL :: Atomic
#ifdef _OPENMP
IF (PRESENT(ATOMIC)) THEN
IF (Atomic) CALL omp_set_lock(ListMatrixArray % RowLocks(row))
END IF
#endif
END SUBROUTINE ListMatrixArray_LockRow
SUBROUTINE ListMatrixArray_UnlockRow(ListMatrixArray, row, Atomic)
IMPLICIT NONE
TYPE(ListMatrixArray_t) :: ListMatrixArray
INTEGER, INTENT(IN) :: row
LOGICAL, OPTIONAL :: Atomic
#ifdef _OPENMP
IF (PRESENT(ATOMIC)) THEN
IF (Atomic) CALL omp_unset_lock(ListMatrixArray % RowLocks(row))
END IF
#endif
END SUBROUTINE ListMatrixArray_UnlockRow
SUBROUTINE ListMatrixArray_ToGraph( ListMatrixArray, Graph)
IMPLICIT NONE
TYPE(ListMatrixArray_t) :: ListMatrixArray
TYPE(Graph_t) :: Graph
CALL Fatal('ListMatrixArray_ToGraph','Not implemented yet!')
END SUBROUTINE ListMatrixArray_ToGraph
SUBROUTINE ListMatrixArray_ToCRSMatrix( ListMatrixArray, CRSMatrix )
IMPLICIT NONE
TYPE(ListMatrixArray_t) :: ListMatrixArray
TYPE(Matrix_t) :: CRSMatrix
CALL Fatal('ListMatrixArray_ToCRSMatrix','Not implemented yet!')
END SUBROUTINE ListMatrixArray_ToCRSMatrix
SUBROUTINE ListMatrixArray_FromCRSMatrix( ListMatrixArray, CRSMatrix )
IMPLICIT NONE
TYPE(ListMatrixArray_t) :: ListMatrixArray
TYPE(Matrix_t) :: CRSMatrix
CALL Fatal('ListMatrixArray_FromCRSMatrix','Not implemented yet!')
END SUBROUTINE ListMatrixArray_FromCRSMatrix
SUBROUTINE ListMatrixArray_AddEntry(ListMatrixArray, row, col, val, Atomic)
IMPLICIT NONE
TYPE(ListMatrixArray_t) :: ListMatrixArray
INTEGER, INTENT(IN) :: row, col
REAL(KIND=dp), OPTIONAL :: val
LOGICAL, OPTIONAL :: Atomic
TYPE(ListMatrixEntry_t), POINTER :: CEntryPtr, PEntryPtr, NEntryPtr
INTEGER :: TID
TID = 1
CALL ListMatrixArray_LockRow(ListMatrixArray, row, Atomic)
CEntryPtr => ListMatrixArray % Rows(row) % Head
IF (.NOT. ASSOCIATED(CEntryPtr)) THEN
ListMatrixArray % Rows(row) % Head => &
ListMatrixPool_GetListEntry(ListMatrixArray % Pool(TID), col, NULL())
ListMatrixArray % Rows(row) % Degree = 1
CALL ListMatrixArray_UnlockRow(ListMatrixArray, row, Atomic)
RETURN
ELSE IF (CEntryPtr % Index == col) THEN
CALL ListMatrixArray_UnlockRow(ListMatrixArray, row, Atomic)
RETURN
ELSE IF (CEntryPtr % Index > col) THEN
ListMatrixArray % Rows(row) % Head => &
ListMatrixPool_GetListEntry(ListMatrixArray % Pool(TID), col, CEntryPtr)
ListMatrixArray % Rows(row) % Degree = &
ListMatrixArray % Rows(row) % Degree + 1
CALL ListMatrixArray_UnlockRow(ListMatrixArray, row, Atomic)
RETURN
END IF
PEntryPtr => CEntryPtr
CEntryPtr => CEntryPtr % Next
DO WHILE( ASSOCIATED(CEntryPtr) )
IF (CEntryPtr % Index == col) THEN
CALL ListMatrixArray_UnlockRow(ListMatrixArray, row, Atomic)
RETURN
END IF
IF (CEntryPtr % Index > col) EXIT
PEntryPtr => CEntryPtr
CEntryPtr => CEntryPtr % Next
END DO
PEntryPtr % Next => ListMatrixPool_GetListEntry(ListMatrixArray % Pool(TID), col, CEntryPtr)
ListMatrixArray % Rows(row) % Degree = &
ListMatrixArray % Rows(row) % Degree + 1
CALL ListMatrixArray_UnlockRow(ListMatrixArray, row, Atomic)
END SUBROUTINE ListMatrixArray_AddEntry
SUBROUTINE ListMatrixArray_AddEntries(ListMatrixArray, row, nentry, Indexes, Perm, Atomic)
IMPLICIT NONE
TYPE(ListMatrixArray_t) :: ListMatrixArray
INTEGER, INTENT(IN) :: row, nentry
INTEGER, INTENT(IN) :: Indexes(nentry), Perm(nentry)
LOGICAL, OPTIONAL :: Atomic
TYPE(ListMatrixEntry_t), POINTER :: CEntryPtr, PEntryPtr, NEntryPtr
INTEGER :: TID, centry, sentry, rentry, col
TID = 1
CALL ListMatrixArray_LockRow(ListMatrixArray, row, Atomic)
CEntryPtr => ListMatrixArray % Rows(row) % Head
sentry = 1
col = Indexes(Perm(1))
IF (.NOT. ASSOCIATED(CEntryPtr)) THEN
CEntryPtr => ListMatrixPool_GetListEntry(ListMatrixArray % Pool(TID), col, NULL())
ListMatrixArray % Rows(row) % Head => CEntryPtr
ListMatrixArray % Rows(row) % Degree = 1
sentry = 2
ELSE IF (CEntryPtr % Index == col) THEN
sentry = 2
ELSE IF (CEntryPtr % Index > col) THEN
NEntryPtr => ListMatrixPool_GetListEntry(ListMatrixArray % Pool(TID), col, CEntryPtr)
CEntryPtr => NEntryPtr
ListMatrixArray % Rows(row) % Head => CEntryPtr
ListMatrixArray % Rows(row) % Degree = &
ListMatrixArray % Rows(row) % Degree + 1
sentry = 2
END IF
PEntryPtr => CEntryPtr
CEntryPtr => CEntryPtr % Next
DO centry=sentry,nentry
col=Indexes(Perm(centry))
DO WHILE( ASSOCIATED(CEntryPtr) )
IF (CEntryPtr % Index >= col) EXIT
PEntryPtr => CEntryPtr
CEntryPtr => PEntryPtr % Next
END DO
IF (ASSOCIATED(CEntryPtr)) THEN
IF (CEntryPtr % Index /= col) THEN
NEntryPtr => ListMatrixPool_GetListEntry(ListMatrixArray % Pool(TID), col, CEntryPtr)
PEntryPtr % Next => NEntryPtr
ListMatrixArray % Rows(row) % Degree = &
ListMatrixArray % Rows(row) % Degree + 1
PEntryPtr => NEntryPtr
CEntryPtr => NEntryPtr % Next
ELSE
PEntryPtr => CEntryPtr
CEntryPtr => CEntryPtr % Next
END IF
ELSE
EXIT
END IF
END DO
DO rentry=centry,nentry
col=Indexes(Perm(rentry))
NEntryPtr => ListMatrixPool_GetListEntry(ListMatrixArray % Pool(TID), col, NULL())
PEntryPtr % Next => NEntryPtr
PEntryPtr => NEntryPtr
ListMatrixArray % Rows(row) % Degree = &
ListMatrixArray % Rows(row) % Degree + 1
END DO
CALL ListMatrixArray_UnlockRow(ListMatrixArray, row, Atomic)
END SUBROUTINE ListMatrixArray_AddEntries
SUBROUTINE ListMatrixArray_DeleteEntry(ListMatrixArray, row, col, Atomic)
IMPLICIT NONE
TYPE(ListMatrixArray_t) :: ListMatrixArray
INTEGER, INTENT(IN) :: row, col
LOGICAL, OPTIONAL :: Atomic
TYPE(ListMatrixEntry_t), POINTER :: CEntryPtr, PEntryPtr
INTEGER :: TID
LOGICAL :: NotFound
TID = 1
CALL ListMatrixArray_LockRow(ListMatrixArray, row, Atomic)
PEntryPtr => NULL()
CEntryPtr => ListMatrixArray % Rows(row) % Head
DO WHILE( ASSOCIATED(CEntryPtr) )
IF (CEntryPtr % Index >= col) EXIT
PEntryPtr => CEntryPtr
CEntryPtr => CEntryPtr % Next
END DO
IF (ASSOCIATED(CEntryPtr)) THEN
IF (CEntryPtr % Index == col) THEN
IF (ASSOCIATED(PEntryPtr)) THEN
PEntryPtr % Next => CEntryPtr % Next
ELSE
ListMatrixArray % Rows(row) % Head => CEntryPtr % Next
END IF
CALL ListMatrixPool_AddDeletedEntry(ListMatrixArray % Pool(TID), CEntryPtr)
ListMatrixArray % Rows(row) % Degree = &
MAX(ListMatrixArray % Rows(row) % Degree - 1, 0)
END IF
END IF
CALL ListMatrixArray_UnlockRow(ListMatrixArray, row, Atomic)
END SUBROUTINE ListMatrixArray_DeleteEntry
SUBROUTINE ListMatrixPool_Initialize(Pool, PoolSize)
IMPLICIT NONE
TYPE(ListMatrixPool_t) :: Pool
INTEGER, INTENT(IN) :: PoolSize
Pool % EntryPool => NULL()
Pool % Deleted => NULL()
Pool % PoolSize = PoolSize
CALL ListMatrixPool_EnLarge(Pool)
END SUBROUTINE ListMatrixPool_Initialize
SUBROUTINE ListMatrixPool_Enlarge(Pool)
IMPLICIT NONE
TYPE(ListMatrixPool_t) :: Pool
TYPE(ListMatrixEntryPool_t), POINTER :: EntryPool
INTEGER :: astat
ALLOCATE(EntryPool, STAT=astat)
IF (astat == 0) ALLOCATE(EntryPool % Entries(Pool % PoolSize), STAT=astat)
IF (astat /= 0) THEN
CALL Fatal('ListMatrixPool_Enlarge','Pool allocation failed')
END IF
EntryPool % NextIndex = 1
EntryPool % Next => Pool % EntryPool
Pool % EntryPool => EntryPool
END SUBROUTINE ListMatrixPool_Enlarge
SUBROUTINE ListMatrixPool_Free(Pool)
IMPLICIT NONE
TYPE(ListMatrixPool_t) :: Pool
TYPE(ListMatrixEntryPool_t), POINTER :: EntryPool, EntryPoolNext
EntryPool => Pool % EntryPool
DO WHILE (ASSOCIATED(EntryPool))
EntryPoolNext => EntryPool % Next
DEALLOCATE(EntryPool % Entries)
DEALLOCATE(EntryPool)
EntryPool => EntryPoolNext
END DO
END SUBROUTINE ListMatrixPool_Free
FUNCTION ListMatrixPool_GetListEntry(Pool, ind, Next) RESULT(ListEntry)
IMPLICIT NONE
TYPE(ListMatrixPool_t) :: Pool
INTEGER, INTENT(IN) :: ind
TYPE(ListMatrixEntry_t), POINTER :: Next
TYPE(ListMatrixEntry_t), POINTER :: ListEntry
IF (ASSOCIATED(Pool % Deleted)) THEN
ListEntry => Pool % Deleted
Pool % Deleted => ListEntry % Next
ELSE
IF (Pool % PoolSize < Pool % EntryPool % NextIndex) THEN
CALL ListMatrixPool_Enlarge(Pool)
END IF
ListEntry => Pool % EntryPool % Entries(Pool % EntryPool % NextIndex)
Pool % EntryPool % NextIndex = Pool % EntryPool % NextIndex + 1
END IF
ListEntry % Index = ind
ListEntry % Next => Next
END FUNCTION ListMatrixPool_GetListEntry
SUBROUTINE ListMatrixPool_AddDeletedEntry(Pool, DEntry)
IMPLICIT NONE
TYPE(ListMatrixPool_t) :: Pool
TYPE(ListMatrixEntry_t), POINTER :: DEntry
DEntry % Next => Pool % Deleted
Pool % Deleted => DEntry
END SUBROUTINE ListMatrixPool_AddDeletedEntry
END MODULE ListMatrixArray