test_solvers Program

Uses

  • program~~test_solvers~~UsesGraph program~test_solvers test_solvers module~data_arch data_arch program~test_solvers->module~data_arch module~gen_param gen_param program~test_solvers->module~gen_param module~miscellaneous miscellaneous program~test_solvers->module~miscellaneous module~solver solver program~test_solvers->module~solver omp_lib omp_lib program~test_solvers->omp_lib iso_fortran_env iso_fortran_env module~data_arch->iso_fortran_env module~gen_param->module~data_arch module~miscellaneous->module~data_arch module~solver->module~data_arch module~solver->module~gen_param hsl_ma48_double hsl_ma48_double module~solver->hsl_ma48_double iso_c_binding iso_c_binding module~solver->iso_c_binding module~solver->iso_fortran_env module~mumfpack mumfpack module~solver->module~mumfpack module~mumps_wrapper mumps_wrapper module~solver->module~mumps_wrapper module~sort_arrays sort_arrays module~solver->module~sort_arrays module~sulu_wrapper sulu_wrapper module~solver->module~sulu_wrapper module~mumfpack->iso_c_binding module~sort_arrays->module~data_arch module~sulu_wrapper->iso_c_binding

MSOLV example of use

Note

The program asks first for the matrix size: 1 for a very small matrix, and 0 for a bigger one.The systems are CC HB format systems with elemental matrices.

Small system – nnz=18

The system is (example provided by MUMP):

  • eltvar locates the elemental matrix line in the assembled matrix
  • eltptr gives the elemental matrix first entry position in eltvar (last position being size(eltvar)+1)

The rhs is (12, 7, 23, 6, 22), and the solution (1, 2, 3, 4, 5)

Big (well, in fact, medium) system – nnz=2,097,152

The system results from a MUSST study case and there is of course no theoretical solution to compare with

Warning

Some solver implementation are C written, so the arrays may begin at 0. It explains the variable dec in prod_a_x


Calls

