!# 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_write_scenario_param

  implicit none
  private
  integer :: ord_scenario

  interface write_parameter
     module procedure write_parameter_integer, write_parameter_SPR, &
          write_parameter_DPR, write_parameter_bool, &
          write_parameter_string
  end interface write_parameter

  public :: write_scenario_param, ord_scenario, write_parameter

contains

!#======================================================================
!# `write_scenario_param` writes the processed name of output files.

  subroutine write_scenario_param( &
       version_id, &
       version_date, &
       compiler, &
       run_begin_time, &
       dim_SSP, &
       header_SSPs, &
       unit, line_prefix, for_grains)

    use mod_types
    use mod_linked_list
    use mod_strings, only : quote_string, same_case_equal
    use mod_convert_type
    use mod_read_SF_param
    use mod_read_reserv_infall_param
    use mod_read_outflow_param
    use mod_read_dust_evol_param
    use mod_read_dust_transfer_param
    use mod_read_cloud_neb_param
    use mod_read_output_param
    use mod_read_other_param
    use mod_read_cosmo_param

    implicit none
    character(len=*), intent(in), optional :: version_id, version_date
    character(len=*), intent(in), optional :: compiler
    character(len=*), intent(in), optional :: run_begin_time
    integer, intent(in), optional :: unit, dim_SSP
    type(lk_lst_long_string), dimension(:), intent(in), optional :: header_SSPs
    character(len=*), intent(in), optional :: line_prefix
    logical, optional :: for_grains
!#......................................................................
    integer :: i_SSP, i_reserv, i_epis
    type(lk_lst_long_string), pointer :: header_node => null()
    type(lk_lst_long_string), pointer :: text_current_node => null()
    logical :: for_grains_eff
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    for_grains_eff = .false.
    if (present(for_grains)) then
       if (for_grains) for_grains_eff = for_grains
    endif

!# Code version identifier and date.
    if (unit >= 0 .and. line_prefix == "!#") then
       write(unit, "(a)") quote_string(version_id) // " !# `version_id`."
       write(unit, "(a)") quote_string(version_date) // " !# `version_date`."
    endif

!# General comments on the scenario:
    text_current_node => text % ptr
    if (associated(text_current_node)) then
       if (unit < 0) then
          write(*, "(a,a)") trim(line_prefix), repeat("=", 70)
       else
          write(unit, "(a,a)") trim(line_prefix), repeat("=", 70)
       endif

       do
          if (.not.associated(text_current_node)) exit
          if (unit < 0) then
             write(*, "(a,tr1,a)") trim(line_prefix), trim(text_current_node % val)
          else
             write(unit, "(a,tr1,a)") trim(line_prefix), trim(text_current_node % val)
          endif
          text_current_node => text_current_node % ptr
       enddo

       if (unit < 0) then
          write(*, "(a,a)") trim(line_prefix), repeat("=", 70)
       else
          write(unit, "(a,a)") trim(line_prefix), repeat("=", 70)
       endif
    endif

!# Local time at which "spectra" was launched:
    if (present(run_begin_time)) write(unit, "(a)") &
         "!# Code ""spectra"" executed at " // trim(run_begin_time) // "."

!# Compiler used:
    if (unit >= 0 .and. line_prefix == "!#") then
       if (present(compiler)) write(unit, "(a)") &
            "!# Compiler for ""spectra"": " // trim(compiler) // "."
    endif

!# File of scenarios and rank of the scenario within this file:
    if (unit >= 0 .and. line_prefix == "!#") then
       write(unit, "(a)") "!# File of scenarios: " // &
            quote_string(scenarios_file) // "."
       write(unit, "(a, i0, a)") "!# Scenario number ", ord_scenario, &
            " in this file."
    endif

    if (unit < 0 .or. line_prefix /= "!#") then !# For the screen and the log-file.
       call write_parameter(unit, line_prefix, "verbosity", verbosity)
       call write_parameter(unit, line_prefix, "check_only", check_only)
       call write_parameter(unit, line_prefix, "overwrite", overwrite)
    endif

    if (unit < 0 .or. line_prefix /= "!#" .or. for_grains_eff) & 
         call write_parameter(unit, line_prefix, "spectra_output", spectra_output) !# \
