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

  use mod_types

  implicit none
  private
  type :: struct_track
     real(DPR) :: init_mass
     real(DPR) :: l10_init_mass
     real(DPR) :: mass_HB
     real(DPR) :: final_mass
     real(DPR) :: lifetime
     integer :: dim_age
     integer :: WD_extension
     real(DPR) :: last_age
     real(DPR), dimension(:), pointer :: age => null()
     real(DPR), dimension(:), pointer :: lum => null()
     real(DPR), dimension(:), pointer :: T_eff => null()
     real(DPR), dimension(:), pointer :: grav => null()
  end type struct_track

  type :: lk_lst_track
     type(lk_lst_track), pointer :: ptr => null()
     real(DPR) :: init_mass
     real(DPR) :: l10_mass
     integer :: WD_extension
     integer :: dim_age
     real(DPR), dimension(:), pointer :: age => null()
     real(DPR), dimension(:), pointer :: lum => null()
     real(DPR), dimension(:), pointer :: T_eff => null()
     real(DPR), dimension(:), pointer :: grav => null()
  end type lk_lst_track

  public :: read_tracks, connect_tracks, white_dwarfs_tracks, struct_track

contains

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

  subroutine read_tracks(tracks_file, X_sol, Z_sol, &
       n_MS, n_He_flash, n_HB, n_VLM, dim_age_WD, Y_track, Z_track, &
       M_over_H_track, min_mass_CCSN, &
       std_track)

    use mod_types
    use mod_directories, only : tracks_dir
    use mod_interp, only : interp_lin_lin, interp_lin_log
    use mod_file_access, only : open_file, close_file, path_file

    implicit none
    character(len=*), intent(in) :: tracks_file
    real(DPR), intent(in) :: X_sol, Z_sol
    integer, intent(out) :: n_MS, n_He_flash, n_HB, n_VLM, dim_age_WD
    real(DPR), intent(out) :: Y_track, Z_track, M_over_H_track, min_mass_CCSN
    type(struct_track), dimension(:), pointer :: std_track
!#......................................................................
    real(DPR) :: mass_core, gross_Z_ejec_wind, delta_t, X_track
    integer :: i_track, i_MS, i_age, unit, dim_age_tot
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    call open_file(unit, path_file(tracks_dir, tracks_file))
    read(unit, *) n_MS, n_He_flash, n_HB, n_VLM, Z_track, Y_track, &
         min_mass_CCSN, dim_age_WD
    X_track = 1 - Y_track - Z_track
    M_over_H_track = log10((Z_track/X_track) / (Z_sol/X_sol))

!#     `n_MS`: total number of ZAMS tracks (i.e. starting on the zero-age main sequence).
!#     `n_HB`: number of ZAHB tracks (i.e. starting on the zero-age horizontal branch);
!#           only for stars undergoing the helium flash.
!#     `n_VLM`: number of ZAMS tracks for very low mass stars (~<= 0.5 Msol)
!#           which do not evolve. (Included in `n_MS`.)
!#     `n_He_flash`: number of ZAMS tracks (ZAMS->tip of the RGB)
!#           for low-mass stars which undergo the helium flash
!#           and *must* be connected to ZAHB tracks. (Included in `n_MS`, but excludes
!#           very low mass stars.)
!#
!# `mass_core` is the final mass of the core.
!# `gross_Z_ejec_wind` is the gross ejecta from metals due to winds and directly computed
!# from the tracks.
!# None of these quantities is used. (The yields of metals are read from files of yields.)

    if (associated(std_track)) then
       do i_track = 1, size(std_track)
          if (associated(std_track(i_track) % age)) &
               deallocate(std_track(i_track) % age)
          if (associated(std_track(i_track) % lum)) &
               deallocate(std_track(i_track) % lum)
          if (associated(std_track(i_track) % T_eff)) &
               deallocate(std_track(i_track) % T_eff)
          if (associated(std_track(i_track) % grav)) &
               deallocate(std_track(i_track) % grav)
       enddo
       deallocate(std_track)
    endif

!# The size of `std_track` will be larger than `n_MS + n_HB` (the original
!# value of `n_HB`) because `n_HB_supp` tracks are added in subroutine
!# `connect_tracks`.
    allocate(std_track(n_MS + n_HB))

