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

  use mod_types

  implicit none
  private
    
  type :: struct_RT_sph_sym !# Radiative transfer for a spherically symmetric distribution \
!#                             of dust and stars.
     integer :: dim_tau = 0, dim_alb = 0, dim_asym = 0
     real(CDR), dimension(:), pointer :: tau => null()
     real(CDR), dimension(:), pointer :: alb => null()
     real(CDR), dimension(:), pointer :: asym => null()
     real(CDR), dimension(:,:,:), pointer :: ln_trans_tot => null()
  end type struct_RT_sph_sym
  
  type :: struct_RT_cyl_sym !# Radiative transfer for a cylindrically symmetric \
!#                             distribution of dust and stars.
     integer :: dim_tau = 0, dim_alb = 0, dim_asym = 0, dim_inclin = 0
     real(CDR), dimension(:), pointer :: tau => null()
     real(CDR), dimension(:), pointer :: alb => null()
     real(CDR), dimension(:), pointer :: asym => null()
     real(CDR), dimension(:), pointer :: inclin => null()
     real(CDR), dimension(:, :, :), pointer :: ln_trans_tot => null()
     real(CDR), dimension(:, :, :, :), pointer :: ln_trans_incl => null()
  end type struct_RT_cyl_sym
  
  public :: read_RT_data, struct_RT_sph_sym, struct_RT_cyl_sym

contains

!#======================================================================
  
  subroutine read_RT_data(King, &
       slab, disk, bulge)

    use mod_types
    use mod_directories, only : RT_dir
    use mod_file_access, only : open_file, close_file, path_file
    
    implicit none
    type(struct_RT_sph_sym), intent(out) :: King
    type(struct_RT_cyl_sym), intent(out) :: slab, disk, bulge
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
!# Read extinction parameters for the "slab" model.
    call read_RT_cyl_sym(path_file(RT_dir, "slab_transmit.txt"), slab)

!# Read extinction parameters for the "spiral" model.
    call read_RT_cyl_sym(path_file(RT_dir, "disk_transmit.txt"), disk)
    call read_RT_cyl_sym(path_file(RT_dir, "bulge_transmit.txt"), bulge)
    
!# Read extinction parameters for the King model.
    call read_RT_sph_sym(path_file(RT_dir, "King_transmit.txt"), King)

  end subroutine read_RT_data

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

  subroutine read_RT_cyl_sym(file, data)

    use mod_file_access, only : open_file, close_file
    
    implicit none
    character(len=*), intent(in) :: file
    type(struct_RT_cyl_sym), intent(out) :: data
!#......................................................................    
    integer :: unit, i1, i2, i3, i4
    real(CDR), dimension(:, :, :), allocatable :: trans_tot
    real(CDR), dimension(:, :, :, :), allocatable :: trans_incl
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call open_file(unit, file)
    read(unit,*) data % dim_tau, data % dim_alb, data % dim_asym, data % dim_inclin
    if (associated(data % tau)) deallocate(data % tau) 
    allocate(data % tau(data % dim_tau))
    if (associated(data % alb)) deallocate(data % alb) 
    allocate(data % alb(data % dim_alb))
    if (associated(data % asym)) deallocate(data % asym) 
    allocate(data % asym(data % dim_asym))
    if (associated(data % ln_trans_tot)) deallocate(data % ln_trans_tot) 
    allocate(data % ln_trans_tot(data % dim_tau, data % dim_alb, data % dim_asym))
    if (associated(data % inclin)) deallocate(data % inclin) 
    allocate(data % inclin(data % dim_inclin))
    if (associated(data % ln_trans_incl)) deallocate(data % ln_trans_incl) 
    allocate(data % ln_trans_incl(data % dim_tau, data % dim_alb, data % dim_asym, &
         data % dim_inclin))

    allocate(trans_tot(data % dim_tau, data % dim_alb, data % dim_asym))
    allocate(trans_incl(data % dim_tau, data % dim_alb, data % dim_asym, &
         data % dim_inclin))
    
    do i1 = 1, data % dim_tau
       do i2 = 1, data % dim_alb
          read(unit, *) data % tau(i1), data % alb(i2), (data % asym(i3), i3 = 1, &
               data % dim_asym)
          read(unit, *) (trans_tot(i1, i2, i3), i3 = 1, data % dim_asym)
          do i4 = 1, data % dim_inclin
             read(unit, *) data % inclin(i4), &
                  (trans_incl(i1, i2, i3, i4), i3 = 1, data % dim_asym)
          enddo
       end do
    end do
    where(trans_tot > tiny(1.))
       data % ln_trans_tot = log(trans_tot)
    elsewhere
       data % ln_trans_tot = -huge(1.) 
    end where
    where(trans_incl > tiny(1.))
       data % ln_trans_incl = log(trans_incl)
    elsewhere
       data % ln_trans_incl = -huge(1.)
    end where

    deallocate(trans_tot, trans_incl)
    call close_file(unit)

  end subroutine read_RT_cyl_sym

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

  subroutine read_RT_sph_sym(file, data)

    use mod_file_access, only : open_file, close_file
    
    implicit none
    character(len=*), intent(in) :: file
    type(struct_RT_sph_sym), intent(out) :: data
!#......................................................................
    integer :: unit, i1, i2, i3
    real(CDR), dimension(:, :, :), allocatable :: trans_tot
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    call open_file(unit, file)
    read(unit,*) data % dim_tau, data % dim_alb, data % dim_asym
    if (associated(data % tau)) deallocate(data % tau) 
    allocate(data % tau(data % dim_tau))
    if (associated(data % alb)) deallocate(data % alb) 
    allocate(data % alb(data % dim_alb))
    if (associated(data % asym)) deallocate(data % asym) 
    allocate(data % asym(data % dim_asym))
    if (associated(data % ln_trans_tot)) deallocate(data % ln_trans_tot) 
    allocate(data % ln_trans_tot(data % dim_tau, data % dim_alb, data % dim_asym))

    allocate(trans_tot(data % dim_tau, data % dim_alb, data % dim_asym))

    do i1 = 1, data % dim_tau
       do i2 = 1, data % dim_alb
          do i3 = 1, data % dim_asym
             read(unit, *) data % tau(i1), data % alb(i2), data % asym(i3), &
                  trans_tot(i1, i2, i3)
          end do
       end do
    end do
    where(trans_tot > tiny(1.))
       data % ln_trans_tot = log(trans_tot)
    elsewhere
       data % ln_trans_tot = -huge(1.)
    end where
    
    deallocate(trans_tot)
    call close_file(unit)

  end subroutine read_RT_sph_sym

end module mod_RT