!# `spectra_output` will be printed uncommented in the main output file (see the end
!# of this procedure). The same for `RF_output` and `sublim_output`.
    
    if (spectra_output /= "none") then
       call write_parameter(unit, line_prefix, "spectra_file", spectra_file)
       if (unit < 0 .or. line_prefix /= "!#" .or. for_grains_eff) then
          if (spectra_output == "detailed") then
             call write_parameter(unit, line_prefix, "RF_output", & 
                  RF_output)
             call write_parameter(unit, line_prefix, "sublim_output", &
                  sublim_output)
          endif
       endif
    endif

!# Associated files:
    call write_parameter(unit, line_prefix, "grain_temp_output", grain_temp_output)
    if (grain_temp_output) &
         call write_parameter(unit, line_prefix, "grain_temp_file", grain_temp_file)

    call write_parameter(unit, line_prefix, "grain_SED_output", grain_SED_output)
    if (grain_SED_output) &
         call write_parameter(unit, line_prefix, "grain_SED_file", grain_SED_file)
    if (grain_temp_output .or. grain_SED_output) then
       call write_parameter(unit, line_prefix, "grain_output_min_age", grain_output_min_age)
       call write_parameter(unit, line_prefix, "grain_output_max_age", grain_output_max_age)
       call write_parameter(unit, line_prefix, "grain_output_SFC", grain_output_SFC)
       call write_parameter(unit, line_prefix, "grain_output_DISM", grain_output_DISM)
       call write_parameter(unit, line_prefix, "grain_output_min_size", grain_output_min_size)
       call write_parameter(unit, line_prefix, "grain_output_max_size", grain_output_max_size)
    endif

!# Seeds used for random numbers:
    call write_seed(unit, line_prefix, dim_seed, seed)

!# Properties of SSPs (repetitive!):
    call write_parameter(unit, line_prefix, "SSPs_set", SSPs_set)
    if (present(header_SSPs)) then
       write(unit, "(a,a)") trim(line_prefix), repeat("=", 70)
       do i_SSP = 1, dim_SSP
          write(unit, "(a,i0,a,i0,a)") trim(line_prefix) // " SSP ", i_SSP, "/", dim_SSP, ":"
          header_node => header_SSPs(i_SSP) % ptr
          do
             if (.not.associated(header_node)) exit
             write(unit, "(a)") trim(header_node % val)
             header_node => header_node % ptr
          enddo
       enddo
       write(unit, "(a,a)") trim(line_prefix), repeat("=", 70)
    endif

!# Output ages, fraction of close binaries and initial metallicity:
    call write_parameter(unit, line_prefix, "ages_file", &
         ages_file)

    call write_parameter(unit, line_prefix, "close_bin_frac", close_bin_frac)

    call write_parameter(unit, line_prefix, "ISM_init_Z", ISM_init_Z)

!# Reservoirs:
    do i_reserv = 1, max_dim_reserv
       if (reserv_init_mass(i_reserv) > 0) then
          call write_parameter(unit, line_prefix, "reserv_init_mass", &
               reserv_init_mass(i_reserv), i_reserv)

          call write_parameter(unit, line_prefix, "reserv_Z", &
               reserv_Z(i_reserv), i_reserv)
       endif
    enddo

!# Infall episodes:
    do i_epis = 1, max_dim_infall_epis
       if (same_case_equal(infall_type(i_epis), "none")) cycle

       call write_parameter(unit, line_prefix, "infall_source", &
            infall_source(i_epis), i_epis)

       call write_parameter(unit, line_prefix, "infall_begin_time", &
            infall_begin_time(i_epis), i_epis)
       call write_parameter(unit, line_prefix, "infall_end_time", &
            infall_end_time(i_epis), i_epis)

       call write_parameter(unit, line_prefix, "infall_type", &
            infall_type(i_epis) , i_epis)

       if (same_case_equal(infall_type(i_epis), "instantaneous")) then
          call write_parameter(unit, line_prefix, "infall_inst_mass", &
               infall_inst_mass(i_epis), i_epis)

       else if (same_case_equal(infall_type(i_epis), "constant")) then
          call write_parameter(unit, line_prefix, "infall_const_mass", &
               infall_const_mass(i_epis), i_epis)

       else if (same_case_equal(infall_type(i_epis), "exponential")) then
          call write_parameter(unit, line_prefix, "infall_expo_timescale", &
               infall_expo_timescale(i_epis), i_epis)
          call write_parameter(unit, line_prefix, "infall_expo_mass", &
               infall_expo_mass(i_epis), i_epis)

       else if (same_case_equal(infall_type(i_epis), "reserv_mass")) then
          call write_parameter(unit, line_prefix, "infall_reserv_timescale", &
               infall_reserv_timescale(i_epis), i_epis)
          call write_parameter(unit, line_prefix, "infall_reserv_power", &
               infall_reserv_power(i_epis), i_epis)

       else if (same_case_equal(infall_type(i_epis), "file")) then
          call write_parameter(unit, line_prefix, "infall_file", &
               infall_file(i_epis), i_epis)
       endif

    enddo