!# For all ZAMS tracks:
    do i_track = 1, n_MS
       read(unit, *) std_track(i_track) % init_mass, &
            std_track(i_track) % dim_age, &
            mass_core, &
            std_track(i_track) % final_mass, &
            std_track(i_track) % WD_extension, &
            gross_Z_ejec_wind
       dim_age_tot = std_track(i_track) % dim_age + &
            std_track(i_track) % WD_extension*dim_age_WD
       allocate(std_track(i_track) % age(dim_age_tot))
       allocate(std_track(i_track) % lum(dim_age_tot))
       allocate(std_track(i_track) % T_eff(dim_age_tot))
       allocate(std_track(i_track) % grav(dim_age_tot))
       do i_age = 1, dim_age_tot
          read(unit, *) std_track(i_track) % lum(i_age), &
               std_track(i_track) % T_eff(i_age), &
               std_track(i_track) % grav(i_age), std_track(i_track) % age(i_age)
       end do
       std_track(i_track) % last_age = &
            std_track(i_track) % age(std_track(i_track) % dim_age)
       std_track(i_track) % l10_init_mass = &
            log10(std_track(i_track) % init_mass)
    end do

!# For ZAHB tracks except the one with the largest mass on the ZAHB:
    do i_track = n_MS+1, n_MS+n_HB-1
       read(unit, *) std_track(i_track) % mass_HB, &
            std_track(i_track) % dim_age, &
            mass_core, &
            std_track(i_track) % final_mass, &
            std_track(i_track) % WD_extension, &
            gross_Z_ejec_wind
       i_MS = n_VLM
       do while(.not.(std_track(i_MS) % final_mass <= std_track(i_track) % mass_HB .and. &
            std_track(i_track) % mass_HB <= std_track(i_MS+1) % final_mass))
          i_MS = i_MS+1
       end do
       std_track(i_track) % init_mass = interp_lin_lin( &
            std_track(i_MS) % final_mass, &
            std_track(i_MS+1) % final_mass, &
            std_track(i_MS) % init_mass, &
            std_track(i_MS+1) % init_mass, &
            std_track(i_track) % mass_HB)
       std_track(i_track) % l10_init_mass = &
            log10(std_track(i_track) % init_mass)
       std_track(i_track) % lifetime = &
            interp_lin_log(std_track(i_MS) % l10_init_mass, &
            std_track(i_MS+1) % l10_init_mass, &
            std_track(i_MS) % last_age, &
            std_track(i_MS+1) % last_age, &
            std_track(i_track) % l10_init_mass)

       dim_age_tot = std_track(i_track) % dim_age + &
            std_track(i_track) % WD_extension*dim_age_WD
       allocate(std_track(i_track) % age(dim_age_tot))
       allocate(std_track(i_track) % lum(dim_age_tot))
       allocate(std_track(i_track) % T_eff(dim_age_tot))
       allocate(std_track(i_track) % grav(dim_age_tot))
       do i_age = 1, dim_age_tot
          read(unit, *) std_track(i_track) % lum(i_age), &
               std_track(i_track) % T_eff(i_age), &
               std_track(i_track) % grav(i_age), &
               std_track(i_track) % age(i_age)
       end do
       std_track(i_track) % last_age = &
            std_track(i_track) % age(std_track(i_track) % dim_age)
    end do

!# For the ZAHB track with the largest mass on the ZAHB:
    i_track = n_MS+n_HB
    read(unit, *) std_track(i_track) % mass_HB, &
         std_track(i_track) % dim_age, mass_core, &
         std_track(i_track) % final_mass, std_track(i_track) % WD_extension, &
         gross_Z_ejec_wind
    dim_age_tot = std_track(i_track) % dim_age + &
         std_track(i_track) % WD_extension*dim_age_WD
    allocate(std_track(i_track) % age(dim_age_tot))
    allocate(std_track(i_track) % lum(dim_age_tot))
    allocate(std_track(i_track) % T_eff(dim_age_tot))
    allocate(std_track(i_track) % grav(dim_age_tot))
    do i_age = 1, dim_age_tot
       read(unit, *) std_track(i_track) % lum(i_age), &
            std_track(i_track) % T_eff(i_age), &
            std_track(i_track) % grav(i_age), std_track(i_track) % age(i_age)
    end do
    std_track(i_track) % last_age = &
         std_track(i_track) % age(std_track(i_track) % dim_age)
    std_track(i_track) % lifetime = std_track(n_VLM+n_He_flash) % last_age
    std_track(i_track) % init_mass = std_track(n_VLM+n_He_flash) % init_mass
    std_track(i_track) % l10_init_mass = std_track(n_VLM+n_He_flash) % l10_init_mass