program~~test_solvers~~CallsGraph program~test_solvers test_solvers omp_get_wtime omp_get_wtime program~test_solvers->omp_get_wtime proc~convert_matrice_format convert_matrice_format program~test_solvers->proc~convert_matrice_format proc~get_unit~2 get_unit program~test_solvers->proc~get_unit~2 proc~modify_a_elt modify_a_elt program~test_solvers->proc~modify_a_elt proc~solve_syst solve_syst program~test_solvers->proc~solve_syst proc~verif_solution verif_solution program~test_solvers->proc~verif_solution proc~from_elemental_to_assembled from_elemental_to_assembled proc~convert_matrice_format->proc~from_elemental_to_assembled proc~analyse_solver analyse_solver proc~solve_syst->proc~analyse_solver proc~close_solver close_solver proc~solve_syst->proc~close_solver proc~factorize_solver factorize_solver proc~solve_syst->proc~factorize_solver proc~freefact_solver freefact_solver proc~solve_syst->proc~freefact_solver proc~init_solver init_solver proc~solve_syst->proc~init_solver proc~solution_solver solution_solver proc~solve_syst->proc~solution_solver proc~prod_a_x prod_a_x proc~verif_solution->proc~prod_a_x proc~prod_elemental_x prod_elemental_x proc~verif_solution->proc~prod_elemental_x dmumps dmumps proc~analyse_solver->dmumps ma48_analyse ma48_analyse proc~analyse_solver->ma48_analyse proc~prep_superlu prep_superlu proc~analyse_solver->proc~prep_superlu proc~s_umfpack_di_symbolic s_umfpack_di_symbolic proc~analyse_solver->proc~s_umfpack_di_symbolic proc~close_solver->dmumps infog infog proc~close_solver->infog ma48_finalize ma48_finalize proc~close_solver->ma48_finalize mpi_finalize mpi_finalize proc~close_solver->mpi_finalize proc~close_superlu close_superlu proc~close_solver->proc~close_superlu proc~umfpack_di_free_numeric umfpack_di_free_numeric proc~close_solver->proc~umfpack_di_free_numeric proc~umfpack_di_free_symbolic umfpack_di_free_symbolic proc~close_solver->proc~umfpack_di_free_symbolic proc~umfpack_di_report_info umfpack_di_report_info proc~close_solver->proc~umfpack_di_report_info proc~factorize_solver->dmumps ma48_factorize ma48_factorize proc~factorize_solver->ma48_factorize proc~fact_superlu fact_superlu proc~factorize_solver->proc~fact_superlu proc~s_umfpack_di_numeric s_umfpack_di_numeric proc~factorize_solver->proc~s_umfpack_di_numeric proc~factorize_solver->proc~umfpack_di_free_numeric proc~free_superlu free_superlu proc~freefact_solver->proc~free_superlu proc~freefact_solver->proc~umfpack_di_free_numeric proc~sort_array2 sort_array2 proc~from_elemental_to_assembled->proc~sort_array2 proc~init_solver->dmumps icntl icntl proc~init_solver->icntl proc~init_solver->infog ma48_initialize ma48_initialize proc~init_solver->ma48_initialize proc~init_solver->mpi_finalize mpi_init mpi_init proc~init_solver->mpi_init proc~init_superlu init_superlu proc~init_solver->proc~init_superlu proc~umfpack_di_defaults umfpack_di_defaults proc~init_solver->proc~umfpack_di_defaults proc~umfpack_di_report_control umfpack_di_report_control proc~init_solver->proc~umfpack_di_report_control proc~solution_solver->proc~solve_syst proc~solution_solver->dmumps proc~solution_solver->infog ma48_solve ma48_solve proc~solution_solver->ma48_solve proc~solution_solver->mpi_finalize proc~s_umfpack_di_solve s_umfpack_di_solve proc~solution_solver->proc~s_umfpack_di_solve proc~solv_superlu solv_superlu proc~solution_solver->proc~solv_superlu rhs rhs proc~solution_solver->rhs interface~destroy_compcol_matrix Destroy_CompCol_Matrix proc~close_superlu->interface~destroy_compcol_matrix interface~destroy_dense_matrix Destroy_Dense_Matrix proc~close_superlu->interface~destroy_dense_matrix interface~dgssvx dgssvx proc~fact_superlu->interface~dgssvx interface~statfree StatFree proc~fact_superlu->interface~statfree interface~statinit StatInit proc~fact_superlu->interface~statinit interface~statprint StatPrint proc~fact_superlu->interface~statprint interface~set_default_options set_default_options proc~init_superlu->interface~set_default_options interface~dcreate_compcol_matrix dCreate_CompCol_Matrix proc~prep_superlu->interface~dcreate_compcol_matrix interface~dcreate_dense_matrix dCreate_Dense_Matrix proc~prep_superlu->interface~dcreate_dense_matrix proc~umfpack_di_numeric umfpack_di_numeric proc~s_umfpack_di_numeric->proc~umfpack_di_numeric proc~umfpack_di_solve umfpack_di_solve proc~s_umfpack_di_solve->proc~umfpack_di_solve proc~umfpack_di_symbolic umfpack_di_symbolic proc~s_umfpack_di_symbolic->proc~umfpack_di_symbolic proc~solv_superlu->proc~prep_superlu proc~solv_superlu->interface~destroy_compcol_matrix interface~destroy_supernode_matrix Destroy_SuperNode_Matrix proc~solv_superlu->interface~destroy_supernode_matrix proc~solv_superlu->interface~dgssvx proc~solv_superlu->interface~statfree proc~solv_superlu->interface~statinit proc~solv_superlu->interface~statprint proc~change_array_order change_array_order proc~sort_array2->proc~change_array_order proc~init_order init_order proc~sort_array2->proc~init_order proc~sort_array_integer_with_order sort_array_integer_with_order proc~sort_array2->proc~sort_array_integer_with_order proc~sort_array_real_with_order sort_array_real_with_order proc~sort_array2->proc~sort_array_real_with_order interface~c_umfpack_di_defaults c_umfpack_di_defaults proc~umfpack_di_defaults->interface~c_umfpack_di_defaults interface~c_umfpack_di_free_numeric c_umfpack_di_free_numeric proc~umfpack_di_free_numeric->interface~c_umfpack_di_free_numeric interface~c_umfpack_di_free_symbolic c_umfpack_di_free_symbolic proc~umfpack_di_free_symbolic->interface~c_umfpack_di_free_symbolic interface~c_umfpack_di_report_control c_umfpack_di_report_control proc~umfpack_di_report_control->interface~c_umfpack_di_report_control interface~c_umfpack_di_report_info c_umfpack_di_report_info proc~umfpack_di_report_info->interface~c_umfpack_di_report_info proc~sort_array_integer_with_order->proc~sort_array_integer_with_order proc~sort_array_real_with_order->proc~sort_array_real_with_order interface~c_umfpack_di_numeric c_umfpack_di_numeric proc~umfpack_di_numeric->interface~c_umfpack_di_numeric interface~c_umfpack_di_solve c_umfpack_di_solve proc~umfpack_di_solve->interface~c_umfpack_di_solve interface~c_umfpack_di_symbolic c_umfpack_di_symbolic proc~umfpack_di_symbolic->interface~c_umfpack_di_symbolic