!# Star formation episodes:
    do i_epis = 1, max_dim_SF_epis
       if (same_case_equal(SF_type(i_epis), "none")) cycle

       call write_parameter(unit, line_prefix, "SF_begin_time", &
            SF_begin_time(i_epis), i_epis)
       call write_parameter(unit, line_prefix, "SF_end_time", &
            SF_end_time(i_epis), i_epis)

       call write_parameter(unit, line_prefix, "SF_type", SF_type(i_epis), i_epis)

       if (same_case_equal(SF_type(i_epis), "instantaneous")) then
          call write_parameter(unit, line_prefix, "SF_inst_mass", &
               SF_inst_mass(i_epis), i_epis)

       else if (same_case_equal(SF_type(i_epis), "constant")) then
          call write_parameter(unit, line_prefix, "SF_const_mass", &
               SF_const_mass(i_epis), i_epis)

       else if (same_case_equal(SF_type(i_epis), "exponential")) then
          call write_parameter(unit, line_prefix, "SF_expo_timescale", &
               SF_expo_timescale(i_epis), i_epis)
          call write_parameter(unit, line_prefix, "SF_expo_mass", &
               SF_expo_mass(i_epis), i_epis)

       else if (same_case_equal(SF_type(i_epis), "peaked")) then
          call write_parameter(unit, line_prefix, "SF_peaked_timescale", &
               SF_peaked_timescale(i_epis), i_epis)
          call write_parameter(unit, line_prefix, "SF_peaked_mass", &
               SF_peaked_mass(i_epis), i_epis)

       else if (same_case_equal(SF_type(i_epis), "ISM_mass")) then
          call write_parameter(unit, line_prefix, "SF_ISM_timescale", &
               SF_ISM_timescale(i_epis), i_epis)
          call write_parameter(unit, line_prefix, "SF_ISM_power", &
               SF_ISM_power(i_epis), i_epis)
          call write_parameter(unit, line_prefix, "SF_ISM_threshold", &
               SF_ISM_threshold(i_epis), i_epis)

       else if (same_case_equal(SF_type(i_epis), "infall")) then
          call write_parameter(unit, line_prefix, "SF_infall_factor", &
               SF_infall_factor(i_epis), i_epis)

       else if (same_case_equal(SF_type(i_epis), "file")) then
          call write_parameter(unit, line_prefix, "SF_file", SF_file(i_epis), i_epis)
       endif

       call write_parameter(unit, line_prefix, "SF_stochastic", &
            SF_stochastic(i_epis), i_epis)
       if (SF_stochastic(i_epis)) then
          call write_parameter(unit, line_prefix, "SF_stoch_fluc", &
               SF_stoch_fluc(i_epis), i_epis)
          call write_parameter(unit, line_prefix, "SF_stoch_timescale", &
               SF_stoch_timescale(i_epis), i_epis)
       endif

       call write_parameter(unit, line_prefix, "SF_Z_type", SF_Z_type(i_epis), i_epis)
       if (same_case_equal(SF_Z_type(i_epis), "constant")) then
          call write_parameter(unit, line_prefix, "SF_Z_const_val", &
               SF_Z_const_val(i_epis), i_epis)
       else if (same_case_equal(SF_Z_type(i_epis), "file")) then
          call write_parameter(unit, line_prefix, "SF_Z_file", &
               SF_Z_file(i_epis), i_epis)
       end if

       call write_parameter(unit, line_prefix, "SF_inert_frac", &
            SF_inert_frac(i_epis), i_epis)
    enddo

