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

  implicit none
  private
  public :: spectra_alloc1, spectra_alloc2

contains

!#======================================================================
  
  subroutine spectra_alloc1(dim_cont, dim_lambda_stel, dim_line, &
       dim_species_SFC, dim_species_DISM, &
       lum_cont, lum_stel_SFC_att_gas, lum_stel_SFC_unatt, &
       lum_stel_SFC, lum_stel_DISM_att_gas, lum_stel_DISM_unatt, &
       lum_cont_unatt, &
       lum_neb_cont_SFC_unatt, lum_neb_cont_SFC, &
       lum_neb_cont_DISM_unatt, &
       kappa_abs_cont, cont_trans_DISM_tot, &
       cont_trans_DISM_incl, cont_trans_SFC, &
       lum_species_SFC, lum_species_DISM, &
       sublim_lum_species_SFC, sublim_lum_species_DISM, &
       kappa_abs_line, L_line, L_line_SFC_unatt, L_line_SFC, &
       L_line_DISM_unatt, L_line_unatt, line_trans_DISM_tot, &
       line_trans_DISM_incl, line_trans_SFC, &
       RF_cont_SFC, RF_line_SFC, RF_cont_DISM, RF_line_DISM, &
       lum_stel_SFC_att_gas0, lum_stel_SFC_unatt0, lum_stel_DISM_att_gas0, lum_stel_DISM_unatt0, &
       lum_stel_SFC0, &
       lum_neb_cont_SFC_unatt0, lum_neb_cont_SFC0, &
       lum_neb_cont_DISM_unatt0, &
       species_weight_SFC, species_weight_DISM)

    use mod_types

    implicit none
    integer, intent(in) :: dim_cont, dim_lambda_stel, dim_line
    integer, intent(in) :: dim_species_SFC, dim_species_DISM
    real(CDR), dimension(:), pointer :: lum_cont, lum_stel_SFC_att_gas, &
         lum_stel_SFC_unatt, lum_stel_SFC, &
         lum_stel_DISM_att_gas, lum_stel_DISM_unatt, &
         lum_cont_unatt, &
         lum_neb_cont_SFC_unatt, lum_neb_cont_SFC, &
         lum_neb_cont_DISM_unatt, &
         kappa_abs_cont, cont_trans_DISM_tot, &
         cont_trans_DISM_incl, cont_trans_SFC
    real(CDR), dimension(:,:), pointer :: lum_species_SFC, lum_species_DISM
    real(CDR), dimension(:,:), pointer :: sublim_lum_species_SFC, sublim_lum_species_DISM
    real(CDR), dimension(:), pointer :: kappa_abs_line, L_line, &
         L_line_SFC_unatt, L_line_SFC, L_line_DISM_unatt, L_line_unatt, &
         line_trans_DISM_tot, line_trans_DISM_incl, line_trans_SFC, &
         RF_cont_SFC, RF_line_SFC, RF_cont_DISM, RF_line_DISM
    real(CDR), dimension(:), pointer :: lum_stel_SFC_att_gas0, lum_stel_SFC_unatt0, &
         lum_stel_DISM_att_gas0, lum_stel_DISM_unatt0, lum_stel_SFC0, &
         lum_neb_cont_SFC_unatt0, lum_neb_cont_SFC0, &
         lum_neb_cont_DISM_unatt0, &
         species_weight_SFC, species_weight_DISM
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    if (associated(lum_cont)) deallocate(lum_cont)
    allocate(lum_cont(dim_cont))

    if (associated(lum_stel_SFC_att_gas)) deallocate(lum_stel_SFC_att_gas)
    allocate(lum_stel_SFC_att_gas(dim_cont))

    if (associated(lum_stel_SFC_unatt)) deallocate(lum_stel_SFC_unatt)
    allocate(lum_stel_SFC_unatt(dim_cont))

    if (associated(lum_stel_SFC)) deallocate(lum_stel_SFC)
    allocate(lum_stel_SFC(dim_cont))

    if (associated(lum_stel_DISM_att_gas)) deallocate(lum_stel_DISM_att_gas)
    allocate(lum_stel_DISM_att_gas(dim_cont))

    if (associated(lum_stel_DISM_unatt)) deallocate(lum_stel_DISM_unatt)
    allocate(lum_stel_DISM_unatt(dim_cont))

    if (associated(lum_cont_unatt)) deallocate(lum_cont_unatt)
    allocate(lum_cont_unatt(dim_cont))

    if (associated(lum_neb_cont_SFC_unatt)) deallocate(lum_neb_cont_SFC_unatt)
    allocate(lum_neb_cont_SFC_unatt(dim_cont))

    if (associated(lum_neb_cont_SFC)) deallocate(lum_neb_cont_SFC)
    allocate(lum_neb_cont_SFC(dim_cont))

    if (associated(lum_neb_cont_DISM_unatt)) deallocate(lum_neb_cont_DISM_unatt)
    allocate(lum_neb_cont_DISM_unatt(dim_cont))

    if (associated(kappa_abs_cont)) deallocate(kappa_abs_cont)
    allocate(kappa_abs_cont(dim_cont))

    if (associated(cont_trans_DISM_tot)) deallocate(cont_trans_DISM_tot)
    allocate(cont_trans_DISM_tot(dim_cont))

    if (associated(cont_trans_DISM_incl)) deallocate(cont_trans_DISM_incl)
    allocate(cont_trans_DISM_incl(dim_cont))

    if (associated(cont_trans_SFC)) deallocate(cont_trans_SFC)
    allocate(cont_trans_SFC(dim_cont))

    if (associated(lum_species_SFC)) deallocate(lum_species_SFC)
    allocate(lum_species_SFC(dim_species_SFC, dim_cont))
    
    if (associated(lum_species_DISM)) deallocate(lum_species_DISM)
    allocate(lum_species_DISM(dim_species_DISM, dim_cont))

    if (associated(sublim_lum_species_SFC)) deallocate(sublim_lum_species_SFC)
    allocate(sublim_lum_species_SFC(dim_species_SFC, dim_cont))
    
    if (associated(sublim_lum_species_DISM)) deallocate(sublim_lum_species_DISM)
    allocate(sublim_lum_species_DISM(dim_species_DISM, dim_cont))
    
    if (associated(kappa_abs_line)) deallocate(kappa_abs_line)
    allocate(kappa_abs_line(dim_line))
    
    if (associated(L_line)) deallocate(L_line)
    allocate(L_line(dim_line))
    
    if (associated(L_line_SFC_unatt)) deallocate(L_line_SFC_unatt)
    allocate(L_line_SFC_unatt(dim_line))

    if (associated(L_line_SFC)) deallocate(L_line_SFC)
    allocate(L_line_SFC(dim_line))

    if (associated(L_line_DISM_unatt)) deallocate(L_line_DISM_unatt)
    allocate(L_line_DISM_unatt(dim_line))

    if (associated(L_line_unatt)) deallocate(L_line_unatt)
    allocate(L_line_unatt(dim_line))
    
    if (associated(line_trans_DISM_tot)) deallocate(line_trans_DISM_tot)
    allocate(line_trans_DISM_tot(dim_line))
    
    if (associated(line_trans_DISM_incl)) deallocate(line_trans_DISM_incl)
    allocate(line_trans_DISM_incl(dim_line))
    
    if (associated(line_trans_SFC)) deallocate(line_trans_SFC)
    allocate(line_trans_SFC(dim_line))

    if (associated(RF_cont_SFC)) deallocate(RF_cont_SFC)
    allocate(RF_cont_SFC(dim_cont))

    if (associated(RF_line_SFC)) deallocate(RF_line_SFC)
    allocate(RF_line_SFC(dim_line))

    if (associated(RF_cont_DISM)) deallocate(RF_cont_DISM)
    allocate(RF_cont_DISM(dim_cont))

    if (associated(RF_line_DISM)) deallocate(RF_line_DISM)
    allocate(RF_line_DISM(dim_line))

    if (associated(lum_stel_SFC_att_gas0)) deallocate(lum_stel_SFC_att_gas0)
    allocate(lum_stel_SFC_att_gas0(dim_lambda_stel))

    if (associated(lum_stel_SFC_unatt0)) deallocate(lum_stel_SFC_unatt0)
    allocate(lum_stel_SFC_unatt0(dim_lambda_stel))

    if (associated(lum_stel_DISM_att_gas0)) deallocate(lum_stel_DISM_att_gas0)
    allocate(lum_stel_DISM_att_gas0(dim_lambda_stel))

    if (associated(lum_stel_DISM_unatt0)) deallocate(lum_stel_DISM_unatt0)
    allocate(lum_stel_DISM_unatt0(dim_lambda_stel))

    if (associated(lum_stel_SFC0)) deallocate(lum_stel_SFC0)
    allocate(lum_stel_SFC0(dim_lambda_stel))

    if (associated(lum_neb_cont_SFC_unatt0)) deallocate(lum_neb_cont_SFC_unatt0)
    allocate(lum_neb_cont_SFC_unatt0(dim_lambda_stel))

    if (associated(lum_neb_cont_SFC0)) deallocate(lum_neb_cont_SFC0)
    allocate(lum_neb_cont_SFC0(dim_lambda_stel))

    if (associated(lum_neb_cont_DISM_unatt0)) deallocate(lum_neb_cont_DISM_unatt0)
    allocate(lum_neb_cont_DISM_unatt0(dim_lambda_stel))

    if (associated(species_weight_SFC)) deallocate(species_weight_SFC)
    allocate(species_weight_SFC(dim_species_SFC))

    if (associated(species_weight_DISM)) deallocate(species_weight_DISM)
    allocate(species_weight_DISM(dim_species_DISM))
    
  end subroutine spectra_alloc1

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

  subroutine spectra_alloc2(dim_convol_time, dim_elem, &
       galaxy_mass, ISM_mass, BHNS_mass, &
       WD_mass, carb_abund, sil_abund, SF_rate, CCSN_rate, SNIa_rate, &
       ejec_rate_tot, infall_rate, outflow_rate, ejec_cumul_mass, &
       SF_live_cumul_mass, infall_cumul_mass, outflow_cumul_mass, &
       inert_mass, ISM_over_H, &
       LC_gas_abs_birth_cloud, LC_dust_abs_birth_cloud, &
       LC_gas_abs_DISM, dust_col_dens_birth_cloud, &
       cloud_frac, ISM_elem_mass, ISM_abund, reserv_abund, &
       n_Z_neb, n_Q_neb, Z_neb_weight, Q_neb_weight_SFC)

    use mod_types
    use mod_scenario, only : max_dim_reserv

    implicit none
    integer, intent(in) :: dim_convol_time, dim_elem
    real(CDR), dimension(:), pointer :: galaxy_mass, ISM_mass, BHNS_mass, &
         WD_mass, carb_abund, sil_abund
    real(DPR), dimension(:), pointer :: SF_rate
    real(DPR), dimension(:), pointer :: CCSN_rate, &
         SNIa_rate, &
         ejec_rate_tot, &
         infall_rate, &
         outflow_rate, &
         ejec_cumul_mass, &
         SF_live_cumul_mass, &
         infall_cumul_mass, &
         outflow_cumul_mass
    real(CDR), dimension(:), pointer :: inert_mass, &
         ISM_over_H, &
         LC_gas_abs_birth_cloud, LC_dust_abs_birth_cloud, &
         LC_gas_abs_DISM, &
         dust_col_dens_birth_cloud, &
         cloud_frac
    real(CDR), dimension(:), pointer :: ISM_elem_mass
    real(CDR), dimension(:,:), pointer :: ISM_abund
    real(CDR), dimension(:,:), pointer :: reserv_abund
    integer, intent(in) :: n_Z_neb, n_Q_neb
    real(CDR), dimension(:,:), pointer :: Z_neb_weight, Q_neb_weight_SFC
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    if (associated(galaxy_mass)) deallocate(galaxy_mass)
    allocate(galaxy_mass(dim_convol_time+1))

    if (associated(ISM_mass)) deallocate(ISM_mass)
    allocate(ISM_mass(dim_convol_time+1))

    if (associated(BHNS_mass)) deallocate(BHNS_mass)
    allocate(BHNS_mass(dim_convol_time+1))

    if (associated(WD_mass)) deallocate(WD_mass)
    allocate(WD_mass(dim_convol_time+1))

    if (associated(carb_abund)) deallocate(carb_abund)
    allocate(carb_abund(dim_convol_time+1-1))

    if (associated(sil_abund)) deallocate(sil_abund)
    allocate(sil_abund(dim_convol_time+1-1))

    if (associated(SF_rate)) deallocate(SF_rate)
