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

  use mod_types

  implicit none
  private
  type :: struct_yield
     integer :: dim_elem
     integer :: dim_mass
     character(len=std_string), dimension(:), pointer :: elem => null()
     real(DPR), dimension(:), pointer :: mass => null()
     real(DPR), dimension(:), pointer :: tot_ejec => null()
     real(DPR), dimension(:,:), pointer :: gross_ejec => null()
     real(DPR), dimension(:,:), pointer :: net_ejec => null()
  end type struct_yield
  public :: read_yields, compute_yields, fn_IRA_yield, struct_yield

contains

!#======================================================================
  
  subroutine read_yields(yields_set, &
       mass_Ch, dim_elem_SNIa, gross_ejec_SNIa, elem_SNIa, &
       X_sol, Y_sol, Z_sol, dim_elem_sol, abund_sol, elem_sol, &
       dim_tracks_file, &
       yield_LMW, yield_HMW, yield_CCSN)

    use mod_types
    use mod_directories, only : yields_dir
    use mod_file_access, only : open_file, close_file, path_file
    use mod_read_abundances, only : read_abundances
    use mod_constants, only : solar_abundances

    implicit none
    character(len=*) :: yields_set
    type(struct_yield), dimension(:), pointer :: yield_LMW, yield_HMW, &
         yield_CCSN
    real(DPR), intent(out) :: mass_Ch, X_sol, Y_sol, Z_sol
    integer, intent(out) :: dim_elem_SNIa, dim_elem_sol
    real(DPR), dimension(:), pointer :: gross_ejec_SNIa
    character(len=*), dimension(:), pointer :: elem_SNIa
    real(DPR), dimension(:), pointer :: abund_sol
    character(len=*), dimension(:), pointer :: elem_sol
    integer, intent(in) :: dim_tracks_file
!#......................................................................
    integer :: i, j, unit
    real(DPR) :: x
    character(std_string) :: skipped_string
    integer :: dim_elem, dim_mass
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

!# {Gross ejecta}(element) is the mass of this element which is ejected.
!# {Net ejecta}(element) = {gross ejecta}(element)
!#                         - {total mass ejected}*{initial abundance}(element).

    if (associated(yield_LMW)) deallocate(yield_LMW)
    allocate(yield_LMW(dim_tracks_file))
    if (associated(yield_HMW)) deallocate(yield_HMW)
    allocate(yield_HMW(dim_tracks_file))
    if (associated(yield_CCSN)) deallocate(yield_CCSN)
    allocate(yield_CCSN(dim_tracks_file))

!# Low-mass stars (ejecta during the 1st ("red") giant branch and the AGB phase).

    call open_file(unit, path_file(yields_dir, "gross_ejecta_LMW.txt"))
    read(unit,*) dim_elem
    do i = 1, dim_tracks_file
       yield_LMW(i) % dim_elem = dim_elem
       allocate(yield_LMW(i) % elem(dim_elem))
       read(unit, *) x, dim_mass
       yield_LMW(i) % dim_mass = dim_mass
       allocate(yield_LMW(i) % mass(dim_mass))
       allocate(yield_LMW(i) % tot_ejec(dim_mass))
       allocate(yield_LMW(i) % gross_ejec(dim_mass, dim_elem))
       allocate(yield_LMW(i) % net_ejec(dim_mass, dim_elem))
       read(unit, *) skipped_string, skipped_string, &
            yield_LMW(i) % elem(1:dim_elem)
       do j = 1, dim_mass
          read(unit, *) yield_LMW(i) % mass(j), &
               yield_LMW(i) % tot_ejec(j), &
               yield_LMW(i) % gross_ejec(j, 1:dim_elem)
       enddo
    enddo
    call close_file(unit)

    call open_file(unit, path_file(yields_dir, "net_ejecta_LMW.txt"))
    read(unit,*) dim_elem
    do i = 1, dim_tracks_file
       yield_LMW(i) % dim_elem = dim_elem
       read(unit, *) x, dim_mass
       yield_LMW(i) % dim_mass = dim_mass
       read(unit, *) skipped_string, skipped_string, &
            yield_LMW(i) % elem(1:dim_elem)
       do j = 1, dim_mass
          read(unit, *) yield_LMW(i) % mass(j), &
               yield_LMW(i) % tot_ejec(j), &
               yield_LMW(i) % net_ejec(j, 1:dim_elem)
       enddo
    enddo
    call close_file(unit)

!# High-mass stars.

    if (yields_set == "yields_Portinari.txt") then

!# Wind ("Wolf-Rayet") phase.

       call open_file(unit, path_file(yields_dir, "gross_ejecta_HMW_P.txt"))
       read(unit,*) dim_elem
       do i = 1, dim_tracks_file
          yield_HMW(i) % dim_elem = dim_elem
          allocate(yield_HMW(i) % elem(dim_elem))
          read(unit, *) x, dim_mass
          yield_HMW(i) % dim_mass = dim_mass
          allocate(yield_HMW(i) % mass(dim_mass))
          allocate(yield_HMW(i) % tot_ejec(dim_mass))
          allocate(yield_HMW(i) % gross_ejec(dim_mass, dim_elem))
          allocate(yield_HMW(i) % net_ejec(dim_mass, dim_elem))
          read(unit, *) skipped_string, skipped_string, &
               yield_HMW(i) % elem(1:dim_elem)
          do j = 1, dim_mass
             read(unit, *) yield_HMW(i) % mass(j), &
                  yield_HMW(i) % tot_ejec(j), &
                  yield_HMW(i) % gross_ejec(j, 1:dim_elem)
          enddo
       enddo
       call close_file(unit)

       call open_file(unit, path_file(yields_dir, "net_ejecta_HMW_P.txt"))
       read(unit,*) dim_elem
       do i = 1, dim_tracks_file
          yield_HMW(i) % dim_elem = dim_elem
          read(unit, *) x, dim_mass
          yield_HMW(i) % dim_mass = dim_mass
          read(unit, *) skipped_string, skipped_string, &
               yield_HMW(i) % elem(1:dim_elem)
          do j = 1, dim_mass
             read(unit, *) yield_HMW(i) % mass(j), &
                  yield_HMW(i) % tot_ejec(j), &
                  yield_HMW(i) % net_ejec(j, 1:dim_elem)
          enddo
       enddo
       call close_file(unit)