!# For the ZAMS track with the lowest mass not undergoing the helium flash
!# (excluding very low mass stars):
    i_track = n_VLM+n_He_flash+1
    delta_t = std_track(n_VLM+n_He_flash) % last_age &
         + std_track(n_MS+n_HB) % last_age &
         - std_track(i_track) % last_age
    dim_age_tot = std_track(i_track) % dim_age + &
         std_track(i_track) % WD_extension*dim_age_WD
    do i_age = std_track(i_track) % dim_age, dim_age_tot
       std_track(i_track) % age(i_age) = std_track(i_track) % age(i_age) + &
            delta_t !# !!! Age shift added so that the sequence of ages is increasing.
    end do
    call close_file(unit)

  end subroutine read_tracks

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

  subroutine connect_tracks(n_MS, n_VLM, n_He_flash, n_HB, dim_age_WD, &
       std_track)

    use mod_types

    implicit none
    integer, intent(in) :: n_MS, n_VLM, n_He_flash, dim_age_WD
    integer, intent(inout) :: n_HB
    type(struct_track), dimension(:), pointer :: std_track
!#......................................................................
    integer :: n_HB_supp, i_MS, i_HB, i_track, first_HB
    real(DPR) :: alpha
    integer :: dim_age_tot
    type(struct_track), dimension(:), allocatable :: tmp_track

    type(lk_lst_track) :: head_node
    type(lk_lst_track), pointer :: current_node => null()
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    first_HB = n_MS+1
    i_HB = first_HB
    i_MS = n_VLM+1
    n_HB_supp = 0

    call lk_lst_initialize_track(head_node)

!# Extension of the ZAMS tracks by ZAHB tracks for stars undergoing
!# the Helium flash AND "extension" of the ZAHB tracks by ZAMS tracks.

    do while (i_MS < n_VLM+n_He_flash)
       if (std_track(i_MS) % final_mass < std_track(first_HB) % mass_HB) then
          if (std_track(i_MS) % init_mass >= std_track(first_HB) % mass_HB) then

!# Stars with a ZAMS mass higher than the lowest ZAHB mass
!# [mass_HB(n_MS+1)], but which have, at the end of the RGB, a current
!# mass lower than mass_HB(n_MS+1), are assigned the evolution
!# corresponding to mass_HB(n_MS+1) after the RGB.

             n_HB_supp = n_HB_supp+1
             dim_age_tot = std_track(first_HB) % dim_age &
                  + std_track(first_HB) % WD_extension*dim_age_WD
             call lk_lst_new_node_track(head_node, current_node, &
                  dim_age_tot)
             current_node % l10_mass = std_track(i_MS) % l10_init_mass
             current_node % init_mass = std_track(i_MS) % init_mass
             current_node % WD_extension = std_track(first_HB) % WD_extension
             current_node % dim_age = std_track(first_HB) % dim_age
             current_node % age(:) = &
                  std_track(i_MS) % last_age &
                  + std_track(first_HB) % age(:)
             current_node % lum(:) = std_track(first_HB) % lum(:)
             current_node % T_eff(:) = std_track(first_HB) % T_eff(:)
             current_node % grav(:) = std_track(first_HB) % grav(:)
             i_MS = i_MS+1
          end if
       else
          if (std_track(i_HB) % l10_init_mass < &
               std_track(i_MS) % l10_init_mass) then

!# "Extension" of the ZAHB tracks by ZAMS tracks.

             dim_age_tot = std_track(i_HB) % dim_age + &
                  std_track(i_HB) % WD_extension*dim_age_WD
             call lk_lst_new_node_track(head_node, current_node, &
                  dim_age_tot)
             current_node % l10_mass = std_track(i_HB) % l10_init_mass
             current_node % init_mass = std_track(i_HB) % init_mass
             current_node % WD_extension = std_track(i_HB) % WD_extension
             current_node % dim_age = std_track(i_HB) % dim_age
             current_node % age(:) = std_track(i_HB) % lifetime + &
                  std_track(i_HB) % age(:)
             current_node % lum(:) = std_track(i_HB) % lum(:)
             current_node % T_eff(:) = std_track(i_HB) % T_eff(:)
             current_node % grav(:) = std_track(i_HB) % grav(:)
             i_HB = i_HB+1
          else