Variables

Type Attributes Name Initial
real(kind=R8), dimension(:), allocatable :: a_elt

matrix non-zero entries in CC

real(kind=R8), dimension(:), allocatable :: a_elt_ref

initial a_elt

real(kind=R8), dimension(:), allocatable :: b

system right hand side

integer(kind=I4), dimension(:), allocatable :: eltptr

elemental matrices position in eltvar

integer(kind=I4), dimension(:), allocatable :: eltvar

elemental matrix global lines

real(kind=R8) :: error
integer(kind=I4) :: i
integer(kind=I4) :: ii
integer(kind=I4) :: size_a_elt
type(MAT_SOLV) :: slv_struct
integer(kind=I4) :: state
real(kind=R8) :: time1
real(kind=R8) :: time2
integer(kind=I4) :: uu

Subroutines

subroutine modify_a_elt(tab, nz)

mMltiplication of the system coefficient by a random factor

Arguments

Type IntentOptional Attributes Name
real(kind=R8), intent(inout) :: tab(1:nz)
integer(kind=I4), intent(in) :: nz

subroutine prod_a_x(n, nz, x, y, a_elt, irow, jptr, slvt)

, assembled CC format

Arguments

Type IntentOptional Attributes Name
integer(kind=I4), intent(in) :: n
integer(kind=I4), intent(in) :: nz
real(kind=R8), intent(in), dimension(n) :: x
real(kind=R8), intent(out), dimension(n) :: y
real(kind=R8), intent(in), dimension(nz) :: a_elt
integer(kind=I4), intent(in), dimension(nz ) :: irow
integer(kind=I4), intent(in), dimension(n+1) :: jptr
integer(kind=I4), intent(in) :: slvt

subroutine prod_elemental_x(n, nz, nelt, nvar, x, y, a_elt, eltptr, eltvar)

, elemental CC format

Arguments

Type IntentOptional Attributes Name
integer(kind=I4), intent(in) :: n
integer(kind=I4), intent(in) :: nz
integer(kind=I4), intent(in) :: nelt
integer(kind=I4), intent(in) :: nvar
real(kind=R8), intent(in), dimension(n) :: x
real(kind=R8), intent(out), dimension(n) :: y
real(kind=R8), intent(in), dimension(nz ) :: a_elt
integer(kind=I4), intent(in), dimension(nelt +1) :: eltptr
integer(kind=I4), intent(in), dimension(nvar ) :: eltvar

subroutine verif_solution(slv_struct, a_elt, b, error)

The product of the system matrix by the solution , is calculated, and compared to the right hand side . The calculated error is the absolute error in %.

Read more…

Arguments

Type IntentOptional Attributes Name
type(MAT_SOLV), intent(in) :: slv_struct
real(kind=R8), intent(in), dimension(:) :: a_elt
real(kind=R8), intent(in), dimension(:) :: b
real(kind=R8), intent(out) :: error

Source Code

program test_solvers
use omp_lib,   only :   omp_get_wtime
use data_arch, only :   I4, R4, R8, &
                        OPU,        & ! *default output unit*
                        IPU           ! *default input unit*
use miscellaneous, only : get_unit

use gen_param, only :   SOLV_MESS,    & ! *Solver message: yes=```PRINT_MESS```, no=```NO_MESS```*
                        NO_MESS,      & ! *no output message*
                        PRINT_MESS      ! *solver infos output*