!# Supernova phase.

       call open_file(unit, path_file(yields_dir, "gross_ejecta_CCSN_P.txt"))
       read(unit,*) dim_elem
       do i = 1, dim_tracks_file
          yield_CCSN(i) % dim_elem = dim_elem
          allocate(yield_CCSN(i) % elem(dim_elem))
          read(unit, *) x, dim_mass
          yield_CCSN(i) % dim_mass = dim_mass
          allocate(yield_CCSN(i) % mass(dim_mass))
          allocate(yield_CCSN(i) % tot_ejec(dim_mass))
          allocate(yield_CCSN(i) % gross_ejec(dim_mass, dim_elem))
          allocate(yield_CCSN(i) % net_ejec(dim_mass, dim_elem))
          read(unit, *) skipped_string, skipped_string, &
               yield_CCSN(i) % elem(1:dim_elem)
          do j = 1, dim_mass
             read(unit, *) yield_CCSN(i) % mass(j), &
                  yield_CCSN(i) % tot_ejec(j), &
                  yield_CCSN(i) % gross_ejec(j, 1:dim_elem)
          enddo
       enddo
       call close_file(unit)

       call open_file(unit, path_file(yields_dir, "net_ejecta_CCSN_P.txt"))
       read(unit,*) dim_elem
       do i = 1, dim_tracks_file
          yield_CCSN(i) % dim_elem = dim_elem
          read(unit, *) x, dim_mass
          yield_CCSN(i) % dim_mass = dim_mass
          read(unit, *) skipped_string, skipped_string, &
               yield_CCSN(i) % elem(1:dim_elem)
          do j = 1, dim_mass
             read(unit, *) yield_CCSN(i) % mass(j), &
                  yield_CCSN(i) % tot_ejec(j), &
                  yield_CCSN(i) % net_ejec(j, 1:dim_elem)
          enddo
       enddo
       call close_file(unit)

    else if (yields_set == "yields_Woosley_Weaver.txt") then !# Use Woosley & Weaver \
