! Module   : make_bb_photgrid
! Purpose  : create a blackbody/bolometric photgrid file
!
! Copyright 2021 Rich Townsend & The MSG Team
!
! This file is part of MSG. MSG is free software: you can redistribute
! it and/or modify it under the terms of the GNU General Public
! License as published by the Free Software Foundation, version 3.
!
! MSG is distributed in the hope that it will be useful, but WITHOUT
! ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
! License for more details.
!
! You should have received a copy of the GNU General Public License
! along with this program.  If not, see <http://www.gnu.org/licenses/>.

#:include 'forum.inc'

program make_bb_photgrid

   ! Uses

   use forum_m
   use msg_m

   use ISO_FORTRAN_ENV

   ! No implicit typing

   implicit none

   ! Variables

   real(RD)                  :: Teff_min
   real(RD)                  :: Teff_max
   integer                   :: n_Teff
   real(RD)                  :: logg_min
   real(RD)                  :: logg_max
   integer                   :: n_logg
   integer                   :: n_mu
   real(RD)                  :: u
   character(:), allocatable :: law_str
   character(:), allocatable :: photgrid_file_name
   real(RD)                  :: lambda

   integer                           :: n
   real(RD), allocatable             :: x_vecs(:,:)
   integer                           :: i
   integer                           :: i_Teff
   integer                           :: i_logg
   real(RD)                          :: logT
   real(RD)                          :: logg
   type(vgrid_t)                     :: vgrid
   type(limb_t)                      :: limb
   real(RD), allocatable             :: mu(:)
   real(RD), allocatable             :: f_mu(:)
   type(limb_photint_t), allocatable :: photints(:)
   type(mem_photsource_t)            :: photsource
   type(photgrid_t)                  :: photgrid
   type(hdf5io_t)                    :: hdf5io

   ! Read command-line arguments

   @:ASSERT(n_arg() == 10 .OR. n_arg() == 11, 'Syntax: make_bb_photgrid Teff_min Teff_max n_Teff logg_min logg_max n_logg n_mu u law_str photgrid_file_name [lambda/A]')

   call get_arg(1, Teff_min)
   call get_arg(2, Teff_max)
   call get_arg(3, n_Teff)

   call get_arg(4, logg_min)
   call get_arg(5, logg_max)
   call get_arg(6, n_logg)

   call get_arg(7, n_mu)
   call get_arg(8, u)
   call get_arg(9, law_str)

   call get_arg(10, photgrid_file_name)

   if (n_arg() == 11) then
      call get_arg(11, lambda)
   else
      lambda = 0._RD
   end if

   ! Create the vertex coordinates

   n = n_Teff*n_logg

   allocate(x_vecs(2,n))

   i = 1

   do i_Teff = 1, n_Teff

      logT = (LOG10(Teff_min)*(n_Teff-i_Teff) + LOG10(Teff_max)*(i_Teff-1))/(n_Teff-1)

      do i_logg = 1, n_logg

         logg = (logg_min*(n_logg-i_logg) + logg_max*(i_logg-1))/(n_logg-1)

         x_vecs(1,i) = logT
         x_vecs(2,i) = logg

         i = i + 1

      end do

   end do
         
   ! Create vgrid

   vgrid = vgrid_t(x_vecs, ['logT', 'logg'])

   ! Set up limb-darkening stuff

   limb = limb_t(law_str)

   mu = [(REAL(i-1, RD)/(n_mu-1),i=1,n_mu)]
   f_mu = (1._RD - u*(1._RD - mu))/(1._RD - u/3._RD)

   ! Create photints

   allocate(photints(n))

   call vgrid%map(make_photint)

   ! Create photsource

   photsource = mem_photsource_t(photints)

   ! Create photgrid

   photgrid = photgrid_t(photsource, vgrid)

   ! Write it

   hdf5io = hdf5io_t(photgrid_file_name, CREATE_FILE)
   call photgrid%write(hdf5io)
   call hdf5io%final()

   ! Finish

contains

   subroutine make_photint (v_seq, stat)

      integer, intent(in)            :: v_seq
      integer, intent(out), optional :: stat

      real(RD) :: Teff
      real(RD) :: I(n_mu)

      ! Create intensity data

      Teff = 10**x_vecs(1,v_seq)

      if (lambda > 0._RD) then
         associate (lambda => lambda*1E-8_RD)
           I = 2._RD*H_PLANCK*C_LIGHT**2/lambda**5/ &
                (EXP(H_PLANCK*C_LIGHT/(lambda*K_BOLTZMANN*Teff)) - 1._RD) * f_mu
         end associate
      else
         I = (SIGMA_STEFAN/PI)*Teff**4 * f_mu
      endif

      ! Construct the photint_t

      photints(v_seq) = limb_photint_t(I, mu, limb)

      ! Finish

      if (PRESENT(stat)) stat = STAT_OK

      return

   end subroutine make_photint

end program make_bb_photgrid