!# Extension of the ZAMS tracks by ZAHB tracks.

             n_HB_supp = n_HB_supp+1
             alpha = (std_track(i_HB) % l10_init_mass - &
                  std_track(i_MS) % l10_init_mass)/ &
                  (std_track(i_HB) % l10_init_mass - &
                  std_track(i_HB-1) % l10_init_mass)
             dim_age_tot = std_track(i_HB-1) % dim_age + &
                  std_track(i_HB-1) % WD_extension*dim_age_WD
             call lk_lst_new_node_track(head_node, current_node, &
                  dim_age_tot)
             current_node % WD_extension = std_track(i_HB-1) % WD_extension
             current_node % l10_mass = std_track(i_MS) % l10_init_mass
             current_node % init_mass = std_track(i_MS) % init_mass
             current_node % dim_age = std_track(i_HB-1) % dim_age
             current_node % age(1) = std_track(i_MS) % last_age
             current_node % age(2:) = &
                  std_track(i_MS) % last_age &
                  + 10**(alpha*log10(std_track(i_HB-1) % age(2:)) &
                  + (1-alpha)*log10(std_track(i_HB) % age(2:)))
             current_node % lum(:) = alpha*std_track(i_HB-1) % lum(:) &
                  + (1-alpha)*std_track(i_HB) % lum(:)
             current_node % T_eff(:) = alpha*std_track(i_HB-1) % T_eff(:) &
                  + (1-alpha)*std_track(i_HB) % T_eff(:)
             current_node % grav(:) = alpha*std_track(i_HB-1) % grav(:) &
                  + (1-alpha)*std_track(i_HB) % grav(:)
             i_MS = i_MS+1
          end if
       end if
    end do

!# "Extension" of the remaining ZAHB tracks by ZAMS tracks.

    do i_track = i_HB, n_MS+n_HB
       dim_age_tot = std_track(i_track) % dim_age + &
            std_track(i_track) % WD_extension*dim_age_WD
       call lk_lst_new_node_track(head_node, current_node, &
            dim_age_tot)
       current_node % l10_mass = std_track(i_track) % l10_init_mass
       current_node % init_mass = std_track(i_track) % init_mass
       current_node % WD_extension = std_track(i_track) % WD_extension
       current_node % dim_age = std_track(i_track) % dim_age
       current_node % age(:) = std_track(i_track) % lifetime + &
            std_track(i_track) % age(:)
       current_node % lum(:) = std_track(i_track) % lum(:)
       current_node % T_eff(:) = std_track(i_track) % T_eff(:)
       current_node % grav(:) = std_track(i_track) % grav(:)
    end do

    n_HB = n_HB+n_HB_supp

