!---------------------------------------------------------------------
!     Copyright (C) GFD Dennou Club, 2004. All rights reserved.
!---------------------------------------------------------------------
                                                                 !=begin
!= Module Linlib
!
!   * Developer: SUGIYAMA Ko-ichiro (sugiyama@gfd-dennou.org)
!   * Version: $Id: linlib.f90.ffc,v 1.2 2005/04/22 15:01:52 sugiyama Exp $ 
!   * Tag Name: $Name:  $
!   * Change History: 
!
!== Overview 
!
!線形計算ライブラリ SSL II と LAPACK のラッパー
!
!== Error Handling
!
!== Known Bugs
!
!LAPACK を選択する部分をコーディングしていない. 
!
!== Note
!
!== Future Plans
!
                                                                 !=end

module linlib
  implicit none
  
  private
                                                                 !=begin
  !== Public Interface
  public linlib_init       !初期化ルーチン
  public linsolv           !実 3 項行列の連立 1 次方程式(倍精度)

  integer       :: LN = 10 !配列のサイズ. 値はダミー
  character(1)  :: LLib    !用いるライブラリのフラグ

  save LLib, LN
                                                                 !=end    
contains
                                                                 !=begin
  !== Procedure Interface 
  !
  !=== Initialize module and acquire NAMELIST
  !
  !利用する線形計算パッケージを NAMELIST から設定し, 
  !配列の大きさを決定する
  !
  subroutine linlib_init(cfgfile, N)

    !=== Dependency
    use dc_trace, only : BeginSub, EndSub
    use dc_message, only: MessageNotify
    use ssl2_linear, only: ssl2_ltx_init
    use lapack_linear, only: lapack_dgtsv_init

    !=== Input
    integer, intent(in)      :: N       !配列サイズ
    character(*), intent(in) :: cfgfile !設定ファイル (NAMELIST)
    
    !=== NAMELIST
    NAMELIST /linlib/ LLib
                                                                 !=end
    open (10, FILE=cfgfile)
    read(10, NML=linlib)
    close(10)

    call BeginSub("linlib_init", &
&                 fmt="%c",       &
&                 c1="Initialize linear algebra library.")

    !--- 配列サイズを保管
    LN = N

    !--- 用いるライブラリの初期化
    if (LLib == 's') then 
       call MessageNotify("Message", "linlib.f90", &
&                         "Call SSL II in the calculation")

       call ssl2_ltx_init(LN)

    elseif (LLib == 'l') then 
       call MessageNotify("Message", "linlib.f90", &
&                         "Call LAPACK in the calculation")

       call lapack_dgtsv_init(LN)

    else
      call MessageNotify("Error", "linlib.f90", &
&                        "Unknown LLib ", c1=LLib)
    end if

    call EndSub("linlib_init")

  end subroutine linlib_init
  
                                                                 !=begin
  !== Procedure Interface 
  !
  !=== Initialize module
  !
  !利用する線形計算パッケージに配列を渡す
  !
  subroutine LinSolv(A, B, C, D)

    !=== Dependency
    use dc_trace, only : BeginSub, EndSub
    use dc_message, only: MessageNotify
    use ssl2_linear, only: ssl2_ltx
    use lapack_linear, only: lapack_dgtsv

    !=== Input
    real(8), intent(in)    :: A(LN)
    real(8), intent(in)    :: B(LN-1)
    real(8), intent(in)    :: C(LN-1) 

    !=== In/Out
    real(8), intent(inout) :: D(LN)
                                                                 !=end

    !=== Work
    real(8)                :: AA(LN)
    real(8)                :: BB(LN-1)
    real(8)                :: CC(LN-1) 


    call BeginSub("linsolv", &
&                 fmt="%c",       &
&                 c1="call linear algebra library.")

    !--- 用いるライブラリの初期化
    if (LLib == 's') then 
       call ssl2_ltx(A, B, C, D)

    elseif (LLib == 'l') then 
       !=== 属性が inout なので, 内部変数を使うことに.
       AA = A; BB = B; CC = C
       call lapack_dgtsv(AA, BB, CC, D)
       
    else
      call MessageNotify("Error", "linlib", &
&                        "unknown LLib")
    end if

    call EndSub("linsolv")

  end subroutine LinSolv
  
end module linlib