!# yields for high-mass stars (no stellar winds).

       call open_file(unit, path_file(yields_dir, "gross_ejecta_CCSN_WW.txt"))
       read(unit,*) dim_elem
       do i = 1, dim_tracks_file
          yield_CCSN(i) % dim_elem = dim_elem
          allocate(yield_CCSN(i) % elem(dim_elem))
          read(unit, *) x, dim_mass
          yield_CCSN(i) % dim_mass = dim_mass
          allocate(yield_CCSN(i) % mass(dim_mass))
          allocate(yield_CCSN(i) % tot_ejec(dim_mass))
          allocate(yield_CCSN(i) % gross_ejec(dim_mass, dim_elem))
          allocate(yield_CCSN(i) % net_ejec(dim_mass, dim_elem))
          read(unit, *) skipped_string, skipped_string, &
               yield_CCSN(i) % elem(1:dim_elem)
          do j = 1, dim_mass
             read(unit, *) yield_CCSN(i) % mass(j), &
                  yield_CCSN(i) % tot_ejec(j), &
                  yield_CCSN(i) % gross_ejec(j, 1:dim_elem)
          enddo
       enddo
       call close_file(unit)

       call open_file(unit, path_file(yields_dir, "net_ejecta_CCSN_WW.txt"))
       read(unit,*) dim_elem
       do i = 1, dim_tracks_file
          yield_CCSN(i) % dim_elem = dim_elem
          read(unit, *) x, dim_mass
          yield_CCSN(i) % dim_mass = dim_mass
          read(unit, *) skipped_string, skipped_string, &
               yield_CCSN(i) % elem(1:dim_elem)
          do j = 1, dim_mass
             read(unit, *) yield_CCSN(i) % mass(j), &
                  yield_CCSN(i) % tot_ejec(j), &
                  yield_CCSN(i) % net_ejec(j, 1:dim_elem)
          enddo
       enddo
       call close_file(unit)

    else

       write(*, "(a)") "Yields """, yields_set, """ unavailable. Stopped."
       stop

    endif

!# SNIa.

    call read_abundances(path_file(yields_dir, "W7.txt"), dim_elem_SNIa, &
         gross_ejec_SNIa, elem_SNIa)
    mass_Ch = sum(gross_ejec_SNIa(1:dim_elem_SNIa))

!# Solar abundances.

    call read_abundances(path_file(yields_dir, solar_abundances), dim_elem_sol, abund_sol, elem_sol)
    X_sol = sum(abund_sol, mask = elem_sol == "1H" .or. elem_sol == "2H")
    Y_sol = sum(abund_sol, mask = elem_sol == "3He" .or. elem_sol == "4He")
    Z_sol = 1 - X_sol - Y_sol
    
  end subroutine read_yields

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

  subroutine compute_yields(i_tracks_file, Y_track, Z_track, yields_set, &
       yield_LMW, yield_HMW, yield_CCSN, &
       gross_ejec_SNIa, elem_SNIa, &
       mass_Ch, Z_sol, abund_sol, elem_sol, &
       dim_mass_yields, mass_yields, ejec_tot, ejec_elem, &
       ejec_tot_SNIa, ejec_elem_SNIa, &
       carb_dust_LMW, sil_dust_LMW, carb_dust_HMW, sil_dust_HMW, &
       carb_dust_CCSN, sil_dust_CCSN, carb_dust_SNIa, sil_dust_SNIa, &
       O_dust_LMW, O_dust_HMW, O_dust_CCSN, O_dust_SNIa)

    use mod_types
    use mod_constants, only : &
         dim_elem, elem_id, A_C12, A_C13, &
         A_O16, A_O17, A_O18, A_Mg24, A_Si28, A_S32, A_Ca40, A_Ti48, A_Fe56
    use mod_loc, only : i_loc
    
    implicit none
    integer, intent(in) :: i_tracks_file
    character(len=*), intent(in) :: yields_set
    type(struct_yield), dimension(:), intent(in) :: yield_LMW, yield_HMW, &
         yield_CCSN    
    integer, intent(out) :: dim_mass_yields
    real(DPR), intent(out) :: carb_dust_SNIa, sil_dust_SNIa, O_dust_SNIa
    real(DPR), dimension(:), pointer :: ejec_tot
    real(DPR), dimension(:,:), pointer :: ejec_elem
    real(DPR), dimension(:), pointer :: mass_yields, carb_dust_LMW, &
         sil_dust_LMW, carb_dust_HMW, sil_dust_HMW, carb_dust_CCSN, &
         sil_dust_CCSN, O_dust_LMW, O_dust_HMW, O_dust_CCSN
    real(DPR), intent(out) :: ejec_tot_SNIa
    real(DPR), dimension(0:), intent(out) :: ejec_elem_SNIa
    real(DPR), intent(in) :: Y_track, Z_track, mass_Ch, Z_sol
    real(DPR), dimension(:), intent(in) :: gross_ejec_SNIa, abund_sol
    character(len=*), dimension(:), intent(in) :: elem_sol, elem_SNIa
!#......................................................................
    integer :: i_Z, i_O, i_C, i_Fe, i_He, i_N, i_Ne, i_Mg, i_Si, i_S, i_Ca

    real(DPR) :: nb_atoms_C, nb_atoms_O
    integer :: i, j
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    i_Z = 0
    i_O = i_loc(elem_id, "O")
    i_C = i_loc(elem_id, "C")
    i_Fe = i_loc(elem_id, "Fe")
    i_He = i_loc(elem_id, "He")
    i_N = i_loc(elem_id, "N")
    i_Ne = i_loc(elem_id, "Ne")
    i_Mg = i_loc(elem_id, "Mg")
    i_Si = i_loc(elem_id, "Si")
    i_S = i_loc(elem_id, "S")
    i_Ca = i_loc(elem_id, "Ca")

    if (yields_set == "yields_Woosley_Weaver.txt" .or. &
         yields_set == "yields_Portinari.txt") then
       dim_mass_yields = 1 + yield_LMW(i_tracks_file) % dim_mass &
            + yield_CCSN(i_tracks_file) % dim_mass
    
       if (associated(ejec_tot)) deallocate(ejec_tot)
       allocate(ejec_tot(dim_mass_yields))
       if (associated(ejec_elem)) deallocate(ejec_elem)
       allocate(ejec_elem(dim_mass_yields, 0:dim_elem))
       if (associated(mass_yields)) deallocate(mass_yields)
       allocate(mass_yields(dim_mass_yields))
       
       if (associated(carb_dust_LMW)) deallocate(carb_dust_LMW)
       allocate(carb_dust_LMW(dim_mass_yields))
       if (associated(sil_dust_LMW)) deallocate(sil_dust_LMW)
       allocate(sil_dust_LMW(dim_mass_yields))
       if (associated(O_dust_LMW)) deallocate(O_dust_LMW)
       allocate(O_dust_LMW(dim_mass_yields))
       
       if (associated(carb_dust_HMW)) deallocate(carb_dust_HMW)
       allocate(carb_dust_HMW(dim_mass_yields))
       if (associated(sil_dust_HMW)) deallocate(sil_dust_HMW)
       allocate(sil_dust_HMW(dim_mass_yields))
       if (associated(O_dust_HMW)) deallocate(O_dust_HMW)
       allocate(O_dust_HMW(dim_mass_yields))

       if (associated(carb_dust_CCSN)) deallocate(carb_dust_CCSN)
       allocate(carb_dust_CCSN(dim_mass_yields))
       if (associated(sil_dust_CCSN)) deallocate(sil_dust_CCSN)
       allocate(sil_dust_CCSN(dim_mass_yields))
       if (associated(O_dust_CCSN)) deallocate(O_dust_CCSN)
       allocate(O_dust_CCSN(dim_mass_yields))
       
    else
       write(*, "(a)") "Yields """, yields_set, """ unavailable. Stopped."
       stop
    endif


!# For the purpose of extrapolation below `mass_LMW(.,1)` (~= 0.8 M_sol), we assume that
!#    (1) the star with the initial mass `mass_LMW(.,1)`, denoted by "LS" (lightest star)
!#        hereafter, will end as a CO white dwarf;
!#    (2) the mass of the stellar remnant for all stars ending as CO white dwarfs and
!#        with an initial mass below `mass_LMW(.,1)` is the same as for LS;
!#    (3) all stars "dying" later than LS and before the maximal time for which SSPs
!#        are computed end as CO white dwarfs.
!# We therefore add an object with an initial mass and a remnant's mass equal to the
!# remnant's mass of LS; this object does not eject anything.

    mass_yields(1) = yield_LMW(i_tracks_file) % mass(1)-yield_LMW(i_tracks_file) % tot_ejec(1)
    ejec_tot(:) = 0
    ejec_elem(:,0:) = 0
!# Following assignments mandatory because, although `carb_dust_LMW` (for instance)
!# is defined for all stars, it is computed hereafter only for low-mass stars.
!# It might also retain the value computed for `i_tracks_file-1` if object #i
!# corresponds to a low-mass star for yields `i_tracks_file-1` and to a high-mass star
!# for yields `i_tracks_file`.
!# Similarly for other `*_LMW`, `*_HMW` and `*_CCSN` quantities.
    carb_dust_LMW(:) = 0
    sil_dust_LMW(:) = 0
    O_dust_LMW(:) = 0
    carb_dust_HMW(:) = 0
    sil_dust_HMW(:) = 0  
    O_dust_HMW(:) = 0
    carb_dust_CCSN(:) = 0
    sil_dust_CCSN(:) = 0
    O_dust_CCSN(:) = 0

!# ??? Should one modify instead the interpolation routine `interp_lin_lin` used in
!# "mod_remnants_ejec_SN.f90" to ensure, in case of extrapolation below the
!# mass of LS, that
!#    (1) the total ejected mass is non-negative and less than the initial mass;
!#    (2) the mass of the gross ejecta of each element is non-negative;
!#    (3) their sum is consistent with the total ejected mass?

!#......................................................................
!# Low-mass stars.

    dim_mass_yields = 1
    do i = 1, yield_LMW(i_tracks_file) % dim_mass
       dim_mass_yields = dim_mass_yields+1
       mass_yields(dim_mass_yields) = yield_LMW(i_tracks_file) % mass(i)
!#
       ejec_tot(dim_mass_yields) = yield_LMW(i_tracks_file) % tot_ejec(i)
!# Net yield of metals.
       ejec_elem(dim_mass_yields, i_Z) = -sum(yield_LMW(i_tracks_file) % net_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "1H" .or. &
            yield_LMW(i_tracks_file) % elem(:) == "3He" .or. &
            yield_LMW(i_tracks_file) % elem(:) == "4He")
!# Net yield of oxygen.
       ejec_elem(dim_mass_yields, i_O) = sum(yield_LMW(i_tracks_file) % net_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "16O" .or. &
            yield_LMW(i_tracks_file) % elem(:) == "17O" .or. &
            yield_LMW(i_tracks_file) % elem(:) == "18O")
!# Net yield of carbon.
       ejec_elem(dim_mass_yields, i_C) = sum(yield_LMW(i_tracks_file) % net_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "12C" .or. &
            yield_LMW(i_tracks_file) % elem(:) == "13C")
!# Net yield of iron.
       ejec_elem(dim_mass_yields, i_Fe) = sum(yield_LMW(i_tracks_file) % net_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "56Fe")
!# Net yield of helium.
       ejec_elem(dim_mass_yields, i_He) = sum(yield_LMW(i_tracks_file) % net_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "3He" .or. &
            yield_LMW(i_tracks_file) % elem(:) == "4He")
!# Net yield of nitrogen.
       ejec_elem(dim_mass_yields, i_N) = sum(yield_LMW(i_tracks_file) % net_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "14N" .or. &
            yield_LMW(i_tracks_file) % elem(:) == "15N")
!# Net yield of neon.
       ejec_elem(dim_mass_yields, i_Ne) = sum(yield_LMW(i_tracks_file) % net_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "20Ne" .or. &
            yield_LMW(i_tracks_file) % elem(:) == "22Ne")
!# Net yield of magnesium.
       ejec_elem(dim_mass_yields, i_Mg) = sum(yield_LMW(i_tracks_file) % net_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "24Mg")
!# Net yield of silicon.
       ejec_elem(dim_mass_yields, i_Si) = sum(yield_LMW(i_tracks_file) % net_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "28Si")
!# Net yield of sulfur.
       ejec_elem(dim_mass_yields, i_S) = sum(yield_LMW(i_tracks_file) % net_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "32S")
!# Net yield of calcium.
       ejec_elem(dim_mass_yields, i_Ca) = sum(yield_LMW(i_tracks_file) % net_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "40Ca")
       nb_atoms_C = &
            sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "12C")/A_C12 &
            + sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "13C")/A_C13
       nb_atoms_O = &
            sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "16O")/A_O16 &
            + sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "17O")/A_O17 &
            + sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
            mask = yield_LMW(i_tracks_file) % elem(:) == "18O")/A_O18

       if (nb_atoms_C > nb_atoms_O) then

!# Because the formation of the CO molecule is much more efficient than that of dust in stellar winds,
!# carbon dust is produced if the number of carbon atoms is larger than that of oxygen atoms: all oxygen atoms
!# are used for CO (so, no silicate dust may be produced, since oxygen is needed for it), and all carbon
!# atoms not used for CO may be included in dust. Note that hydrogen atoms in carbon dust are neglected.
!# The real quantity of carbon or silicate dust formed around low-mass stars is
!# determined by `LMW_carb_deplet` and `LMW_sil_deplet`.

          carb_dust_LMW(dim_mass_yields) = &
               sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_LMW(i_tracks_file) % elem(:) == "12C" &
               .or. yield_LMW(i_tracks_file) % elem(:) == "13C") &
               -A_C12/A_O16* & !# ??? Not fully consistent: A_C13, A_O17 and A_O18 should be used too.
               sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_LMW(i_tracks_file) % elem(:) == "16O" &
               .or. yield_LMW(i_tracks_file) % elem(:) == "17O" .or. &
               yield_LMW(i_tracks_file) % elem(:) == "18O")
          sil_dust_LMW(dim_mass_yields) = 0
          O_dust_LMW(dim_mass_yields) = 0
       else

!# If the number of oxygen atoms is larger than that of carbon atoms, only silicate dust is produced: to each
!# magnesium, silicon, sulfur, calcium or iron atom is associated one oxygen atom, in the mean. It is assumed
!# that the number of oxygen atoms is sufficient for that.

          carb_dust_LMW(dim_mass_yields) = 0
          sil_dust_LMW(dim_mass_yields) = &
               sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_LMW(i_tracks_file) % elem(:) == "24Mg") &
               + sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_LMW(i_tracks_file) % elem(:) == "28Si") &
               + sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_LMW(i_tracks_file) % elem(:) == "32S") &
               + sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_LMW(i_tracks_file) % elem(:) == "40Ca") &
               + sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_LMW(i_tracks_file) % elem(:) == "56Fe")
          O_dust_LMW(dim_mass_yields) = &
               sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_LMW(i_tracks_file) % elem(:) == "24Mg")*A_O16/A_Mg24 &
               + sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_LMW(i_tracks_file) % elem(:) == "28Si")*A_O16/A_Si28 &
               + sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_LMW(i_tracks_file) % elem(:) == "32S")*A_O16/A_S32 &
               + sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_LMW(i_tracks_file) % elem(:) == "40Ca")*A_O16/A_Ca40 &
               + sum(yield_LMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_LMW(i_tracks_file) % elem(:) == "56Fe")*A_O16/A_Fe56

!# ??? The masses of the isotopes should be used too.
       endif
    enddo

!#......................................................................

!# Woosley & Weaver.

    if (yields_set == "yields_Woosley_Weaver.txt") then
       do i = 1, yield_CCSN(i_tracks_file) % dim_mass
          dim_mass_yields = dim_mass_yields+1
          mass_yields(dim_mass_yields) = yield_CCSN(i_tracks_file) % mass(i)
          ejec_tot(dim_mass_yields) = yield_CCSN(i_tracks_file) % tot_ejec(i)
!# Net yield of metals.
          ejec_elem(dim_mass_yields, i_Z) = -sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "H" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "He")
!# Net yield of oxygen.
          ejec_elem(dim_mass_yields, i_O) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "O")
!# Net yield of carbon.
          ejec_elem(dim_mass_yields, i_C) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "C")
!# Net yield of iron.
          ejec_elem(dim_mass_yields, i_Fe) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Fe")
!# Net yield of helium.
          ejec_elem(dim_mass_yields, i_He) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "He")
!# Net yield of nitrogen.
          ejec_elem(dim_mass_yields, i_N) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "N")
!# Net yield of neon.
          ejec_elem(dim_mass_yields, i_Ne) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Ne")
!# Net yield of magnesium.
          ejec_elem(dim_mass_yields, i_Mg) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Mg")
!# Net yield of silicon.
          ejec_elem(dim_mass_yields, i_Si) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Si")
!# Net yield of sulfur.
          ejec_elem(dim_mass_yields, i_S) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "S")
!# Net yield of calcium.
          ejec_elem(dim_mass_yields, i_Ca) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Ca")
!# Gross yield of dust.
          carb_dust_CCSN(dim_mass_yields) = &
               sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "C")

          sil_dust_CCSN(dim_mass_yields) = &
               sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Mg") &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Si") &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "S") &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Ca") &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Ti") &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Fe")
          O_dust_CCSN(dim_mass_yields) = &
               sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Mg")*A_O16/A_Mg24 &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Si")*A_O16/A_Si28 &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "S")*A_O16/A_S32 &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Ca")*A_O16/A_Ca40 &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Ti")*A_O16/A_Ti48 &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "Fe")*A_O16/A_Fe56
       enddo

    else if (yields_set == "yields_Portinari.txt") then

!# Portinari et al.
!# Only supernova ejecta for lower high-mass stars.

       do i = 1, yield_CCSN(i_tracks_file) % dim_mass-yield_HMW(i_tracks_file) % dim_mass
          dim_mass_yields = dim_mass_yields+1
          mass_yields(dim_mass_yields) = yield_CCSN(i_tracks_file) % mass(i)
          ejec_tot(dim_mass_yields) = yield_CCSN(i_tracks_file) % tot_ejec(i)
!# Net yield of metals.
          ejec_elem(dim_mass_yields, i_Z) = -sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "1H" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "3He" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "4He")
!# Net yield of oxygen.
          ejec_elem(dim_mass_yields, i_O) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "16O" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "17O" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "18O")
!# Net yield of carbon.
          ejec_elem(dim_mass_yields, i_C) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "12C" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "13C")
!# Net yield of iron.
          ejec_elem(dim_mass_yields, i_Fe) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "56Fe")
!# Net yield of helium.
          ejec_elem(dim_mass_yields, i_He) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "3He" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "4He")
!# Net yield of nitrogen.
          ejec_elem(dim_mass_yields, i_N) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "14N" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "15N")
!# Net yield of neon.
          ejec_elem(dim_mass_yields, i_Ne) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "20Ne" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "22Ne")
!# Net yield of magnesium.
          ejec_elem(dim_mass_yields, i_Mg) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "24Mg")
!# Net yield of silicon.
          ejec_elem(dim_mass_yields, i_Si) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "28Si")
!# Net yield of sulfur.
          ejec_elem(dim_mass_yields, i_S) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "32S")
!# Net yield of calcium.
          ejec_elem(dim_mass_yields, i_Ca) = sum(yield_CCSN(i_tracks_file) % net_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "40Ca")

!# No CO is formed: all the carbon, magnesium, silicon, sulfur, calcium and iron atoms may be used to form dust.
!# Note that hydrogen atoms in carbon dust are neglected.
!# To each magnesium, silicon, sulfur, calcium, titanium (for Woosley and Weaver yields only), or iron atom is associated
!# one oxygen atom, in the mean. It is assumed that the number of oxygen atoms is sufficient for that.
!# The real quantity of carbon or silicate dust formed around core-collapse
!# supernovae is determined by `CCSN_carb_deplet` and
!# `CCSN_sil_deplet`.

          carb_dust_CCSN(dim_mass_yields) = &
               sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "12C" &
               .or. yield_CCSN(i_tracks_file) % elem(:) == "13C")

          sil_dust_CCSN(dim_mass_yields) = &
               sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "24Mg") &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "28Si") &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "32S") &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "40Ca") &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "56Fe")

          O_dust_CCSN(dim_mass_yields) = &
               sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "24Mg")*A_O16/A_Mg24 &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "28Si")*A_O16/A_Si28 &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "32S")*A_O16/A_S32 &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "40Ca")*A_O16/A_Ca40 &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "56Fe")*A_O16/A_Fe56
       enddo

!#......................................................................

!# Wind (Wolf-Rayet) + supernova ejecta for higher high-mass stars.

       do i = 1, yield_HMW(i_tracks_file) % dim_mass
          dim_mass_yields = dim_mass_yields+1
          j = i+yield_CCSN(i_tracks_file) % dim_mass-yield_HMW(i_tracks_file) % dim_mass
          mass_yields(dim_mass_yields) = yield_HMW(i_tracks_file) % mass(i)
          ejec_tot(dim_mass_yields) = yield_HMW(i_tracks_file) % tot_ejec(i)+yield_CCSN(i_tracks_file) % tot_ejec(j)
!# Net yield of metals.
          ejec_elem(dim_mass_yields, i_Z) = -sum(yield_CCSN(i_tracks_file) % net_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "1H" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "3He" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "4He") &
               - sum(yield_HMW(i_tracks_file) % net_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "1H" .or. &
               yield_HMW(i_tracks_file) % elem(:) == "3He" .or. &
               yield_HMW(i_tracks_file) % elem(:) == "4He")
!# Net yield of oxygen.
          ejec_elem(dim_mass_yields, i_O) = sum(yield_CCSN(i_tracks_file) % net_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "16O" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "17O" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "18O") &
               + sum(yield_HMW(i_tracks_file) % net_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "16O" .or. &
               yield_HMW(i_tracks_file) % elem(:) == "17O" .or. &
               yield_HMW(i_tracks_file) % elem(:) == "18O")
!# Net yield of carbon.
          ejec_elem(dim_mass_yields, i_C) = sum(yield_CCSN(i_tracks_file) % net_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "12C" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "13C") &
               + sum(yield_HMW(i_tracks_file) % net_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "12C" .or. &
               yield_HMW(i_tracks_file) % elem(:) == "13C")
!# Net yield of iron.
          ejec_elem(dim_mass_yields, i_Fe) = sum(yield_CCSN(i_tracks_file) % net_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "56Fe") &
               + sum(yield_HMW(i_tracks_file) % net_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "56Fe")
!# Net yield of helium.
          ejec_elem(dim_mass_yields, i_He) = sum(yield_CCSN(i_tracks_file) % net_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "3He" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "4He") &
               + sum(yield_HMW(i_tracks_file) % net_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "3He" .or. &
               yield_HMW(i_tracks_file) % elem(:) == "4He")
!# Net yield of nitrogen.
          ejec_elem(dim_mass_yields, i_N) = sum(yield_CCSN(i_tracks_file) % net_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "14N" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "15N") &
               + sum(yield_HMW(i_tracks_file) % net_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "14N" .or. &
               yield_HMW(i_tracks_file) % elem(:) == "15N")
!# Net yield of neon.
          ejec_elem(dim_mass_yields, i_Ne) = sum(yield_CCSN(i_tracks_file) % net_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "20Ne" .or. &
               yield_CCSN(i_tracks_file) % elem(:) == "22Ne") &
               + sum(yield_HMW(i_tracks_file) % net_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "20Ne" .or. &
               yield_HMW(i_tracks_file) % elem(:) == "22Ne")
!# Net yield of magnesium.
          ejec_elem(dim_mass_yields, i_Mg) = sum(yield_CCSN(i_tracks_file) % net_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "24Mg") &
               + sum(yield_HMW(i_tracks_file) % net_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "24Mg")
!# Net yield of silicon.
          ejec_elem(dim_mass_yields, i_Si) = sum(yield_CCSN(i_tracks_file) % net_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "28Si") &
               + sum(yield_HMW(i_tracks_file) % net_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "28Si")
!# Net yield of sulfur.
          ejec_elem(dim_mass_yields, i_S) = sum(yield_CCSN(i_tracks_file) % net_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "32S") &
               + sum(yield_HMW(i_tracks_file) % net_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "32S")
!# Net yield of calcium.
          ejec_elem(dim_mass_yields, i_Ca) = sum(yield_CCSN(i_tracks_file) % net_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "40Ca") &
               + sum(yield_HMW(i_tracks_file) % net_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "40Ca")

!# Gross yield of dust.
!# No CO is formed: all the carbon, magnesium, silicon, sulfur, calcium and iron atoms may be used to form dust.
!# Note that hydrogen atoms in carbon dust are neglected.
!# To each magnesium, silicon, sulfur, calcium or iron atom is associated one oxygen atom, in the mean.
!# It is assumed that the number of oxygen atoms is sufficient for that.
!# The real quantity of carbon or silicate dust formed around core-collapse
!# supernovae is determined by `CCSN_carb_deplet` and
!# `CCSN_sil_deplet`.

          carb_dust_CCSN(dim_mass_yields) = &
               sum(yield_CCSN(i_tracks_file) % gross_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "12C" &
               .or. yield_CCSN(i_tracks_file) % elem(:) == "13C")

          sil_dust_CCSN(dim_mass_yields) = &
               sum(yield_CCSN(i_tracks_file) % gross_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "24Mg") &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "28Si") &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "32S") &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "40Ca") &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "56Fe")

          O_dust_CCSN(dim_mass_yields) = &
               sum(yield_CCSN(i_tracks_file) % gross_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "24Mg")*A_O16/A_Mg24 &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "28Si")*A_O16/A_Si28 &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "32S")*A_O16/A_S32 &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "40Ca")*A_O16/A_Ca40 &
               + sum(yield_CCSN(i_tracks_file) % gross_ejec(j, :), &
               mask = yield_CCSN(i_tracks_file) % elem(:) == "56Fe")*A_O16/A_Fe56

          nb_atoms_C = &
               sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "12C")/A_C12 &
               + sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "13C")/A_C13
          nb_atoms_O = &
               sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "16O")/A_O16 &
               + sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "17O")/A_O17 &
               + sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
               mask = yield_HMW(i_tracks_file) % elem(:) == "18O")/A_O18

          if (nb_atoms_C > nb_atoms_O) then

!# Because the formation of the CO molecule is much more efficient than that of dust in stellar winds,
!# carbon dust is produced if the number of carbon atoms is larger than that of oxygen atoms: all oxygen
!# atoms are used for CO (so, no silicate dust may be produced, since oxygen is needed for it), and all carbon
!# atoms not used for CO may be included in dust. Note that hydrogen atoms in carbon dust are neglected.
!# The real quantity of carbon or silicate dust formed in the winds of
!# high-mass stars is determined by `HMW_carb_deplet` and `HMW_sil_deplet`.

             carb_dust_HMW(dim_mass_yields) = &
                  sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
                  mask = yield_HMW(i_tracks_file) % elem(:) == "12C" &
                  .or. yield_HMW(i_tracks_file) % elem(:) == "13C") &
                  -A_C12/A_O16* & !# ??? Not fully consistent: A_C13, A_O17 and A_O18 should be used too.
                  sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
                  mask = yield_HMW(i_tracks_file) % elem(:) == "16O" &
                  .or. yield_HMW(i_tracks_file) % elem(:) == "17O" .or. &
                  yield_HMW(i_tracks_file) % elem(:) == "18O")
             sil_dust_HMW(dim_mass_yields) = 0
             O_dust_HMW(dim_mass_yields) = 0
          else

!# If the number of oxygen atoms is larger than that of carbon atoms, only silicate dust is produced: to each
!# magnesium, silicon, sulfur, calcium or iron atom is associated one oxygen atom, in the mean. It is assumed
!# that the number of oxygen atoms is sufficient for that.

             carb_dust_HMW(dim_mass_yields) = 0

             sil_dust_HMW(dim_mass_yields) = &
                  sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
                  mask = yield_HMW(i_tracks_file) % elem(:) == "24Mg") &
                  + sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
                  mask = yield_HMW(i_tracks_file) % elem(:) == "28Si") &
                  + sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
                  mask = yield_HMW(i_tracks_file) % elem(:) == "32S") &
                  + sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
                  mask = yield_HMW(i_tracks_file) % elem(:) == "40Ca") &
                  + sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
                  mask = yield_HMW(i_tracks_file) % elem(:) == "56Fe")

             O_dust_HMW(dim_mass_yields) = &
                  sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
                  mask = yield_HMW(i_tracks_file) % elem(:) == "24Mg")*A_O16/A_Mg24 &
                  + sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
                  mask = yield_HMW(i_tracks_file) % elem(:) == "28Si")*A_O16/A_Si28 &
                  + sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
                  mask = yield_HMW(i_tracks_file) % elem(:) == "32S")*A_O16/A_S32 &
                  + sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
                  mask = yield_HMW(i_tracks_file) % elem(:) == "40Ca")*A_O16/A_Ca40 &
                  + sum(yield_HMW(i_tracks_file) % gross_ejec(i, :), &
                  mask = yield_HMW(i_tracks_file) % elem(:) == "56Fe")*A_O16/A_Fe56
!# ??? The masses of the isotopes should be used too.
          endif
       enddo
    endif

!#......................................................................

!# SNIa
    ejec_tot_SNIa = mass_Ch

!# Net yield of metals.
    ejec_elem_SNIa(i_Z) = mass_Ch-Z_track*ejec_tot_SNIa

!# Net yield of oxygen.
    ejec_elem_SNIa(i_O) = sum(gross_ejec_SNIa, mask = elem_SNIa == "16O" .or. &
         elem_SNIa == "17O" .or. elem_SNIa == "18O") &
         -ejec_tot_SNIa*Z_track/Z_sol * &
         sum(abund_sol, mask = elem_sol == "16O" .or. elem_sol == "17O" .or. &
         elem_sol == "18O")

!# Net yield of carbon.
    ejec_elem_SNIa(i_C) = sum(gross_ejec_SNIa, mask = elem_SNIa == "12C" .or. &
         elem_SNIa == "13C" .or. elem_SNIa == "14C") &
         -ejec_tot_SNIa*Z_track/Z_sol * &
         sum(abund_sol, mask = elem_sol == "12C" .or. elem_sol == "13C" .or. &
         elem_sol == "14C")

!# Net yield of iron.
    ejec_elem_SNIa(i_Fe) = sum(gross_ejec_SNIa, mask = elem_SNIa == "54Fe" .or. &
         elem_SNIa == "56Fe" .or. elem_SNIa == "57Fe" .or. elem_SNIa == "58Fe") &
         -ejec_tot_SNIa*Z_track/Z_sol * &
         sum(abund_sol, mask = elem_sol == "54Fe" .or. elem_sol == "56Fe" .or. &
         elem_sol == "57Fe" .or.  elem_sol == "58Fe")

!# Net yield of helium.
    ejec_elem_SNIa(i_He) = -ejec_tot_SNIa*Y_track

!# Net yield of nitrogen.
    ejec_elem_SNIa(i_N) = sum(gross_ejec_SNIa, mask = elem_SNIa == "14N" .or. &
         elem_SNIa == "15N") &
         -ejec_tot_SNIa*Z_track/Z_sol * &
         sum(abund_sol, mask = elem_sol == "14N" .or. elem_sol == "15N")

!# Net yield of neon.
    ejec_elem_SNIa(i_Ne) = sum(gross_ejec_SNIa, mask = elem_SNIa == "20Ne" .or. &
         elem_SNIa == "21Ne" .or. elem_SNIa == "22Ne") &
         -ejec_tot_SNIa*Z_track/Z_sol * &
         sum(abund_sol, mask = elem_sol == "20Ne" .or. elem_sol == "21Ne" .or. &
         elem_sol == "22Ne")

!# Net yield of magnesium.
    ejec_elem_SNIa(i_Mg) = sum(gross_ejec_SNIa, mask = elem_SNIa == "24Mg" .or. &
         elem_SNIa == "25Mg" .or. elem_SNIa == "26Mg") &
         -ejec_tot_SNIa*Z_track/Z_sol * &
         sum(abund_sol, mask = elem_sol == "24Mg" .or. elem_sol == "25Mg" .or. &
         elem_sol == "26Mg")

!# Net yield of silicon.
    ejec_elem_SNIa(i_Si) = sum(gross_ejec_SNIa, mask = elem_SNIa == "28Si" .or. &
         elem_SNIa == "29Si" .or. elem_SNIa == "30Si") &
         -ejec_tot_SNIa*Z_track/Z_sol * &
         sum(abund_sol, mask = elem_sol == "28Si" .or. elem_sol == "29Si" .or. &
         elem_sol == "30Si")

!# Net yield of sulfur.
    ejec_elem_SNIa(i_S) = sum(gross_ejec_SNIa, mask = elem_SNIa == "32S" .or. &
         elem_SNIa == "33S" .or. elem_SNIa == "34S" .or. elem_SNIa == "36S") &
         -ejec_tot_SNIa*Z_track/Z_sol * &
         sum(abund_sol, mask = elem_sol == "32S" .or.  elem_sol == "33S" .or.  &
         elem_sol == "34S" .or.  elem_sol == "36S")

!# Net yield of calcium.
    ejec_elem_SNIa(i_Ca) = sum(gross_ejec_SNIa, mask = elem_SNIa == "40Ca" .or. &
         elem_SNIa == "42Ca" .or. elem_SNIa == "43Ca" &
         .or. elem_SNIa == "44Ca" .or. elem_SNIa == "46Ca" .or. &
         elem_SNIa == "48Ca") &
         -ejec_tot_SNIa*Z_track/Z_sol * &
         sum(abund_sol, mask = elem_sol == "40Ca" .or. elem_sol == "42Ca" .or. &
         elem_sol == "43Ca" .or. elem_sol == "44Ca" .or. elem_sol == "46Ca" .or. &
         elem_sol == "48Ca")

!# Gross yield of dust.
!# No CO is formed: all the carbon, magnesium, silicon, sulfur, calcium and iron atoms may be used to form dust.
!# Note that hydrogen atoms in carbon dust are neglected.
!# To each magnesium, silicon, sulfur, calcium, titanium (for Woosley and Weaver yields only), or iron atom is associated
!# one oxygen atom, in the mean. It is assumed that the number of oxygen atoms is sufficient for that.
!# The real quantity of carbon or silicate dust formed around type Ia supernovae is
!# determined by `SNIa_carb_deplet` and `SNIa_sil_deplet`.

    carb_dust_SNIa = sum(gross_ejec_SNIa, mask = elem_SNIa == "12C" .or. &
         elem_SNIa == "13C" .or. elem_SNIa == "14C")

    sil_dust_SNIa = sum(gross_ejec_SNIa, mask = elem_SNIa == "24Mg" .or. &
         elem_SNIa == "25Mg" .or. elem_SNIa == "26Mg") &
         + sum(gross_ejec_SNIa, mask = elem_SNIa == "28Si" .or. &
         elem_SNIa == "29Si" .or. elem_SNIa == "30Si") &
         + sum(gross_ejec_SNIa, mask = elem_SNIa == "32S" .or. &
         elem_SNIa == "33S" .or. elem_SNIa == "34S" .or. elem_SNIa == "36S") &
         + sum(gross_ejec_SNIa, mask = elem_SNIa == "40Ca" .or. &
         elem_SNIa == "42Ca" .or.  elem_SNIa == "43Ca" .or.  &
         elem_SNIa == "44Ca" .or.  elem_SNIa == "46Ca" .or.  &
         elem_SNIa == "48Ca") &
         + sum(gross_ejec_SNIa, mask = elem_SNIa == "54Fe" .or. &
         elem_SNIa == "56Fe" .or. elem_SNIa == "57Fe" .or. &
         elem_SNIa == "58Fe")

    O_dust_SNIa = sum(gross_ejec_SNIa, mask = elem_SNIa == "24Mg" .or. &
         elem_SNIa == "25Mg" .or. elem_SNIa == "26Mg")*A_O16/A_Mg24 &
         + sum(gross_ejec_SNIa, mask = elem_SNIa == "28Si" .or. &
         elem_SNIa == "29Si" .or. elem_SNIa == "30Si")*A_O16/A_Si28 &
         + sum(gross_ejec_SNIa, mask = elem_SNIa == "32S" .or. &
         elem_SNIa == "33S" .or. elem_SNIa == "34S" .or. elem_SNIa == "36S") &
         *A_O16/A_S32 &
         + sum(gross_ejec_SNIa, mask = elem_SNIa == "40Ca" .or. &
         elem_SNIa == "42Ca" .or.  elem_SNIa == "43Ca" .or.  &
         elem_SNIa == "44Ca" .or.  elem_SNIa == "46Ca" .or.  &
         elem_SNIa == "48Ca")*A_O16/A_Ca40 &
         + sum(gross_ejec_SNIa, mask = elem_SNIa == "54Fe" .or. &
         elem_SNIa == "56Fe" .or. elem_SNIa == "57Fe" .or. &
         elem_SNIa == "58Fe")*A_O16/A_Fe56

  end subroutine compute_yields

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

  function fn_IRA_yield(IMF_file, IMF_dim_slope, IMF_bin_coeff, IMF_bin_bottom_mass, IMF_bin_slope, &
       IMF_mass_min, IMF_mass_max, dim_mass_yields, mass_yields, ejec_tot, ejec_Z, IMF_norm)

    use mod_types
    use mod_interp, only : bracket, interp_lin_lin
    use mod_IMF, only : IMF_d_n
    use mod_SSPs_constants, only : d_l10_m_ejec
    
    implicit none
    character(len=*), intent(in) :: IMF_file
    integer, intent(in) :: IMF_dim_slope, dim_mass_yields
    real(DPR), dimension(:), intent(in) :: IMF_bin_coeff, IMF_bin_bottom_mass, IMF_bin_slope, mass_yields, ejec_tot, ejec_Z
    real(DPR), intent(in) :: IMF_mass_min, IMF_mass_max
    real(DPR), intent(in) :: IMF_norm
    real(DPR) :: fn_IRA_yield
!#......................................................................
    real(DPR) :: IRA_tot_ejec, IRA_Z_ejec, l10_mass_min, l10_mass_max, d_l10_mass, l10_mass, d_n
    integer :: n_bins, i_bin, i_bracket
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    IRA_tot_ejec = 0
    IRA_Z_ejec = 0
    l10_mass_min = log10(IMF_mass_min)
    l10_mass_max = log10(IMF_mass_max)
    n_bins = int((l10_mass_max-l10_mass_min)/d_l10_m_ejec+1)
    d_l10_mass = (l10_mass_max-l10_mass_min)/n_bins
    do i_bin = 0, n_bins-1
       l10_mass = l10_mass_min+(i_bin+0.5_DPR)*d_l10_mass
       d_n = IMF_d_n(l10_mass, d_l10_mass, IMF_file, IMF_dim_slope, IMF_bin_coeff, IMF_bin_bottom_mass, IMF_bin_slope, &
            IMF_mass_min, IMF_mass_max, IMF_norm)
       if (10**l10_mass >= mass_yields(1)) then
          i_bracket = 0
          call bracket(dim_mass_yields, mass_yields, 10**l10_mass, i_bracket)
          IRA_tot_ejec = IRA_tot_ejec + d_n * interp_lin_lin( &
               mass_yields(i_bracket), mass_yields(i_bracket+1), &
               ejec_tot(i_bracket), ejec_tot(i_bracket+1), 10**l10_mass)
          IRA_Z_ejec = IRA_Z_ejec + d_n * interp_lin_lin( &
               mass_yields(i_bracket), mass_yields(i_bracket+1), &
               ejec_Z(i_bracket), ejec_Z(i_bracket+1), 10**l10_mass)
       endif
    end do
    fn_IRA_yield = IRA_Z_ejec/(1-IRA_tot_ejec)

  end function fn_IRA_yield

end module mod_yields
