!# This source file is part of code Pégase.3.0.1 (2019-02-21).
!# Copyright: Michel Fioc (Michel.Fioc@iap.fr), Sorbonne université, 
!# Institut d'astrophysique de Paris/CNRS, France.
!# 
!# Pégase.3.0.1 is governed by the CeCILL license under French law and abides 
!# by the rules of distribution of free software. You can use, modify and/or 
!# redistribute this software under the terms of the CeCILL license as circulated 
!# by CEA, CNRS and INRIA at "http://www.cecill.info". The text of this license
!# is also available in French and in English in directory "doc_dir/" of this
!# code.
!# 
!# As a counterpart to the access to the source code and to the rights to copy,
!# modify and redistribute it granted by the license, users are provided only
!# with a limited warranty, and the software's author, the holder of the
!# economic rights, and the successive licensors have only limited
!# liability. 
!# 
!# The fact that you are presently reading this means that you have had
!# knowledge of the CeCILL license and that you accept its terms.
!#====================================================================== 

module mod_read_outflow_param

  use mod_types
  use mod_analyze_statement, only : get_val, file_name, line_number, &
       error_message, warning_message
  use mod_convert_type, only : to_string
  use mod_spectra_constants, only : max_dim_outflow_epis

  implicit none
  public
  real(CDR), dimension(max_dim_outflow_epis), save :: &
       outflow_begin_time, outflow_end_time
  character(len=std_string), dimension(max_dim_outflow_epis), save :: &
       outflow_type
  real(CDR), dimension(max_dim_outflow_epis), save :: &
       outflow_inst_mass, &
       outflow_const_mass, &
       outflow_SF_factor, outflow_SF_power, &
       outflow_SN_mass, outflow_SN_power, &
       outflow_CCSN_mass, outflow_CCSN_power, &
       outflow_SNIa_mass, outflow_SNIa_power, &
       outflow_ejec_threshold, outflow_ejec_factor
  character(len=std_string), dimension(max_dim_outflow_epis), save :: &
       outflow_file
  integer, dimension(max_dim_outflow_epis), save :: outflow_file_dim_time
  type(irreg_array_CDR), dimension(max_dim_outflow_epis), save :: &
       outflow_file_time, outflow_file_rate

  logical, dimension(max_dim_outflow_epis), private :: &
       outflow_inst_mass_set, outflow_const_mass_set, &
       outflow_SF_factor_set, outflow_SN_mass_set, &
       outflow_CCSN_mass_set, outflow_SNIa_mass_set, &
       outflow_ejec_threshold_set, outflow_file_set

contains

!#======================================================================
  
  subroutine reset_outflow

    use mod_spectra_def_param
    implicit none
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    outflow_begin_time(:) = outflow_begin_time_def
    outflow_end_time(:) = outflow_end_time_def

    outflow_type(:) = outflow_type_def

    outflow_inst_mass_set(:) = .false.

    outflow_const_mass_set(:) = .false.

    outflow_SF_factor_set(:) = .false.
    outflow_SF_power(:) = outflow_SF_power_def

    outflow_SN_mass_set(:) = .false.
    outflow_SN_power(:) = outflow_SN_power_def

    outflow_CCSN_mass_set(:) = .false.
    outflow_CCSN_power(:) = outflow_CCSN_power_def

    outflow_SNIa_mass_set(:) = .false.
    outflow_SNIa_power(:) = outflow_SNIa_power_def

    outflow_ejec_threshold_set(:) = .false.
    outflow_ejec_factor(:) = outflow_ejec_factor_def

    outflow_file_set(:) = .false.
   
  end subroutine reset_outflow

!#======================================================================

  subroutine outflow_check

    implicit none
