!# 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.
!#====================================================================== 

!# Read the spectral energy distribution (SED) of grains from a file.
!# For grain temperature distributions, see "mod_read_grain_temp.f90".
!#----------------------------------------------------------------------
!# To read these data, create a Fortran 95 code and type in it
!#
!#     `call read_grain_SED(file_name, data)`,
!#
!# where the string of characters denoted by `file_name` is the name of the file
!# and `data` is a structure of type `struct_grain_SED` and must be declared with
!#
!#     `type(struct_grain_SED) :: data`.
!#
!# The line
!#
!#     `use mod_read_grain_SED`
!#
!# must be inserted before all declarations.
!#
!# See file "plot_grain_SED.f90" for an example.
!#
!# To compile the code you created, link it (with the appropriate paths) to
!# "mod_types.f90", "mod_dir_access.f90", "mod_file_access.f90", 
!# "mod_strings.f90", "mod_directories.f90" and "mod_read_grain_SED.f90".
!#----------------------------------------------------------------------
!# The fields of `data` are the following:
!# -- `data % version_id`: code's version;
!# -- `data % version_date`: code's date;
!# -- `data % dim_age_grains`: number of ages
!#    -> index `i_age` hereafter;
!# -- `data % dim_region`: number of regions (star-forming clouds, diffuse 
!#    ISM)
!#    -> index `i_region` hereafter;
!# -- `data % age_grains(i_age)`: age in Myr;
!# -- `data % region(i_region)`: structure for the region #`i_region`.
!#
!# The fields of `data % region(i_region)` are the following:
!# -- `data % region(i_region) % id`: identifier of the region ("SFC" for 
!#    star-forming clouds, "DISM" for the diffuse ISM...;
!# -- `data % region(i_region) % dim_species`: number of grain species (graphite, 
!#    silicate, etc.) for this region
!#    -> index `i_species` hereafter;
!# -- `data % region(i_region) % stoch_heating`: boolean set to `.true.`
!#    if SEDs are computed both for stochastically heated grains (so, with a 
!#    temperature distribution) and at the equilibrium temperature, and to 
!#    `.false.` if SEDs are computed only at the equilibrium temperature;
!# -- `data % region(i_region) % species(i_species)`: structure for the grain species
!#    #`i_species` in the region #`i_region`.
!#
!# The fields of `data % region(i_region) % species(i_species)` are the following:
!# -- `data % region(i_region) % species(i_species) % id`: identifier of the grain species;
!# -- `data % region(i_region) % species(i_species) % dim_lambda`: number of 
!#    wavelengths for the radiation field
!#    -> index `i_lambda` hereafter;
!# -- `data % region(i_region) % species(i_species) % lambda(i_lambda)`: wavelength;
!# -- `data % region(i_region) % species(i_species) % dim_radius`: number of grain 
!#    radii
!#    -> index `i_radius` hereafter;
!# -- `data % region(i_region) % species(i_species) % radius(i_radius)`: radius in 
!#    micrometers;
!# -- `data % region(i_region) % species(i_species) 
!#    % lum_stoch(i_age, i_radius, i_lambda)`: monochromatic luminosity for 
!#    stochastically heated grains (void if `data % region(i_region) 
!#    % stoch_heating` is false);
!# -- `data % region(i_region) % species(i_species) 
!#    % lum_eq(i_age, i_radius, i_lambda)`: monochromatic luminosity for 
!#    grains at equilibrium temperature.

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

module mod_read_grain_SED

  use mod_types

  implicit none

  type :: struct_grain_SED
     character(len=std_string) :: version_id, version_date
     integer :: dim_age_grains, dim_region
     real(CDR), dimension(:), pointer :: age_grains => null()
     type(struct_grain_SED1), dimension(:), pointer :: region => null()
  end type struct_grain_SED

  type :: struct_grain_SED1
     character(len=std_string) :: id
     integer :: dim_species
     logical :: stoch_heating
     type(struct_grain_SED2), dimension(:), pointer :: species => null()
  end type struct_grain_SED1

  type :: struct_grain_SED2
     character(len=std_string) :: id
     integer :: dim_lambda
     real(CDR), dimension(:), pointer :: lambda => null()
     integer :: dim_radius
     real(CDR), dimension(:), pointer :: radius => null()
     real(CDR), dimension(:,:,:), pointer :: lum_stoch => null()
     real(CDR), dimension(:,:,:), pointer :: lum_eq => null()
  end type struct_grain_SED2

contains

!#======================================================================
  
  subroutine read_grain_SED(file_name, data)

    use mod_directories, only : grain_SED_dir
    use mod_file_access

    implicit none
    character(len=*), intent(in) :: file_name
    type(struct_grain_SED), intent(out) :: data
!#......................................................................
    integer :: i_species, i_age, i_region, i_radius, eff_dim_species
    integer :: unit
    integer :: dim_age_grains, dim_species, dim_lambda, dim_radius, dim_region
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call open_file(unit, path_file(grain_SED_dir, file_name))
    read(unit,*) data % version_id
    read(unit, *) data % version_date
    call skip_comment_lines(unit)
    read(unit,*) dim_age_grains, dim_region
    data % dim_age_grains = dim_age_grains
    data % dim_region = dim_region
    allocate(data % age_grains(dim_age_grains))
    allocate(data % region(dim_region))
    do i_region = 1, dim_region
       read(unit,*) data % region(i_region) % id, dim_species, &
            data % region(i_region) % stoch_heating
       data % region(i_region) % dim_species = dim_species
       allocate(data % region(i_region) % species(dim_species))
       do i_species = 1, data % region(i_region) % dim_species
          read(unit,*) data % region(i_region) % species(i_species) % id, &
               dim_lambda
          data % region(i_region) % species(i_species) % dim_lambda = dim_lambda
          allocate(data % region(i_region) % species(i_species) &
               % lambda(dim_lambda))
          read(unit,*) data % region(i_region) % species(i_species) % lambda(:)
       enddo
    enddo

    do i_age = 1, data % dim_age_grains
       do i_region = 1, data % dim_region
          read(unit,*) data % age_grains(i_age)
          read(unit,*) eff_dim_species
          if (eff_dim_species > 0) then
             do i_species = 1, data % region(i_region) % dim_species
                read(unit,*) dim_radius
                data % region(i_region) % species(i_species) % dim_radius = &
                     dim_radius
                if (i_age == 1) then
                   allocate(data % region(i_region) % species(i_species) &
                        % radius(dim_radius))
                   dim_lambda = data % region(i_region) % species(i_species) &
                        % dim_lambda
                   if (data % region(i_region) % stoch_heating) then
                      allocate(data % region(i_region) % species(i_species) &
                           % lum_stoch(dim_age_grains, dim_radius, dim_lambda))
                   endif
                   allocate(data % region(i_region) % species(i_species) &
                        % lum_eq(dim_age_grains, dim_radius, dim_lambda))
                end if
                do i_radius = 1, dim_radius
                   read(unit,*) data % region(i_region) % species(i_species) &
                        % radius(i_radius)
                   if (data % region(i_region) % stoch_heating) then
                      read(unit,*) data % region(i_region) % species(i_species) &
                           % lum_stoch(i_age, i_radius, :)
                   endif
                   read(unit,*) data % region(i_region) % species(i_species) &
                        % lum_eq(i_age, i_radius, :)
                enddo
             enddo
          else

          endif
       enddo
    enddo
    call close_file(unit)

  end subroutine read_grain_SED

end module mod_read_grain_SED