!# ??? Why not `dim_convol_time+1`, as for others? Or why for others?
    allocate(SF_rate(dim_convol_time)) 
    
    if (associated(CCSN_rate)) deallocate(CCSN_rate)
    allocate(CCSN_rate(dim_convol_time+1))

    if (associated(SNIa_rate)) deallocate(SNIa_rate)
    allocate(SNIa_rate(dim_convol_time+1))

    if (associated(ejec_rate_tot)) deallocate(ejec_rate_tot)
    allocate(ejec_rate_tot(dim_convol_time+1))

    if (associated(infall_rate)) deallocate(infall_rate)
    allocate(infall_rate(dim_convol_time+1-1))

    if (associated(outflow_rate)) deallocate(outflow_rate)
    allocate(outflow_rate(dim_convol_time+1))

    if (associated(ejec_cumul_mass)) deallocate(ejec_cumul_mass)
    allocate(ejec_cumul_mass(dim_convol_time+1))

    if (associated(SF_live_cumul_mass)) deallocate(SF_live_cumul_mass)
    allocate(SF_live_cumul_mass(dim_convol_time+1))

    if (associated(infall_cumul_mass)) deallocate(infall_cumul_mass)
    allocate(infall_cumul_mass(dim_convol_time+1))

    if (associated(outflow_cumul_mass)) deallocate(outflow_cumul_mass)
    allocate(outflow_cumul_mass(dim_convol_time+1))

    if (associated(inert_mass)) deallocate(inert_mass)
    allocate(inert_mass(dim_convol_time+1))

    if (associated(ISM_over_H)) deallocate(ISM_over_H)
    allocate(ISM_over_H(dim_convol_time+1-1))

    if (associated(LC_gas_abs_birth_cloud)) deallocate(LC_gas_abs_birth_cloud)
    allocate(LC_gas_abs_birth_cloud(dim_convol_time+1-1))

    if (associated(LC_dust_abs_birth_cloud)) deallocate(LC_dust_abs_birth_cloud)
    allocate(LC_dust_abs_birth_cloud(dim_convol_time+1-1))

    if (associated(LC_gas_abs_DISM)) deallocate(LC_gas_abs_DISM)
    allocate(LC_gas_abs_DISM(dim_convol_time+1-1))

    if (associated(dust_col_dens_birth_cloud)) deallocate(dust_col_dens_birth_cloud)
    allocate(dust_col_dens_birth_cloud(dim_convol_time+1-1))

    if (associated(cloud_frac)) deallocate(cloud_frac)
    allocate(cloud_frac(dim_convol_time+1-1))

    if (associated(ISM_elem_mass)) deallocate(ISM_elem_mass)
    allocate(ISM_elem_mass(0:dim_elem))
    
    if (associated(ISM_abund)) deallocate(ISM_abund)
    allocate(ISM_abund(dim_convol_time, 0:dim_elem))
    
    if (associated(reserv_abund)) deallocate(reserv_abund)
    allocate(reserv_abund(max_dim_reserv, 0:dim_elem))

    if (associated(Z_neb_weight)) deallocate(Z_neb_weight)
    allocate(Z_neb_weight(dim_convol_time+1-1, n_Z_neb))
    

    if (associated(Q_neb_weight_SFC)) deallocate(Q_neb_weight_SFC)
    allocate(Q_neb_weight_SFC(dim_convol_time+1-1, n_Q_neb))

  end subroutine spectra_alloc2
  
end module mod_spectra_alloc