use solver,    only :   MAT_SOLV,     & ! *system data type*
                        solve_syst,   & ! *subroutine for the system resolution*
                        MUMP,         & ! *integer*
                        UMFP,         & ! *integer*
                        SULU,         & ! *integer*
                        convert_matrice_format ! *various matrix format conversion*
implicit none

integer(kind=I4) :: i, ii, uu, size_a_elt, state
real(kind=R8)    :: time1, time2, error
type(MAT_SOLV)   :: slv_struct

real(kind=R8),    dimension(:), allocatable :: b            !! *system right hand side*
real(kind=R8),    dimension(:), allocatable :: a_elt        !! *matrix non-zero entries in CC*
real(kind=R8),    dimension(:), allocatable :: a_elt_ref    !! *initial ```a_elt```*
integer(kind=I4), dimension(:), allocatable :: eltptr       !! *elemental matrices position in ```eltvar```*
integer(kind=I4), dimension(:), allocatable :: eltvar       !! *elemental matrix global lines*

   SOLV_MESS = NO_MESS!PRINT_MESS!

   write(OPU, *) 'small matrix? 0:n, 1:y'
   read( IPU, *) i

   ! ======================== SOLVER TYPE ===========================================
   do
      write(OPU, *) 'data read, choose solver n° : 0-MA48, 1-SULU, 2-MUMP (ref), 3-UMFP'
      read( IPU, *) ii
      slv_struct%slv_t = ii
      if (ii>=0 .and. ii<=3) exit
   enddo

   ! ======================== SYST DATA READ ===========================================
   call get_unit(uu)

   if (i==0) then
      open(unit = uu, file = "mat/big_syst.bin",   form = 'unformatted', access = 'stream')
   else
      open(unit = uu, file = "mat/small_syst.bin", form = 'unformatted', access = 'stream')
   endif

   ! ======================== SYST INFO ===========================================
   read(uu) slv_struct%nn, slv_struct%ne, slv_struct%nvar, slv_struct%nt

   write(OPU, *) '*************** INFO ********************'
   write(OPU, *) 'system size:                  ', slv_struct%nn
   write(OPU, *) 'number of elemental matrices: ', slv_struct%ne
   write(OPU, *) 'number of nnz entries:        ', slv_struct%nt
   write(OPU, *) '*****************************************'

   allocate( eltvar(slv_struct%nvar  ) )
   allocate( a_elt(     slv_struct%nt    ), stat = state ) ; if (state/=0) stop 'Memory allocation problem in PRG'
   allocate( a_elt_ref( slv_struct%nt    ), stat = state ) ; if (state/=0) stop 'Memory allocation problem in PRG'
   allocate( eltptr(slv_struct%ne +1 ) )
   allocate(      b(slv_struct%nn    ) )

   allocate( slv_struct%eltvar(slv_struct%nvar  ) )
   allocate( slv_struct%a_elt( slv_struct%nt    ), stat = state ) ; if (state/=0) stop 'Memory allocation problem in PRG'
   allocate( slv_struct%eltptr(slv_struct%ne +1 ) )


   call solve_syst(mat = slv_struct, step = 'ini')

   do ii = 1, slv_struct%nvar
      read(uu) slv_struct%eltvar(ii)
   enddo
   do ii = 1, slv_struct%ne +1
      read(uu) slv_struct%eltptr(ii)
   enddo
   do ii = 1, slv_struct%nt
      read(uu) slv_struct%a_elt(ii)
   enddo
   do ii = 1, slv_struct%nn
      read(uu) slv_struct%b(ii)
   enddo

   close(uu)

   ! The matrices are in CC HB format. Only MUMPS accepts elemental entries, so the
   ! following subroutine converts elemental marices to assembled vectors.
   ! If MUMPS is chosen, nothing is done.
   call convert_matrice_format(mat = slv_struct)
   ! ======================== backup ============================================
   eltvar     = slv_struct%eltvar
   a_elt_ref  = slv_struct%a_elt
   eltptr     = slv_struct%eltptr
   b          = slv_struct%b

   ! ======================== PROCESS ===========================================
   time1 = omp_get_wtime()
      call solve_syst(mat = slv_struct, step = 'ana') ; write(OPU, *) 'system analyzed'
      call solve_syst(mat = slv_struct, step = 'fac') ; write(OPU, *) 'system factorized'
      call solve_syst(mat = slv_struct, step = 'sol') ; write(OPU, *) 'system solved'
      call solve_syst(mat = slv_struct, step = 'fre') ; write(OPU, *) 'system freed'
   time2 = omp_get_wtime()

   call verif_solution(slv_struct = slv_struct, a_elt = a_elt_ref, b = b, error = error)

   write(OPU,*) 'max error    = ', error
   write(OPU,*) 'elapsed time = ', real(abs(time1 -time2), kind=R4)

   ! Here, the matrix coefficients are modified, but the sparsity is conserved. It gives a look to the ability
   ! of the solver to exploit the symbolic calculations performed before.
   do

      if (slv_struct%slv_t==MUMP) then
         size_a_elt   = size(slv_struct%a_elt)
      else
         size_a_elt   = slv_struct%nt
      endif

      ! the original entries are retrieved, then modified
      a_elt = a_elt_ref
      call modify_a_elt(tab = a_elt, nz = size_a_elt)
      slv_struct%a_elt  = a_elt
      slv_struct%b      = b
      slv_struct%x      = 0._R8

      time1 = omp_get_wtime()
         call solve_syst(mat = slv_struct, step = 'fac')
         call solve_syst(mat = slv_struct, step = 'sol')
         call solve_syst(mat = slv_struct, step = 'fre')
      time2 = omp_get_wtime()

      call verif_solution(slv_struct = slv_struct, a_elt = a_elt, b = b, error = error)

      write(OPU,*) 'max error    = ', error
      write(OPU,*) 'elapsed time = ', real(abs(time1 -time2), kind=R4)

      write(OPU, *) 'STOP? (y=1, n=0)'
      read( IPU, *) ii
      if (ii==1) exit
   enddo

   deallocate(eltvar, a_elt, a_elt_ref, eltptr, b)

   call solve_syst(mat = slv_struct, step = 'end')