!# Outflow episodes:
    do i_epis = 1, max_dim_outflow_epis
       if (same_case_equal(outflow_type(i_epis), "none")) cycle

       call write_parameter(unit, line_prefix, "outflow_begin_time", &
            outflow_begin_time(i_epis), i_epis)
       call write_parameter(unit, line_prefix, "outflow_end_time", &
            outflow_end_time(i_epis), i_epis)

       call write_parameter(unit, line_prefix, "outflow_type", &
            outflow_type(i_epis), i_epis)

       if (same_case_equal(outflow_type(i_epis), "radical")) then

       else if (same_case_equal(outflow_type(i_epis), "instantaneous")) then
          call write_parameter(unit, line_prefix, "outflow_inst_mass", &
               outflow_inst_mass(i_epis), i_epis)

       else if (same_case_equal(outflow_type(i_epis), "constant")) then
          call write_parameter(unit, line_prefix, "outflow_const_mass", &
               outflow_const_mass(i_epis), i_epis)

       else if (same_case_equal(outflow_type(i_epis), "SF")) then
          call write_parameter(unit, line_prefix, "outflow_SF_factor", &
               outflow_SF_factor(i_epis), i_epis)
          call write_parameter(unit, line_prefix, "outflow_SF_power", &
               outflow_SF_power(i_epis), i_epis)

       else if (same_case_equal(outflow_type(i_epis), "SN")) then
          call write_parameter(unit, line_prefix, "outflow_SN_mass", &
               outflow_SN_mass(i_epis), i_epis)
          call write_parameter(unit, line_prefix, "outflow_SN_power", &
               outflow_SN_power(i_epis), i_epis)

       else if (same_case_equal(outflow_type(i_epis), "CCSN")) then
          call write_parameter(unit, line_prefix, "outflow_CCSN_mass", &
               outflow_CCSN_mass(i_epis), i_epis)
          call write_parameter(unit, line_prefix, "outflow_CCSN_power", &
               outflow_CCSN_power(i_epis), i_epis)

       else if (same_case_equal(outflow_type(i_epis), "SNIa")) then
          call write_parameter(unit, line_prefix, "outflow_SNIa_mass", &
               outflow_SNIa_mass(i_epis), i_epis)
          call write_parameter(unit, line_prefix, "outflow_SNIa_power", &
               outflow_SNIa_power(i_epis), i_epis)

       else if (same_case_equal(outflow_type(i_epis), "ejecta")) then
          call write_parameter(unit, line_prefix, "outflow_ejec_threshold", &
               outflow_ejec_threshold(i_epis), i_epis)
          call write_parameter(unit, line_prefix, "outflow_ejec_factor", &
               outflow_ejec_factor(i_epis), i_epis)

       else if (same_case_equal(outflow_type(i_epis), "file")) then
          call write_parameter(unit, line_prefix, "outflow_file", &
               outflow_file(i_epis), i_epis)
       endif
    enddo

!# Nebular emission:
    call write_parameter(unit, line_prefix, "nebular_emission_SFC", &
         nebular_emission_SFC)

    call write_parameter(unit, line_prefix, "nebular_emission_DISM", &
         nebular_emission_DISM)

    if (nebular_emission_SFC) then
       call write_parameter(unit, line_prefix, "neb_emis_type_SFC", &
            neb_emis_type_SFC)

       if (neb_emis_type_SFC == "constant") &
            call write_parameter(unit, line_prefix, "neb_emis_const_frac_SFC", &
            neb_emis_const_frac_SFC)
    endif

    if (nebular_emission_DISM) then
       call write_parameter(unit, line_prefix, "neb_emis_type_DISM", &
            neb_emis_type_DISM)

       if (neb_emis_type_DISM == "constant") &
            call write_parameter(unit, line_prefix, "neb_emis_const_frac_DISM", &
            neb_emis_const_frac_DISM)
    endif

!# Properties of star-forming regions:
    call write_parameter(unit, line_prefix, "cluster_stel_mass", &
         cluster_stel_mass)

    call write_parameter(unit, line_prefix, "cloud_init_frac", &
         cloud_init_frac)

    call write_parameter(unit, line_prefix, "cloud_power", &
         cloud_power)

    call write_parameter(unit, line_prefix, "cloud_duration", &
         cloud_duration)