!# Reallocate `std_track` to include `_supp` tracks. Uses the temporary
!# array `tmp_track`.
!# ??? Cumbersome!
    if (allocated(tmp_track)) then
       do i_track = 1, size(tmp_track)
          if (associated(tmp_track(i_track) % age)) &
               deallocate(tmp_track(i_track) % age)
          if (associated(tmp_track(i_track) % lum)) &
               deallocate(tmp_track(i_track) % lum)
          if (associated(tmp_track(i_track) % T_eff)) &
               deallocate(tmp_track(i_track) % T_eff)
          if (associated(tmp_track(i_track) % grav)) &
               deallocate(tmp_track(i_track) % grav)
       enddo
       deallocate(tmp_track)
    endif
    allocate(tmp_track(n_MS))
    do i_track = 1, n_MS
       tmp_track(i_track) % l10_init_mass = std_track(i_track) % l10_init_mass
       tmp_track(i_track) % init_mass = std_track(i_track) % init_mass
       tmp_track(i_track) % dim_age = std_track(i_track) % dim_age
       tmp_track(i_track) % WD_extension = std_track(i_track) % WD_extension
       dim_age_tot = size(std_track(i_track) % age)
       allocate(tmp_track(i_track) % age(dim_age_tot))
       allocate(tmp_track(i_track) % lum(dim_age_tot))
       allocate(tmp_track(i_track) % T_eff(dim_age_tot))
       allocate(tmp_track(i_track) % grav(dim_age_tot))
       tmp_track(i_track) % age(:) = std_track(i_track) % age(:)
       tmp_track(i_track) % lum(:) = std_track(i_track) % lum(:)
       tmp_track(i_track) % T_eff(:) = std_track(i_track) % T_eff(:)
       tmp_track(i_track) % grav(:) = std_track(i_track) % grav(:)
    enddo

    do i_track = 1, size(std_track)
       deallocate(std_track(i_track) % age, std_track(i_track) % lum, &
            std_track(i_track) % T_eff, std_track(i_track) % grav)
    enddo
    deallocate(std_track)

    allocate(std_track(n_MS + n_HB))
    do i_track = 1, n_MS
       std_track(i_track) % l10_init_mass = tmp_track(i_track) % l10_init_mass
       std_track(i_track) % init_mass = tmp_track(i_track) % init_mass
       std_track(i_track) % dim_age = tmp_track(i_track) % dim_age
       std_track(i_track) % WD_extension = tmp_track(i_track) % WD_extension
       dim_age_tot = size(tmp_track(i_track) % age)
       allocate(std_track(i_track) % age(dim_age_tot))
       allocate(std_track(i_track) % lum(dim_age_tot))
       allocate(std_track(i_track) % T_eff(dim_age_tot))
       allocate(std_track(i_track) % grav(dim_age_tot))
       std_track(i_track) % age(:) = tmp_track(i_track) % age(:)
       std_track(i_track) % lum(:) = tmp_track(i_track) % lum(:)
       std_track(i_track) % T_eff(:) = tmp_track(i_track) % T_eff(:)
       std_track(i_track) % grav(:) = tmp_track(i_track) % grav(:)
       deallocate(tmp_track(i_track) % age, tmp_track(i_track) % lum, &
            tmp_track(i_track) % T_eff, tmp_track(i_track) % grav)
    enddo
    deallocate(tmp_track)

    current_node => head_node % ptr
    do i_track = first_HB, n_MS+n_HB
       std_track(i_track) % l10_init_mass = current_node % l10_mass
       std_track(i_track) % init_mass = current_node % init_mass
       std_track(i_track) % dim_age = current_node % dim_age
       std_track(i_track) % WD_extension = current_node % WD_extension
       dim_age_tot = std_track(i_track) % dim_age + &
            std_track(i_track) % WD_extension*dim_age_WD
       allocate(std_track(i_track) % age(dim_age_tot))
       allocate(std_track(i_track) % lum(dim_age_tot))
       allocate(std_track(i_track) % T_eff(dim_age_tot))
       allocate(std_track(i_track) % grav(dim_age_tot))
       std_track(i_track) % age(:) = current_node % age(:)
       std_track(i_track) % lum(:) = current_node % lum(:)
       std_track(i_track) % T_eff(:) = current_node % T_eff(:)
       std_track(i_track) % grav(:) = current_node % grav(:)
       current_node => current_node % ptr
    end do

  end subroutine connect_tracks

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

  subroutine white_dwarfs_tracks(dim_WD, n_MS, n_HB, n_VLM, n_He_flash, &
       dim_age_WD, &
       WD_track, std_track)

    use mod_types

    implicit none
    integer, intent(out) :: dim_WD
    integer, intent(in) :: n_MS, n_HB, n_VLM, n_He_flash, dim_age_WD
    type(struct_track), dimension(:), intent(in) :: std_track
    type(struct_track), dimension(:), pointer :: WD_track
