lusol_ez.f90 Source File


This file depends on

sourcefile~~lusol_ez.f90~~EfferentGraph sourcefile~lusol_ez.f90 lusol_ez.f90 sourcefile~lusol.f90 lusol.f90 sourcefile~lusol_ez.f90->sourcefile~lusol.f90 sourcefile~lusol_precision.f90 lusol_precision.F90 sourcefile~lusol_ez.f90->sourcefile~lusol_precision.f90 sourcefile~lusol.f90->sourcefile~lusol_precision.f90

Files dependent on this one

sourcefile~~lusol_ez.f90~~AfferentGraph sourcefile~lusol_ez.f90 lusol_ez.f90 sourcefile~lusol_test.f90 lusol_test.f90 sourcefile~lusol_test.f90->sourcefile~lusol_ez.f90 sourcefile~nlesolver_module.f90 nlesolver_module.F90 sourcefile~nlesolver_module.f90->sourcefile~lusol_ez.f90 sourcefile~nlesolver_test_1.f90 nlesolver_test_1.f90 sourcefile~nlesolver_test_1.f90->sourcefile~nlesolver_module.f90 sourcefile~sparse_test.f90 sparse_test.f90 sourcefile~sparse_test.f90->sourcefile~nlesolver_module.f90

Source Code

!*****************************************************************************************
!>
!  Wrapper for LUSOL. Will eventually be moved into a separate repo.

    module lusol_ez_module

    use lusol,           only: lu1fac, lu6sol
    use lusol_precision, only : ip, rp

    implicit none

    private

    type,public :: lusol_settings
        integer(ip) :: nout = 6
        integer(ip) :: lprint = 0
        integer(ip) :: maxcol = 5
        integer(ip) :: method = 0 ! TPP
        integer(ip) :: keepLU = 1

        real(rp) :: Ltol1 = 100.0_rp
        real(rp) :: Ltol2 = 10.0_rp
        real(rp) :: small = epsilon(1.0_rp)**0.8_rp
        real(rp) :: Utol1 = epsilon(1.0_rp)**0.67_rp
        real(rp) :: Utol2 = epsilon(1.0_rp)**0.67_rp
        real(rp) :: Uspace = 3.0_rp
        real(rp) :: dens1 = 0.3_rp
        real(rp) :: dens2 = 0.5_rp

        integer(ip) :: mode = 5 ! for [[lu6sol]] : `w` solves `A w = v`.
    end type lusol_settings


    public :: solve

    contains
!*****************************************************************************************

!*****************************************************************************************
!>
!  Wrapper for [[lu1fac]] + [[lu6sol]] to solve a linear system `A*x = b`.

    subroutine solve(n_cols,n_rows,n_nonzero,irow,icol,mat,b,x,istat,settings)

    integer,intent(in) :: n_cols !! `n`: number of columns in A.
    integer,intent(in) :: n_rows !! `m`: number of rows in A.
    integer,intent(in) :: n_nonzero !! number of nonzero elements of A.
    integer,dimension(n_nonzero),intent(in) :: irow, icol !! sparsity pattern (size is `n_nonzero`)
    real(rp),dimension(n_nonzero),intent(in) :: mat !! matrix elements (size is `n_nonzero`)
    real(rp),dimension(n_rows),intent(in) :: b !! right hand side (size is `m`)
    real(rp),dimension(n_cols),intent(out) :: x !! solution !size is `n`
    integer,intent(out) :: istat !! status code
    type(lusol_settings),intent(in),optional :: settings !! settings (if not present, defaults are used)

    integer(ip) :: nelem, n, m
    integer(ip) :: lena
    real(rp),dimension(:),allocatable :: a
    integer(ip),dimension(:),allocatable :: indc
    integer(ip),dimension(:),allocatable :: indr
    real(rp),dimension(:),allocatable :: ww
    real(rp),dimension(:),allocatable :: w
    real(rp),dimension(:),allocatable :: v
    integer(ip) :: inform
    integer(ip) :: luparm(30)
    real(rp) :: parmlu(30)
    integer(ip),dimension(:),allocatable :: p, q,  &
                                            lenc, lenr,  &
                                            iploc, iqloc,  &
                                            ipinv, iqinv,  &
                                            locc, locr

    type(lusol_settings) :: options

    if (present(settings)) options = settings ! use user-supplied settings

    n = n_cols
    m = n_rows
    nelem = n_nonzero
    lena = 1 + max( 2*nelem, 10*m, 10*n, 10000 )

    allocate(a(lena))
    allocate(indc(lena))
    allocate(indr(lena))
    associate (n =>n_cols, m => n_rows)
        allocate(p(m), q(n), lenc(n), lenr(m), &
                 iploc(n), iqloc(m), ipinv(m), &
                 iqinv(n), locc(n) , locr(m))
        allocate(ww(n))
        allocate(w(n)) ! x
        allocate(v(m)) ! b
    end associate

    a = 0; indc=0; indr=0
    a(1:nelem) = mat
    indc(1:nelem) = irow
    indr(1:nelem) = icol

    ! settings
    luparm = 0
    luparm( 1) = options%nout
    luparm( 2) = options%lprint
    luparm( 3) = options%maxcol
    luparm( 6) = options%method
    luparm( 8) = options%keepLU
    parmlu = 0
    parmlu( 1) = options%Ltol1
    parmlu( 2) = options%Ltol2
    parmlu( 3) = options%small
    parmlu( 4) = options%Utol1
    parmlu( 5) = options%Utol2
    parmlu( 6) = options%Uspace
    parmlu( 7) = options%dens1
    parmlu( 8) = options%dens2

    call lu1fac( m    , n    , nelem, lena , luparm, parmlu, &
                 a    , indc , indr , p    , q     ,         &
                 lenc , lenr , locc , locr ,                 &
                 iploc, iqloc, ipinv, iqinv, ww     , inform )

    !write(*,*) 'lu1fac inform = ', inform

    !  inform = 0 if the LU factors were obtained successfully.
    !         = 1 if U appears to be singular, as judged by lu6chk.
    !         = 3 if some index pair indc(l), indr(l) lies outside
    !             the matrix dimensions 1:m , 1:n.
    !         = 4 if some index pair indc(l), indr(l) duplicates
    !             another such pair.
    !         = 7 if the arrays a, indc, indr were not large enough.
    !             Their length "lena" should be increase to at least
    !             the value "minlen" given in luparm(13).
    !         = 8 if there was some other fatal error.  (Shouldn't happen!)
    !         = 9 if no diagonal pivot could be found with TSP or TDP.
    !             The matrix must not be sufficiently definite
    !             or quasi-definite.
    !         =10 if there was some other fatal error.


    v = b ! right hand side

    ! solve `A w = v`.
    call lu6sol( options%mode, m, n, v, w, &
                 lena, luparm, parmlu,   &
                 a, indc, indr, p, q,    &
                 lenc, lenr, locc, locr, &
                 inform )

    !write(*,*) 'lu6sol inform = ', inform

    ! On exit, inform = 0 except as follows.
    ! If mode = 3,4,5,6 and if U (and hence A) is singular, then
    ! inform = 1 if there is a nonzero residual in solving the system
    ! involving U.  parmlu(20) returns the norm of the residual.

    x = w ! solution
    istat = int(inform)

    end subroutine solve
!*****************************************************************************************

!*****************************************************************************************
    end module lusol_ez_module
!*****************************************************************************************