LCOV - code coverage report
Current view: top level - mtx/public - mtx_lib.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 38.3 % 60 23
Test Date: 2025-05-08 18:23:42 Functions: 33.3 % 15 5

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2010  The MESA Team
       4              : !
       5              : !   This program is free software: you can redistribute it and/or modify
       6              : !   it under the terms of the GNU Lesser General Public License
       7              : !   as published by the Free Software Foundation,
       8              : !   either version 3 of the License, or (at your option) any later version.
       9              : !
      10              : !   This program is distributed in the hope that it will be useful,
      11              : !   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              : !   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13              : !   See the GNU Lesser General Public License for more details.
      14              : !
      15              : !   You should have received a copy of the GNU Lesser General Public License
      16              : !   along with this program. If not, see <https://www.gnu.org/licenses/>.
      17              : !
      18              : ! ***********************************************************************
      19              : 
      20              : module mtx_lib
      21              : 
      22              :    use const_def, only: dp
      23              : 
      24              :    implicit none
      25              : 
      26              : contains
      27              : 
      28              :    ! mesa includes sources for a subset of BLAS and dble.
      29              :    ! you can use those, or, better yet, you can use a package optimized
      30              :    ! for your machine such as GotoBLAS or Intel's MKL.
      31              :    ! see utils/makefile_header for details.
      32              : 
      33              :    ! see mtx/blas_src for the subset of BLAS routines included in mtx_lib
      34              :    ! see mtx/dble_src for the subset of dble routines included in mtx_lib
      35              : 
      36              :    ! subroutines for dense and banded matrix decompositions and solves
      37              : 
      38              :    include "mtx_dble_decsol.dek"  ! dble versions
      39              : 
      40              :    !> Wraps the lapack DGBSVX routine for banded matrices to be used with block tridiagonal matrices.
      41              :       !!
      42              :       !! @params ublk The upper blocks. Shape is (nvars, nvars, nblocks-1).
      43              :       !! @params lblk The lower blocks. Shape is (nvars, nvars, nblocks-1).
      44              :       !! @params dblk The diagonal blocks. Shape is (nvars, nvars, nblocks).
      45              :       !! @params nblocks The number of blocks on the diagonal.
      46              :       !! @params nvars The width and height of each block (e.g. each block is nvars by nvars).
      47              :       !! @params x Array of shape (nblocks,nvar). Stores the result of solving Matrix.x = b.
      48              :       !! @params b Array of shape (nblocks,nvar). The right-hand side from the definition of x.
      49              :       !! @params ierr Integer-valued error code.
      50            0 :    subroutine DGBSVX_block_tridiagonal_padded(ublk, lblk, dblk, x, b, nblocks, nvar, rcond, ierr)
      51              :       use DGBSVX_wrapper, only: DGBSVX_tridiagonal_wrapper
      52              : 
      53              :       ! Inputs
      54              :       real(dp), dimension(:, :, :), intent(in) :: ublk, lblk, dblk
      55              :       real(dp), dimension(:, :), intent(in) :: b
      56              :       integer, intent(in) :: nblocks, nvar
      57              : 
      58              :       ! Intermediates
      59            0 :       real(dp) :: pre_conditioner(nvar, nblocks)
      60              : 
      61              :       ! Outputs
      62              :       real(dp), dimension(:, :), intent(out) :: x
      63              :       real(dp), intent(out) :: rcond
      64              :       integer, intent(out) :: ierr
      65              : 
      66            0 : call DGBSVX_tridiagonal_wrapper(ublk(:,:,1:nblocks-1), lblk(:,:,2:nblocks), dblk, pre_conditioner, x, b, nblocks, nvar, rcond, ierr)
      67              : 
      68            0 :    end subroutine DGBSVX_block_tridiagonal_padded
      69              : 
      70              :    !> Wraps the lapack DGBSVX routine for banded matrices to be used with block tridiagonal matrices.
      71              :       !! This version returns the pre-conditioning array which was used to rescale each row.
      72              :       !!
      73              :       !! @params ublk The upper blocks. Shape is (nvars, nvars, nblocks-1).
      74              :       !! @params lblk The lower blocks. Shape is (nvars, nvars, nblocks-1).
      75              :       !! @params dblk The diagonal blocks. Shape is (nvars, nvars, nblocks).
      76              :       !! @params nblocks The number of blocks on the diagonal.
      77              :       !! @params nvars The width and height of each block (e.g. each block is nvars by nvars).
      78              :       !! @params x Array of shape (nblocks,nvar). Stores the result of solving Matrix.x = b.
      79              :       !! @params b Array of shape (nblocks,nvar). The right-hand side from the definition of x.
      80              :       !! @params pre_conditioner Pre-conditioning vector. Computed in this routine.
      81              :       !! @params ierr Integer-valued error code.
      82            0 :    subroutine DGBSVX_block_tridiagonal_pc(ublk, lblk, dblk, pre_conditioner, x, b, nblocks, nvar, ierr)
      83              :       use DGBSVX_wrapper, only: DGBSVX_tridiagonal_wrapper
      84              : 
      85              :       ! Inputs
      86              :       real(dp), dimension(:, :, :), intent(in) :: ublk, lblk, dblk
      87              :       real(dp), dimension(:, :), intent(in) :: b
      88              :       integer, intent(in) :: nblocks, nvar
      89              : 
      90              :       ! Intermediates
      91              :       real(dp) :: rcond
      92              : 
      93              :       ! Outputs
      94              :       real(dp), dimension(:, :), intent(out) :: pre_conditioner
      95              :       real(dp), dimension(:, :), intent(out) :: x
      96              :       integer, intent(out) :: ierr
      97              : 
      98            0 :       call DGBSVX_tridiagonal_wrapper(ublk, lblk, dblk, pre_conditioner, x, b, nblocks, nvar, rcond, ierr)
      99              : 
     100            0 :    end subroutine DGBSVX_block_tridiagonal_pc
     101              : 
     102              :    !> Wraps the lapack DGBSVX routine for banded matrices to be used with block tridiagonal matrices.
     103              :       !!
     104              :       !! @params ublk The upper blocks. Shape is (nvars, nvars, nblocks-1).
     105              :       !! @params lblk The lower blocks. Shape is (nvars, nvars, nblocks-1).
     106              :       !! @params dblk The diagonal blocks. Shape is (nvars, nvars, nblocks).
     107              :       !! @params nblocks The number of blocks on the diagonal.
     108              :       !! @params nvars The width and height of each block (e.g. each block is nvars by nvars).
     109              :       !! @params x Array of shape (nblocks,nvar). Stores the result of solving Matrix.x = b.
     110              :       !! @params b Array of shape (nblocks,nvar). The right-hand side from the definition of x.
     111              :       !! @params ierr Integer-valued error code.
     112            0 :    subroutine DGBSVX_block_tridiagonal(ublk, lblk, dblk, x, b, nblocks, nvar, ierr)
     113              :       use DGBSVX_wrapper, only: DGBSVX_tridiagonal_wrapper
     114              : 
     115              :       ! Inputs
     116              :       real(dp), dimension(:, :, :), intent(in) :: ublk, lblk, dblk
     117              :       real(dp), dimension(:, :), intent(in) :: b
     118              :       integer, intent(in) :: nblocks, nvar
     119              : 
     120              :       ! Intermediates
     121            0 :       real(dp) :: pre_conditioner(nvar, nblocks)
     122            0 :       real(dp) :: rcond
     123              : 
     124              :       ! Outputs
     125              :       real(dp), dimension(:, :), intent(out) :: x
     126              :       integer, intent(out) :: ierr
     127              : 
     128            0 :       call DGBSVX_tridiagonal_wrapper(ublk, lblk, dblk, pre_conditioner, x, b, nblocks, nvar, rcond, ierr)
     129              : 
     130            0 :    end subroutine DGBSVX_block_tridiagonal
     131              : 
     132              :    !> Wraps the lapack DGBSVX routine for banded matrices with a preconditioner
     133              :       !! This version returns the pre-conditioning array which was used to rescale each row.
     134              :       !!
     135              :       !! @param matrix_size The number of rows or columns in the square matrix.
     136              :       !! @params n_upper_bands The number of bands above the diagonal.
     137              :       !! @params n_lower_bands The number of bands below the diagonal.
     138              :       !! @params bands Array of shape (n_upper_bands + n_lower_bands + 1, matrix_size). Stores the bands going from upper-most to lower-most, aligned so the first entry in each band has index 1.
     139              :       !! @params x Array of shape (matrix_size). Stores the result of solving Matrix.x = b.
     140              :       !! @params b Array of shape (matrix_size). The right-hand side from the definition of x.
     141              :       !! @params pre_conditioner Pre-conditioning vector. Computed in this routine.
     142              :       !! @params ierr Integer-valued error code.
     143            0 :    subroutine DGBSVX_banded_pc(matrix_size, n_upper_bands, n_lower_bands, bands, x, b, pre_conditioner, ierr)
     144              :       use DGBSVX_wrapper, only: DGBSVX_banded_wrapper
     145              : 
     146              :       ! Inputs
     147              :       real(dp), dimension(:, :), intent(in) :: bands
     148              :       real(dp), dimension(:), intent(in) :: b
     149              :       integer, intent(in) :: matrix_size, n_upper_bands, n_lower_bands
     150              : 
     151              :       ! Outputs
     152              :       real(dp), dimension(:), intent(out) :: x
     153              :       real(dp), dimension(:), intent(out) :: pre_conditioner
     154              :       integer, intent(out) :: ierr
     155              : 
     156            0 :       call DGBSVX_banded_wrapper(matrix_size, n_upper_bands, n_lower_bands, bands, x, b, pre_conditioner, ierr)
     157              : 
     158            0 :    end subroutine DGBSVX_banded_pc
     159              : 
     160              :    !> Wraps the lapack DGBSVX routine for banded matrices with a preconditioner
     161              :       !!
     162              :       !! @param matrix_size The number of rows or columns in the square matrix.
     163              :       !! @params n_upper_bands The number of bands above the diagonal.
     164              :       !! @params n_lower_bands The number of bands below the diagonal.
     165              :       !! @params bands Array of shape (n_upper_bands + n_lower_bands + 1, matrix_size). Stores the bands going from upper-most to lower-most, aligned so the first entry in each band has index 1.
     166              :       !! @params x Array of shape (matrix_size). Stores the result of solving Matrix.x = b.
     167              :       !! @params b Array of shape (matrix_size). The right-hand side from the definition of x.
     168              :       !! @params ierr Integer-valued error code.
     169            0 :    subroutine DGBSVX_banded(matrix_size, n_upper_bands, n_lower_bands, bands, x, b, ierr)
     170              :       use DGBSVX_wrapper, only: DGBSVX_banded_wrapper
     171              : 
     172              :       ! Inputs
     173              :       real(dp), dimension(:, :), intent(in) :: bands
     174              :       real(dp), dimension(:), intent(in) :: b
     175              :       integer, intent(in) :: matrix_size, n_upper_bands, n_lower_bands
     176              : 
     177              :       ! Intermediates
     178            0 :       real(dp) :: pre_conditioner(matrix_size)
     179              : 
     180              :       ! Outputs
     181              :       real(dp), dimension(:), intent(out) :: x
     182              :       integer, intent(out) :: ierr
     183              : 
     184            0 :       call DGBSVX_banded_wrapper(matrix_size, n_upper_bands, n_lower_bands, bands, x, b, pre_conditioner, ierr)
     185              : 
     186            0 :    end subroutine DGBSVX_banded
     187              : 
     188              :    ! sometimes you just need a null version of a routine
     189              :    include "mtx_null_decsol.dek"
     190              : 
     191              :    ! sometimes you need to debug a jacobian by saving it to plotting data files
     192              :    include "mtx_debug_decsol.dek"
     193              : 
     194              :    ! sparse matrices come in many formats.
     195              :    ! for example, compressed row sparse format is used by SPARSKIT,
     196              :    ! while compressed column sparse format is used by Super_LU.
     197              :    ! here are conversion routines for these two options.
     198              :    include "mtx_formats.dek"
     199              : 
     200            0 :    subroutine mtx_write_hbcode1(iounit, n, nnzero, values, rowind, colptr, ierr)
     201              :       use mtx_support, only: write_hbcode1
     202              :       integer, intent(in) :: iounit, n, nnzero
     203              :       integer :: rowind(:)  ! (nnzero)
     204              :       integer :: colptr(:)  ! (n+1)
     205              :       real(dp) :: values(:)  ! (nnzero)
     206              :       integer, intent(out) :: ierr
     207            0 :       call write_hbcode1(iounit, n, n, nnzero, values, rowind, colptr, ierr)
     208            0 :    end subroutine mtx_write_hbcode1
     209              : 
     210            0 :    subroutine mtx_write_block_tridiagonal(iounit, nvar, nblk, lblk, dblk, ublk, ierr)
     211              :       use mtx_support, only: write_block_tridiagonal
     212              :       integer, intent(in) :: iounit, nvar, nblk
     213              :       real(dp), intent(in), dimension(:, :, :) :: lblk, dblk, ublk
     214              :       integer, intent(out) :: ierr
     215            0 :       call write_block_tridiagonal(iounit, nvar, nblk, lblk, dblk, ublk, ierr)
     216            0 :    end subroutine mtx_write_block_tridiagonal
     217              : 
     218            1 :    subroutine mtx_read_block_tridiagonal(iounit, nvar, nblk, lblk1, dblk1, ublk1, ierr)
     219              :       use mtx_support, only: read_block_tridiagonal
     220              :       integer, intent(in) :: iounit
     221              :       integer, intent(out) :: nvar, nblk
     222              :       real(dp), pointer, dimension(:) :: lblk1, dblk1, ublk1  ! =(nvar,nvar,nblk) will be allocated
     223              :       integer, intent(out) :: ierr
     224            1 :       call read_block_tridiagonal(iounit, nvar, nblk, lblk1, dblk1, ublk1, ierr)
     225            1 :    end subroutine mtx_read_block_tridiagonal
     226              : 
     227              :    ! BCYCLIC multi-thread block tridiagonal
     228              :    include "mtx_bcyclic_dble_decsol.dek"
     229              :    ! S.P.Hirshman, K.S.Perumalla, V.E.Lynch, & R.Sanchez,
     230              :    ! BCYCLIC: A parallel block tridiagonal matrix cyclic solver,
     231              :    ! J. Computational Physics, 229 (2010) 6392-6404.
     232              : 
     233            1 :    subroutine block_dble_mv(nvar, nz, lblk, dblk, ublk, b, prod)
     234              :       ! set prod = A*b with A = block tridiagonal given by lblk, dblk, ublk
     235              :       use mtx_support, only: do_block_dble_mv
     236              :       integer, intent(in) :: nvar, nz
     237              :       real(dp), pointer, dimension(:, :, :), intent(in) :: lblk, dblk, ublk  ! (nvar,nvar,nz)
     238              :       real(dp), pointer, dimension(:, :), intent(in) :: b  ! (nvar,nz)
     239              :       real(dp), pointer, dimension(:, :), intent(inout) :: prod  ! (nvar,nz)
     240            1 :       call do_block_dble_mv(nvar, nz, lblk, dblk, ublk, b, prod)
     241            1 :    end subroutine block_dble_mv
     242              : 
     243            0 :    subroutine multiply_xa(n, A1, x, b)
     244              :       !  calculates b = x*A
     245              :       use mtx_support, only: do_multiply_xa
     246              :       integer, intent(in) :: n
     247              :       real(dp), pointer, intent(in) :: A1(:)  ! =(n, n)
     248              :       real(dp), pointer, intent(in) :: x(:)  ! (n)
     249              :       real(dp), pointer, intent(inout) :: b(:)  ! (n)
     250            0 :       call do_multiply_xa(n, A1, x, b)
     251            0 :    end subroutine multiply_xa
     252              : 
     253            0 :    subroutine block_multiply_xa(nvar, nz, lblk1, dblk1, ublk1, x1, b1)
     254              :       !  calculates b = x*A
     255              :       use mtx_support, only: do_block_multiply_xa
     256              :       integer, intent(in) :: nvar, nz
     257              :       real(dp), dimension(:), intent(in), pointer :: lblk1, dblk1, ublk1  ! =(nvar,nvar,nz)
     258              :       real(dp), intent(in), pointer :: x1(:)  ! =(nvar,nz)
     259              :       real(dp), intent(inout), pointer :: b1(:)  ! =(nvar,nz)
     260            0 :       call do_block_multiply_xa(nvar, nz, lblk1, dblk1, ublk1, x1, b1)
     261            0 :    end subroutine block_multiply_xa
     262              : 
     263           20 :    subroutine band_multiply_xa(n, kl, ku, ab1, ldab, x, b)
     264              :       !  calculates b = x*a = transpose(a)*x
     265              :       use mtx_support, only: do_band_multiply_xa
     266              :       integer, intent(in) :: n
     267              :       !          the number of linear equations, i.e., the order of the
     268              :       !          matrix a.  n >= 0.
     269              :       integer, intent(in) :: kl
     270              :       !          the number of subdiagonals within the band of a.  kl >= 0.
     271              :       integer, intent(in) :: ku
     272              :       !          the number of superdiagonals within the band of a.  ku >= 0.
     273              :       integer, intent(in) :: ldab
     274              :       !          the leading dimension of the array ab.  ldab >= kl+ku+1.
     275              :       real(dp), intent(in), pointer :: ab1(:)  ! =(ldab, n)
     276              :       !          the matrix a in band storage, in rows 1 to kl+ku+1;
     277              :       !          the j-th column of a is stored in the j-th column of the
     278              :       !          array ab as follows:
     279              :       !          ab(ku+1+i-j, j) = a(i, j) for max(1, j-ku)<=i<=min(n, j+kl)
     280              :       real(dp), intent(in), pointer :: x(:)  ! (n)
     281              :       !          the input vector to be multiplied by the matrix.
     282              :       real(dp), intent(inout), pointer :: b(:)  ! (n)
     283              :       !          on exit, set to matrix product of x*a = b
     284           20 :       call do_band_multiply_xa(n, kl, ku, ab1, ldab, x, b)
     285           20 :    end subroutine band_multiply_xa
     286              : 
     287              :    include "mtx_lapack95.dek"
     288              : 
     289              :    ! utilities for working with jacobians
     290              :    include "mtx_jac.dek"
     291              : 
     292              :    ! the following call dble routines to estimate matrix condition numbers.
     293              :    include "mtx_rcond.dek"
     294              : 
     295            4 :    integer function decsol_option(which_decsol_option, ierr)
     296              :       use mtx_def
     297              :       character(len=*), intent(in) :: which_decsol_option
     298              :       integer, intent(out) :: ierr
     299              :       character(len=64) :: option
     300            4 :       ierr = 0
     301            4 :       option = which_decsol_option
     302              : 
     303            4 :       if (option == 'lapack') then
     304              :          decsol_option = lapack
     305              : 
     306            0 :       else if (option == 'bcyclic_dble') then
     307              :          decsol_option = bcyclic_dble
     308              : 
     309              :       else
     310            0 :          ierr = -1
     311            0 :          decsol_option = -1
     312              :       end if
     313            4 :    end function decsol_option
     314              : 
     315            4 :    subroutine decsol_option_str(which_decsol_option, decsol_option, ierr)
     316              :       use mtx_def
     317              :       integer, intent(in) :: which_decsol_option
     318              :       character(len=*), intent(out) :: decsol_option
     319              :       integer, intent(out) :: ierr
     320            4 :       ierr = 0
     321              : 
     322            4 :       if (which_decsol_option == lapack) then
     323            1 :          decsol_option = 'lapack'
     324            3 :       else if (which_decsol_option == bcyclic_dble) then
     325            1 :          decsol_option = 'bcyclic_dble'
     326              : 
     327              :       else
     328            2 :          ierr = -1
     329            2 :          decsol_option = ''
     330              :       end if
     331              : 
     332            4 :    end subroutine decsol_option_str
     333              : 
     334            0 :    logical function is_block_tridiagonal_decsol(which_decsol_option)
     335              :       use mtx_def
     336              :       integer, intent(in) :: which_decsol_option
     337            0 :       is_block_tridiagonal_decsol = (which_decsol_option == bcyclic_dble)
     338            0 :    end function is_block_tridiagonal_decsol
     339              : 
     340              : end module mtx_lib
        

Generated by: LCOV version 2.0-1