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

Generated by: LCOV version 2.0-1