!# Dust evolution:
    call write_parameter(unit, line_prefix, "dust_evolution", &
         dust_evolution)
    call write_parameter(unit, line_prefix, "O_sil_ratio", O_sil_ratio)

    if (dust_evolution == "basic") then
       call write_parameter(unit, line_prefix, "ISM_carb_deplet", &
            ISM_carb_deplet)
       call write_parameter(unit, line_prefix, "ISM_sil_deplet", &
            ISM_sil_deplet)
    else if (dust_evolution == "Dwek") then
       call write_parameter(unit, line_prefix, "CCSN_carb_deplet", &
            CCSN_carb_deplet)
       call write_parameter(unit, line_prefix, "HMW_carb_deplet", &
            HMW_carb_deplet)
       call write_parameter(unit, line_prefix, "LMW_carb_deplet", &
            LMW_carb_deplet)
       call write_parameter(unit, line_prefix, "SNIa_carb_deplet", &
            SNIa_carb_deplet)
       call write_parameter(unit, line_prefix, "CCSN_sil_deplet", &
            CCSN_sil_deplet)
       call write_parameter(unit, line_prefix, "HMW_sil_deplet", &
            HMW_sil_deplet)
       call write_parameter(unit, line_prefix, "LMW_sil_deplet", &
            LMW_sil_deplet)
       call write_parameter(unit, line_prefix, "SNIa_sil_deplet", &
            SNIa_sil_deplet)
       call write_parameter(unit, line_prefix, "SN_swept_mass", SN_swept_mass)
       call write_parameter(unit, line_prefix, "carb_accr_timescale", &
            carb_accr_timescale)
       call write_parameter(unit, line_prefix, "sil_accr_timescale", &
            sil_accr_timescale)
    endif

!# Extinction and dust emission in star-forming clouds:
    call write_parameter(unit, line_prefix, "extinction_SFC", extinction_SFC)
    if (extinction_SFC) then
       call write_parameter(unit, line_prefix, "grains_file_SFC", &
            grains_file_SFC)

       call write_parameter(unit, line_prefix, "dust_emission_SFC", dust_emission_SFC)
       if (dust_emission_SFC) then
          call write_parameter(unit, line_prefix, "stoch_heating_SFC", &
               stoch_heating_SFC)
          call write_parameter(unit, line_prefix, "self_abs_power_SFC", &
               self_abs_power_SFC)
          if (spectra_output == "detailed" .and. sublim_output) then
             call write_parameter(unit, line_prefix, "carb_sublim_temp_SFC", &
                  carb_sublim_temp_SFC)
             call write_parameter(unit, line_prefix, "sil_sublim_temp_SFC", &
                  sil_sublim_temp_SFC)
          endif
       endif
    endif

!# Extinction and dust emission in the diffuse ISM:
    call write_parameter(unit, line_prefix, "extinction_DISM", extinction_DISM)
    if (extinction_DISM) then
       call write_parameter(unit, line_prefix, "grains_file_DISM", &
            grains_file_DISM)

       call write_parameter(unit, line_prefix, "geometry", geometry)

       if (geometry == "spiral" .or. geometry == "slab") then
          if (geometry == "spiral") then
             call write_parameter(unit, line_prefix, "bulge_tot_ratio", &
                  bulge_tot_ratio)
             call write_parameter(unit, line_prefix, "M_sys_spiral", &
                  M_sys_spiral)
             call write_parameter(unit, line_prefix, "expo_radius", &
                  expo_radius)
          else
             call write_parameter(unit, line_prefix, "slab_factor", &
                  slab_factor)
          endif
          call write_parameter(unit, line_prefix, "inclin_averaged", &
               inclin_averaged)
          if (.not.inclin_averaged) then
             call write_parameter(unit, line_prefix, "inclination", &
                  inclination)
          endif
       else if (geometry == "spheroidal") then
          call write_parameter(unit, line_prefix, "M_sys_spher", &
               M_sys_spher)
          call write_parameter(unit, line_prefix, "core_radius", &
               core_radius)
       endif

       call write_parameter(unit, line_prefix, "dust_emission_DISM", dust_emission_DISM)
       if (dust_emission_DISM) then
          call write_parameter(unit, line_prefix, "stoch_heating_DISM", &
               stoch_heating_DISM)
          call write_parameter(unit, line_prefix, "self_abs_power_DISM", &
               self_abs_power_DISM)
          if (spectra_output == "detailed" .and. sublim_output) then
             call write_parameter(unit, line_prefix, "carb_sublim_temp_DISM", &
                  carb_sublim_temp_DISM)
             call write_parameter(unit, line_prefix, "sil_sublim_temp_DISM", &
                  sil_sublim_temp_DISM)
          endif
       endif
    endif