!#......................................................................
    integer :: i_epis
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    do i_epis = 1, max_dim_outflow_epis
       if (outflow_type(i_epis) == "none") cycle

       if (outflow_type(i_epis) == "instantaneous") then
          if (.not. outflow_inst_mass_set(i_epis)) then
             call error_message("Value of `outflow_inst_mass(" // &
                  to_string(i_epis) // ")` is unknown.")
          endif
       endif

       if (outflow_type(i_epis) == "constant") then
          if (.not. outflow_const_mass_set(i_epis)) then
             call error_message("Value of `outflow_const_mass(" // &
                  to_string(i_epis) // ")` is unknown.")
          endif
       endif

       if (outflow_type(i_epis) == "SF") then
          if (.not. outflow_SF_factor_set(i_epis)) then
             call error_message("Value of `outflow_SF_factor(" // &
                  to_string(i_epis) // ")` is unknown.")
           endif
       endif

       if (outflow_type(i_epis) == "SN") then
          if (.not. outflow_SN_mass_set(i_epis)) then
             call error_message("Value of `outflow_SN_mass(" // &
                  to_string(i_epis) // ")` is unknown.")
          endif
       endif

       if (outflow_type(i_epis) == "CCSN") then
          if (.not. outflow_CCSN_mass_set(i_epis)) then
              call error_message("Value of `outflow_CCSN_mass(" // &
                  to_string(i_epis) // ")` is unknown.")
          endif
       endif

       if (outflow_type(i_epis) == "SNIa") then
          if (.not. outflow_SNIa_mass_set(i_epis)) then
             call error_message("Value of `outflow_SNIa_mass(" // &
                  to_string(i_epis) // ")` is unknown.")
          endif
       endif

       if (outflow_type(i_epis) == "ejecta") then
          if (.not. outflow_ejec_threshold_set(i_epis)) then
             call error_message("Value of `outflow_ejec_threshold(" // &
                  to_string(i_epis) // ")` is unknown.")
          endif
       endif

       if (outflow_type(i_epis) == "file") then
          if (.not. outflow_file_set(i_epis)) then
             call error_message("Value of `outflow_file(" // &
                  to_string(i_epis) // ")` is unknown.")
          endif
       endif
       
       if (outflow_end_time(i_epis) <= &
            outflow_begin_time(i_epis)) &
            call warning_message("`outflow_end_time(" // &
            to_string(i_epis) // ")` = " // &
            to_string(outflow_end_time(i_epis), "(f6.0)") // &
            " <= `outflow_begin_time(" // to_string(i_epis) // ")` = " // &
            to_string(outflow_begin_time(i_epis), "(f6.0)") // ".")
    enddo

  end subroutine outflow_check

!#======================================================================

  subroutine read_outflow_begin_time(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_begin_time, rhs, indices_string, index_present)
    where (outflow_begin_time(:) > 0)
!# To make sure that the interval is closed on the left.
       outflow_begin_time(:) = nearest(outflow_begin_time(:), -1.)
    end where

  end subroutine read_outflow_begin_time

!#======================================================================

  subroutine read_outflow_end_time(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_end_time, rhs, indices_string, index_present)
    where (outflow_end_time(:) > 0)
!# To make sure that the interval is open on the right.
       outflow_end_time(:) = nearest(outflow_end_time(:), -1.)
    end where

  end subroutine read_outflow_end_time
  
!#======================================================================

  subroutine read_outflow_type(rhs, indices_string)
    
    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
    integer :: i_epis
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_type, rhs, indices_string, index_present)
    do i_epis = 1, max_dim_outflow_epis
       if (index_present(i_epis)) then
          if (all(outflow_type(i_epis) /= (/ &
               "none         ", &
               "radical      ", &
               "instantaneous", &
               "constant     ", &
               "SF           ", &
               "SN           ", &
               "CCSN         ", &
               "SNIa         ", &
               "ejecta       ", &
               "file         "/))) &
               call error_message("The value of `outflow_type(" // &
               to_string(i_epis) // ")` should be ""none"", ""radical"", &
               &""instantaneous"", ""constant"", ""SF"", ""SN"", ""CCSN"", &
               &""SNIa"", ""ejecta"" or ""file"".")
       endif
    enddo

  end subroutine read_outflow_type

!#======================================================================

  subroutine read_outflow_inst_mass(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_inst_mass, rhs, indices_string, index_present)
    where (index_present(:)) outflow_inst_mass_set(:) = .true.
    call set_outflow_type(index_present, "instantaneous")

  end subroutine read_outflow_inst_mass

!#======================================================================

  subroutine read_outflow_const_mass(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_const_mass, rhs, indices_string, index_present)
    where (index_present(:)) outflow_const_mass_set(:) = .true.
    call set_outflow_type(index_present, "constant")

  end subroutine read_outflow_const_mass

!#======================================================================

  subroutine read_outflow_SF_factor(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_SF_factor, rhs, indices_string, index_present)
    where (index_present(:)) outflow_SF_factor_set(:) = .true.
    call set_outflow_type(index_present, "SF")

  end subroutine read_outflow_SF_factor

!#======================================================================

  subroutine read_outflow_SF_power(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_SF_power, rhs, indices_string, index_present)
    call set_outflow_type(index_present, "SF")

  end subroutine read_outflow_SF_power

!#======================================================================

  subroutine read_outflow_SN_mass(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_SN_mass, rhs, indices_string, index_present)
    where (index_present(:)) outflow_SN_mass_set(:) = .true.
    call set_outflow_type(index_present, "SN")

  end subroutine read_outflow_SN_mass

!#======================================================================

  subroutine read_outflow_SN_power(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_SN_power, rhs, indices_string, index_present)
    call set_outflow_type(index_present, "SN")

  end subroutine read_outflow_SN_power

!#======================================================================

  subroutine read_outflow_CCSN_mass(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_CCSN_mass, rhs, indices_string, index_present)
    where (index_present(:)) outflow_CCSN_mass_set(:) = .true.
    call set_outflow_type(index_present, "CCSN")

  end subroutine read_outflow_CCSN_mass

!#======================================================================

  subroutine read_outflow_CCSN_power(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_CCSN_power, rhs, indices_string, index_present)
    call set_outflow_type(index_present, "CCSN")

  end subroutine read_outflow_CCSN_power

!#======================================================================

  subroutine read_outflow_SNIa_mass(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_SNIa_mass, rhs, indices_string, index_present)
    where (index_present(:)) outflow_SNIa_mass_set(:) = .true.
    call set_outflow_type(index_present, "SNIa")

  end subroutine read_outflow_SNIa_mass

!#======================================================================

  subroutine read_outflow_SNIa_power(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_SNIa_power, rhs, indices_string, index_present)
    call set_outflow_type(index_present, "SNIa")

  end subroutine read_outflow_SNIa_power

!#======================================================================

  subroutine read_outflow_ejec_threshold(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_ejec_threshold, rhs, indices_string, index_present)
    where (index_present(:)) outflow_ejec_threshold_set(:) = .true.
    call set_outflow_type(index_present, "ejecta")

  end subroutine read_outflow_ejec_threshold

!#======================================================================

  subroutine read_outflow_ejec_factor(rhs, indices_string)

    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_ejec_factor, rhs, indices_string, index_present)
    call set_outflow_type(index_present, "ejecta")

  end subroutine read_outflow_ejec_factor

!#======================================================================

  subroutine read_outflow_file(rhs, indices_string)

    use mod_strings, only : same_case_equal
    use mod_directories, only : scenarios_dir
    use mod_read_columns
    use mod_file_access, only : path_file
 
    implicit none
    character(len=*), intent(in) :: rhs
    character(len=*), intent(inout) :: indices_string
!#......................................................................
    integer :: i_epis
    logical, dimension(max_dim_outflow_epis) :: index_present
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call get_val(outflow_file, rhs, indices_string, index_present)

    do i_epis = 1, max_dim_outflow_epis 
       if (index_present(i_epis)) then
          call read_columns(path_file(scenarios_dir, adjustl(outflow_file(i_epis))), &
               outflow_file_dim_time(i_epis), outflow_file_time(i_epis) % val, &
               outflow_file_rate(i_epis) % val)
       endif
    enddo
    
    where (index_present(:)) outflow_file_set(:) = .true.
    call set_outflow_type(index_present, "file")
    
  end subroutine read_outflow_file

!#======================================================================

  subroutine set_outflow_type(index_present, string)

    implicit none
    logical, dimension(:), intent(in) :: index_present
    character(len=*), intent(in) :: string
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    where (index_present(:)) outflow_type(:) = string

  end subroutine set_outflow_type

end module mod_read_outflow_param