!#......................................................................
    integer :: i_track, i_age, i_WD, dim_age
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    dim_WD = count(std_track(n_VLM+n_He_flash+1:n_MS+n_HB-1) % &
         WD_extension > 0)
    if (associated(WD_track)) then
       do i_WD = 1, size(WD_track)
          if (associated(WD_track(i_WD) % lum)) deallocate(WD_track(i_WD) % lum)
          if (associated(WD_track(i_WD) % T_eff)) deallocate(WD_track(i_WD) % T_eff)
          if (associated(WD_track(i_WD) % grav)) deallocate(WD_track(i_WD) % grav)
          if (associated(WD_track(i_WD) % age)) deallocate(WD_track(i_WD) % age)
       enddo
       deallocate(WD_track)
    endif
    allocate(WD_track(dim_WD))
    
    i_WD = 0
    do i_track = n_MS+1, n_MS+n_HB-1
       if (std_track(i_track) % WD_extension > 0) then
          i_WD = i_WD+1
          allocate(WD_track(i_WD) % lum(dim_age_WD))
          allocate(WD_track(i_WD) % T_eff(dim_age_WD))
          allocate(WD_track(i_WD) % grav(dim_age_WD))
          allocate(WD_track(i_WD) % age(dim_age_WD))
          WD_track(i_WD) % init_mass = std_track(i_track) % init_mass
          WD_track(i_WD) % l10_init_mass = std_track(i_track) % l10_init_mass
          dim_age = std_track(i_track) % dim_age
          do i_age = 1, dim_age_WD
             WD_track(i_WD) % lum(i_age) = std_track(i_track) % lum(i_age + dim_age)
             WD_track(i_WD) % T_eff(i_age) = std_track(i_track) % T_eff(i_age + dim_age)
             WD_track(i_WD) % grav(i_age) = std_track(i_track) % grav(i_age + dim_age)
             WD_track(i_WD) % age(i_age) = std_track(i_track) % age(i_age + dim_age)
          end do
          WD_track(i_WD) % last_age = WD_track(i_WD) % age(dim_age_WD)
       end if
    end do
    do i_track = n_VLM+n_He_flash+1, n_MS
       if (std_track(i_track) % WD_extension > 0) then
          i_WD = i_WD+1
          allocate(WD_track(i_WD) % lum(dim_age_WD))
          allocate(WD_track(i_WD) % T_eff(dim_age_WD))
          allocate(WD_track(i_WD) % grav(dim_age_WD))
          allocate(WD_track(i_WD) % age(dim_age_WD))
          WD_track(i_WD) % init_mass = std_track(i_track) % init_mass
          WD_track(i_WD) % l10_init_mass = std_track(i_track) % l10_init_mass
          dim_age = std_track(i_track) % dim_age
          do i_age = 1, dim_age_WD
             WD_track(i_WD) % lum(i_age) = std_track(i_track) % lum(i_age + dim_age)
             WD_track(i_WD) % T_eff(i_age) = std_track(i_track) % T_eff(i_age + dim_age)
             WD_track(i_WD) % grav(i_age) = std_track(i_track) % grav(i_age + dim_age)
             WD_track(i_WD) % age(i_age) = std_track(i_track) % age(i_age + dim_age)
          end do
          WD_track(i_WD) % last_age = WD_track(i_WD) % age(dim_age_WD)
       end if
    end do

  end subroutine white_dwarfs_tracks

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

  subroutine lk_lst_initialize_track(head_node)

    implicit none
    type(lk_lst_track), intent(inout) :: head_node
!#......................................................................
    type(lk_lst_track), pointer :: current_node => null(), &
         next_node => null()
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

!# Delete linked list, if already existing.
!# ??? Utiliser next_node.
    current_node => head_node % ptr
    do
       if (.not.associated(current_node)) exit
       next_node => current_node % ptr
       if (associated(current_node % age)) deallocate(current_node % age)
       if (associated(current_node % lum)) deallocate(current_node % lum)
       if (associated(current_node % T_eff)) deallocate(current_node % T_eff)
       if (associated(current_node % grav)) deallocate(current_node % grav)
       deallocate(current_node)
       current_node => next_node
    enddo

!# Set the head of the linked list.
    nullify(head_node % ptr)

  end subroutine lk_lst_initialize_track

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

  subroutine lk_lst_new_node_track(head_node, current_node, dim_age_tot)

    implicit none
    type(lk_lst_track), intent(inout) :: head_node
    type(lk_lst_track), pointer :: current_node
    integer, intent(in) :: dim_age_tot
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    if (.not.associated(head_node % ptr)) then
       allocate(head_node % ptr)
       current_node => head_node % ptr
    else
       allocate(current_node % ptr)
       current_node => current_node % ptr
    endif
    nullify(current_node % ptr)
    allocate(current_node % age(dim_age_tot))
    allocate(current_node % lum(dim_age_tot))
    allocate(current_node % T_eff(dim_age_tot))
    allocate(current_node % grav(dim_age_tot))

  end subroutine lk_lst_new_node_track

end module mod_tracks