stop

contains

   !=========================================================================================
   !< @note The product \(\{y\}\) of the system matrix \([A]\) by the solution \(\{x\}\), is
   !<        calculated, and compared to the right hand side \(\{b\}\).
   !<        The calculated error is the absolute error in %.
   !< @endnote
   !-----------------------------------------------------------------------------------------
   subroutine verif_solution(slv_struct, a_elt, b, error)
   implicit none
   type(MAT_SOLV), intent(in) :: slv_struct
   real(kind=R8), dimension(:), intent(in) :: a_elt
   real(kind=R8), dimension(:), intent(in) :: b
   real(kind=R8), intent(out) :: error
      real(kind=R8), dimension(slv_struct%nn) :: y
      ! to assess the accuracy, the solution is applied to the
      ! system matrix and compared to the rhs.
      if (slv_struct%slv_t==MUMP) then
         call prod_elemental_x(n      = slv_struct%nn,      &
                               nz     = slv_struct%nt,      &
                               nelt   = slv_struct%ne,      &
                               nvar   = slv_struct%nvar,    &
                               x      = slv_struct%x,       &
                               y      = y,                  &
                               a_elt  = a_elt,              &
                               eltptr = slv_struct%eltptr,  &
                               eltvar = slv_struct%eltvar)
      else
         call prod_a_x(n  = slv_struct%nn,         &
                       nz = slv_struct%nz,         &
                       x  = slv_struct%x,          &
                       y  = y,                     &
                       a_elt = a_elt,              &
                       irow  = slv_struct%irow,    &
                       jptr  = slv_struct%jptr,    &
                       slvt  = slv_struct%slv_t)
      endif

      error = 100*maxval( abs(y(1:slv_struct%nn) -b(1:slv_struct%nn)) )/ &
                  maxval( abs(y(1:slv_struct%nn) +b(1:slv_struct%nn)) )
   return
   endsubroutine verif_solution


   !=========================================================================================
   subroutine modify_a_elt(tab, nz)
   !! mMltiplication of the system coefficient by a random factor
   implicit none
   integer(kind=I4), intent(in) :: nz
   real(kind=R8), intent(inout) :: tab(1:nz)
      real(kind=R8), allocatable :: tmp(:)
      allocate(tmp(1:nz))
      call random_number(harvest=tmp(1:nz))
      tmp(1:nz) = 2*tmp(1:nz) -1.0_R8
      tab(1:nz) = tab(1:nz)*tmp(1:nz)
      deallocate(tmp)
   return
   endsubroutine modify_a_elt


   !=========================================================================================
   subroutine prod_a_x(n, nz, x, y, a_elt, irow, jptr, slvt)
   !! \([A] \{x\}\), assembled CC format
   implicit none
   integer(kind=I4), intent(in) :: n, nz, slvt
   real(kind=R8), dimension(nz), intent(in)     :: a_elt
   integer(kind=I4), dimension(nz ), intent(in) :: irow
   integer(kind=I4), dimension(n+1), intent(in) :: jptr
   real(kind=R8), dimension(n), intent(in)      :: x
   real(kind=R8), dimension(n), intent(out)     :: y
      integer(kind=I4) :: i, k, dec
      y(1:n) = 0._R8
      dec = 0
      if (slvt==UMFP .or. slvt==SULU) dec = 1
      do i = 1, n
         do k = jptr(i), jptr(i+1)-1
            y(irow(k +dec) +dec) = y(irow(k +dec) +dec) + x(i)*a_elt(k +dec)
         enddo
      enddo
   return
   endsubroutine prod_a_x


   !=========================================================================================
   subroutine prod_elemental_x(n, nz, nelt, nvar, x, y, a_elt, eltptr, eltvar)
   !! \([A] \{x\}\), elemental CC format
   implicit none
   integer(kind=I4), intent(in) :: n, nz, nelt, nvar
   real(kind=R8),    dimension(nz     ), intent(in) :: a_elt
   integer(kind=I4), dimension(nelt +1), intent(in) :: eltptr
   integer(kind=I4), dimension(nvar   ), intent(in) :: eltvar
   real(kind=R8), dimension(n), intent(in)      :: x
   real(kind=R8), dimension(n), intent(out)     :: y
      integer(kind=I4) :: i, j, k, kk, inc_nz, inc_nn, n_elem, i_elem, max_n_elem
      real(kind=R8), dimension(:), allocatable :: a_elt_tmp, x_tmp, y_tmp
      inc_nz = 0
      inc_nn = 0
      n_elem = 0
      y      = 0._R8

      max_n_elem = 0
      do i_elem = 1, nelt
         max_n_elem = max(max_n_elem, eltptr(i_elem +1) -eltptr(i_elem))
      enddo

      allocate( a_elt_tmp(1:max_n_elem**2) )
      allocate(     x_tmp(1:max_n_elem   ) )
      allocate(     y_tmp(1:max_n_elem   ) )

      do i_elem = 1, nelt                                               ! browse all elemental matrices
         inc_nn = inc_nn +n_elem                                        ! step in eltvar for matrix number i_elem
         inc_nz = inc_nz +n_elem**2                                     ! step in a_elt for matrix number i_elem
         n_elem = eltptr(i_elem +1) -eltptr(i_elem)                     ! elemental matrix size
         a_elt_tmp(1:n_elem**2) = a_elt(inc_nz +1 : inc_nz +n_elem**2)  ! elemental matrix coefficients
         ! --- elemental rhs
         kk = 0
         do k = inc_nn +1, inc_nn +n_elem
            kk = kk +1
            x_tmp(kk) = x(eltvar(k))
         enddo
         ! --- elemental product
         y_tmp(1:n_elem) = 0._R8
         do i = 1, n_elem
            do j = 1, n_elem
               y_tmp(i) = y_tmp(i) +a_elt_tmp(i +n_elem*(j-1))*x_tmp(j)
            enddo
         enddo
         ! --- elemental product in global vector y
         kk = 0
         do k = inc_nn +1, inc_nn +n_elem
            kk = kk +1
            y(eltvar(k)) = y(eltvar(k)) +y_tmp(kk)
         enddo
      enddo
      deallocate(a_elt_tmp, x_tmp, y_tmp)
   return
   endsubroutine prod_elemental_x

endprogram test_solvers