!# Cosmological parameters:
    call write_parameter(unit, line_prefix, "Omega_m", Omega_m)

    call write_parameter(unit, line_prefix, "H_0", H_0)

    call write_parameter(unit, line_prefix, "form_redshift", form_redshift)

    call write_parameter(unit, line_prefix, "CBR", CBR)

!# For the main output file only:
    if (unit >= 0 .and. line_prefix == "!#" .and. .not.for_grains_eff) then
       write(unit, "(a)") quote_string(spectra_output) // " !# `spectra_output`."
       if (spectra_output == "detailed") then
          write(unit, "(a)") to_string(RF_output) // " !# `RF_output`."
          write(unit, "(a)") to_string(sublim_output) // " !# `sublim_output`."
       endif
    endif

  end subroutine write_scenario_param

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

  subroutine write_parameter_integer(unit, line_prefix, parameter_name, parameter_value, idx)

    use mod_convert_type

    implicit none
    integer, intent(in) :: unit
    character(len=*), intent(in) :: parameter_name, line_prefix
    integer, intent(in) :: parameter_value
    integer, intent(in), optional :: idx
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    if (present(idx)) then
       if (unit < 0) then
          write(*, "(a,tr1,a,i0,a,i0,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // &
               "(", idx, ")` = ", parameter_value, "."
       else
          write(unit, "(a,tr1,a,i0,a,i0,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // &
               "(", idx, ")` = ", parameter_value, "."
       endif
    else
       if (unit < 0) then
          write(*, "(a,tr1,a,i0,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // "` = ", &
               parameter_value, "."
       else
          write(unit, "(a,tr1,a,i0,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // "` = ", &
               parameter_value, "."
       endif
    endif

  end subroutine write_parameter_integer

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

  subroutine write_parameter_SPR(unit, line_prefix, parameter_name, parameter_value, idx)

    use mod_types
    use mod_convert_type

    implicit none
    integer, intent(in) :: unit
    character(len=*), intent(in) :: parameter_name, line_prefix
    real(SPR), intent(in) :: parameter_value
    integer, intent(in), optional :: idx
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    if (present(idx)) then
       if (unit < 0) then
          write(*, "(a,tr1,a,i0,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // &
               "(", idx, ")` = " // to_string(parameter_value) // "."
       else
          write(unit, "(a,tr1,a,i0,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // &
               "(", idx, ")` = " // to_string(parameter_value) // "."
       endif
    else
       if (unit < 0) then
          write(*, "(a,tr1,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // "` = " // &
               to_string(parameter_value) // "."
       else
          write(unit, "(a,tr1,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // "` = " // &
               to_string(parameter_value) // "."
       endif
    endif

  end subroutine write_parameter_SPR

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

  subroutine write_parameter_DPR(unit, line_prefix, parameter_name, parameter_value, idx)

    use mod_types
    use mod_convert_type

    implicit none
    integer, intent(in) :: unit
    character(len=*), intent(in) :: parameter_name, line_prefix
    real(DPR), intent(in) :: parameter_value
    integer, intent(in), optional :: idx
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    if (present(idx)) then
       if (unit < 0) then
          write(*, "(a,tr1,a,i0,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // &
               "(", idx, ")` = " // to_string(parameter_value) // "."
       else
          write(unit, "(a,tr1,a,i0,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // &
               "(", idx, ")` = " // to_string(parameter_value) // "."
       endif
    else
       if (unit < 0) then
          write(*, "(a,tr1,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // "` = " // &
               to_string(parameter_value) // "."
       else
          write(unit, "(a,tr1,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // "` = " // &
               to_string(parameter_value) // "."
       endif
    endif

  end subroutine write_parameter_DPR

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

  subroutine write_parameter_bool(unit, line_prefix, parameter_name, parameter_value, idx)

    use mod_convert_type

    implicit none
    integer, intent(in) :: unit
    character(len=*), intent(in) :: parameter_name, line_prefix
    logical, intent(in) :: parameter_value
    integer, intent(in), optional :: idx
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    if (present(idx)) then
       if (unit < 0) then
          write(*, "(a,tr1,a,i0,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // &
               "(", idx, ")` = " // to_string(parameter_value) // "."
       else
          write(unit, "(a,tr1,a,i0,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // &
               "(", idx, ")` = " // to_string(parameter_value) // "."
       endif
    else
       if (unit < 0) then
          write(*, "(a,tr1,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // "` = " // &
               to_string(parameter_value) // "."
       else
          write(unit, "(a,tr1,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // "` = " // &
               to_string(parameter_value) // "."
       endif
    endif

  end subroutine write_parameter_bool

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

  subroutine write_parameter_string(unit, line_prefix, parameter_name, parameter_value, idx)

    use mod_convert_type
    use mod_strings, only : quote_string

    implicit none
    integer, intent(in) :: unit
    character(len=*), intent(in) :: parameter_name, line_prefix
    character(len=*), intent(in) :: parameter_value
    integer, intent(in), optional :: idx
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    if (present(idx)) then
       if (unit < 0) then
          write(*, "(a,tr1,a,i0,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // &
               "(", idx, ")` = " // quote_string(adjustl(parameter_value)) // "."
       else
          write(unit, "(a,tr1,a,i0,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // &
               "(", idx, ")` = " // quote_string(adjustl(parameter_value)) // "."
       endif
    else
       if (unit < 0) then
          write(*, "(a,tr1,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // "` = " // &
               quote_string(adjustl(parameter_value)) // "."
       else
          write(unit, "(a,tr1,a)") trim(line_prefix), &
               "`" // trim(adjustl(parameter_name)) // "` = " // &
               quote_string(adjustl(parameter_value)) // "."
       endif
    endif

  end subroutine write_parameter_string

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

  subroutine write_seed(unit, line_prefix, dim_seed, seed)

    use mod_parse_file, only : len_max_line
    implicit none
    integer, intent(in) :: unit, dim_seed
    character(len=*), intent(in) :: line_prefix
    integer, dimension(:), intent(in) :: seed
!#......................................................................
    integer, parameter :: len_max_seed = len_max_line
    character(len=len_max_seed) :: seed_string, seed_string_aux
    integer :: len_seed, len_seed_aux, i_seed, horiz_shift
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    write(seed_string, "(a,tr1,a,i0,a)") trim(line_prefix), "`seed(1:", dim_seed, ")` ="
    len_seed = len_trim(seed_string)
    horiz_shift = len_seed + 1 -len_trim(line_prefix)
    if (dim_seed == 1) then
       write(seed_string_aux, "(a,i0,a)") " [", seed(1), "]."
       len_seed_aux = len_trim(seed_string_aux)
       if (len_seed + len_seed_aux > len_max_seed-2) then
!# Line too long. Break it.
          if (unit < 0) then
             write(*, "(a)") trim(seed_string) // " &"
          else
             write(unit, "(a)") trim(seed_string) // " &"
          endif
          seed_string = trim(line_prefix) // repeat(" ", horiz_shift) // seed_string_aux
          len_seed = len_trim(seed_string)
       else
          seed_string = trim(seed_string) // seed_string_aux
          len_seed = len_seed + len_seed_aux
       endif
       if (unit < 0) then
          write(*, "(a)") trim(seed_string)
       else
          write(unit, "(a)") trim(seed_string)
       endif
    else
       do i_seed = 1, dim_seed
          if (i_seed == 1) then
             write(seed_string_aux, "(a,i0,a)") " [", seed(1), ","
          else if (i_seed == dim_seed) then
             write(seed_string_aux, "(tr1,i0,a)") seed(dim_seed), "]."
          else
             write(seed_string_aux, "(tr1,i0,a)") seed(i_seed), ","
          endif
          len_seed_aux = len_trim(seed_string_aux)
          if (len_seed + len_seed_aux > len_max_seed-2) then
!# Line too long. Break it.
             if (unit < 0) then
                write(*, "(a)") trim(seed_string) // " &"
             else
                write(unit, "(a)") trim(seed_string) // " &"
             endif
             seed_string = trim(line_prefix) // repeat(" ", horiz_shift) // seed_string_aux
             len_seed = len_trim(seed_string)
          else
             seed_string = trim(seed_string) // seed_string_aux
             len_seed = len_seed + len_seed_aux
          endif
          if (i_seed == dim_seed) then
             if (unit < 0) then
                write(*, "(a)") trim(seed_string)
             else
                write(unit, "(a)") trim(seed_string)
             endif
          endif
       enddo
    endif

  end subroutine write_seed

end module mod_write_scenario_param
