CSR_SparseMatrix.F90 Source File


This file depends on

sourcefile~~csr_sparsematrix.f90~~EfferentGraph sourcefile~csr_sparsematrix.f90 CSR_SparseMatrix.F90 sourcefile~keywordenforcer.f90 KeywordEnforcer.F90 sourcefile~csr_sparsematrix.f90->sourcefile~keywordenforcer.f90

Files dependent on this one

sourcefile~~csr_sparsematrix.f90~~AfferentGraph sourcefile~csr_sparsematrix.f90 CSR_SparseMatrix.F90 sourcefile~test_csr_sparsematrix.pf Test_CSR_SparseMatrix.pf sourcefile~test_csr_sparsematrix.pf->sourcefile~csr_sparsematrix.f90

Source Code

#include "MAPL_Generic.h"

! When generic procedures are available, this package should be
! redesigned.
module mapl3g_CSR_SparseMatrix
   use mapl_KeywordEnforcer
   use, intrinsic :: iso_fortran_env, only: REAL32, REAL64
   implicit none (type, external)
   private

#define IDENTITY(x) x
#define CONCAT(a,b) IDENTITY(a)IDENTITY(b)
#define CONCAT3(a,b,c) IDENTITY(a)IDENTITY(b)IDENTITY(c)
#define T(kz) CONCAT(CSR_SparseMatrix_,kz)


   public :: T(sp)
   public :: T(dp)
   public :: matmul
   public :: add_row

   integer, parameter :: sp = REAL32
   integer, parameter :: dp = REAL64

#define CSR_SPARSEMATRIX(kz)                                    \
   type :: T(kz);                                               \
      private;                                                  \
      integer :: n_rows;                                        \
      integer :: n_columns;                                     \
      integer :: nnz;                                           \
                                                                \
      integer, allocatable :: row_offsets(:);                   \
      integer, allocatable :: run_starts(:);                    \
      integer, allocatable :: run_lengths(:);                   \
      real(kind=kz), allocatable :: v(:);                       \
   end type T(kz)                                              ;\
   interface matmul                                            ;\
      procedure CONCAT3(matmul_vec_,kz,sp)                     ;\
      procedure CONCAT3(matmul_vec_,kz,dp)                     ;\
      procedure CONCAT3(matmul_multi_vec_,kz,sp)               ;\
      procedure CONCAT3(matmul_multi_vec_,kz,dp)               ;\
   end interface matmul                                        ;\
   interface add_row                                           ;\
      procedure CONCAT(add_row_,kz)                            ;\
   end interface add_row                                       ;\
   interface T(kz)                                             ;\
      procedure CONCAT(new_csr_matrix_,kz)                     ;\
   end interface T(kz)

CSR_SPARSEMATRIX(sp)   

CSR_SPARSEMATRIX(dp)   

contains

#define NEW_CSR_MATRIX(kz)                                                        \
   function CONCAT(new_csr_matrix_,kz)(n_rows, n_columns, nnz) result(mat)       ;\
      type(T(kz)) :: mat                                                         ;\
      integer, intent(in) :: n_rows                                              ;\
      integer, intent(in) :: n_columns                                           ;\
      integer, intent(in) :: nnz                                                 ;\
      mat%n_rows = n_rows                                                        ;\
      mat%n_columns = n_columns                                                  ;\
      mat%nnz = nnz                                                              ;\
      allocate(mat%row_offsets(n_rows+1))                                        ;\
      allocate(mat%run_starts(n_rows))                                           ;\
      allocate(mat%run_lengths(n_rows))                                          ;\
      allocate(mat%v(nnz))                                                       ;\
      mat%row_offsets(1) = 0                                                     ;\
   end function


#define ADD_ROW(kz)                                                  \
   pure subroutine CONCAT(add_row_,kz)(this, row, start_column, v)  ;\
      type(T(kz)), intent(inout) :: this                            ;\
      integer, intent(in) :: row                                    ;\
      integer, intent(in) :: start_column                           ;\
      real(kz), intent(in) :: v(:)                                  ;\
                                                                     \
      associate (n => size(v), offset => this%row_offsets(row))     ;\
                                                                     \
        this%run_lengths(row) = n                                   ;\
        this%run_starts(row) = start_column                         ;\
        this%v(offset+1:offset+n) = v                               ;\
        this%row_offsets(row+1) = offset + n                        ;\
                                                                     \
      end associate                                                 ;\
                                                                     \
   end subroutine


#define MATMUL_VEC(kz,kx)                                            \
   pure function CONCAT3(matmul_vec_,kz,kx)(A, x) result(y)          ;\
      type(T(kz)), intent(in) :: A                                  ;\
      real(kx), intent(in) :: x(:)                                  ;\
      real(kx) :: y(A%n_rows)                                       ;\
                                                                     \
      integer :: i, j                                               ;\
                                                                     \
      do concurrent (i = 1:A%n_rows)                                ;\
                                                                     \
         y(i) = 0                                                   ;\
         associate (n => A%run_lengths(i))                           ;\
           if (n == 0) cycle                                        ;\
                                                                     \
           associate (j0 => A%run_starts(i))                        ;\
             associate (j1 => j0 + n - 1)                           ;\
                                                                     \
               do j = j0, j1                                        ;\
                  associate (jj => A%row_offsets(i) + (j-j0) + 1)   ;\
                    y(i) = y(i) + A%v(jj) * x(j)                    ;\
                  end associate                                     ;\
               end do                                               ;\
                                                                     \
             end associate                                          ;\
           end associate                                            ;\
                                                                     \
         end associate                                              ;\
      end do                                                        ;\
                                                                     \
   end function

#define MATMUL_MULTI_VEC(kz,kx)                                      \
   pure function CONCAT3(matmul_multi_vec_,kz,kx)(A, x) result(b)   ;\
      type(T(kz)), intent(in) :: A(:)                               ;\
      real(kx), intent(in) :: x(:,:)                                ;\
      real(kx) :: b(size(A,1),A(1)%n_rows)                          ;\
      integer :: i                                                  ;\
      do concurrent (i=1:size(A))                                   ;\
         b(i,:) = matmul(A(i), x(i,:))                              ;\
      end do                                                        ;\
   end function

   NEW_CSR_MATRIX(sp)
   ADD_ROW(sp)
   MATMUL_VEC(sp,sp)
   MATMUL_VEC(sp,dp)
   MATMUL_MULTI_VEC(sp,sp)
   MATMUL_MULTI_VEC(sp,dp)

   NEW_CSR_MATRIX(dp)
   ADD_ROW(dp)
   MATMUL_VEC(dp,sp)
   MATMUL_VEC(dp,dp)
   MATMUL_MULTI_VEC(dp,sp)
   MATMUL_MULTI_VEC(dp,dp)


end module mapl3g_CSR_SparseMatrix