LCOV - code coverage report
Current view: top level - star/private - pulse_saio.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 112 0
Test Date: 2025-05-08 18:23:42 Functions: 0.0 % 4 0

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2010-2019  The MESA Team
       4              : !
       5              : !   This program is free software: you can redistribute it and/or modify
       6              : !   it under the terms of the GNU Lesser General Public License
       7              : !   as published by the Free Software Foundation,
       8              : !   either version 3 of the License, or (at your option) any later version.
       9              : !
      10              : !   This program is distributed in the hope that it will be useful,
      11              : !   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              : !   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13              : !   See the GNU Lesser General Public License for more details.
      14              : !
      15              : !   You should have received a copy of the GNU Lesser General Public License
      16              : !   along with this program. If not, see <https://www.gnu.org/licenses/>.
      17              : !
      18              : ! ***********************************************************************
      19              : 
      20              : module pulse_saio
      21              : 
      22              :   use star_private_def
      23              :   use const_def, only: dp, pi, lsun, rsun, clight, crad
      24              :   use utils_lib
      25              :   use atm_def
      26              :   use atm_support
      27              :   use pulse_utils
      28              : 
      29              :   implicit none
      30              : 
      31              :   private
      32              :   public :: get_saio_data
      33              :   public :: write_saio_data
      34              : 
      35              : contains
      36              : 
      37            0 :   subroutine get_saio_data (id, &
      38              :        keep_surface_point, add_atmosphere, global_data, point_data, ierr)
      39              : 
      40              :     integer, intent(in)                :: id
      41              :     logical, intent(in)                :: keep_surface_point
      42              :     logical, intent(in)                :: add_atmosphere
      43              :     real(dp), allocatable, intent(out) :: global_data(:)
      44              :     real(dp), allocatable, intent(out) :: point_data(:,:)
      45              :     integer, intent(out)               :: ierr
      46              : 
      47              :     type(star_info), pointer :: s
      48            0 :     integer, allocatable     :: k_a(:)
      49            0 :     integer, allocatable     :: k_b(:)
      50              :     integer                  :: n_sg
      51              :     integer                  :: n_atm
      52              :     integer                  :: nn_atm
      53              :     integer                  :: n_env
      54              :     integer                  :: nn_env
      55              :     integer                  :: nn
      56            0 :     real(dp)                 :: r_outer
      57            0 :     real(dp)                 :: m_outer
      58              :     integer                  :: j
      59              :     integer                  :: k
      60              :     integer                  :: sg
      61              : 
      62              :     ! Get SAIO data
      63              : 
      64            0 :     call get_star_ptr(id, s, ierr)
      65            0 :     if (ierr /= 0) then
      66            0 :        write(*,*) 'bad star id for get_saio_data'
      67            0 :        return
      68              :     end if
      69              : 
      70              :     ! Set up segment indices
      71              : 
      72            0 :     call set_segment_indices(s, k_a, k_b, .FALSE.)
      73              : 
      74            0 :     n_sg = SIZE(k_a)
      75              : 
      76              :     ! Determine data dimensions
      77              : 
      78            0 :     if (add_atmosphere) then
      79            0 :        call build_atm(s, s%L(1), s%r(1), s%Teff, s%m_grav(1), s%cgrav(1), ierr)
      80            0 :        if (ierr /= 0) then
      81            0 :           write(*,*) 'failed in build_atm'
      82            0 :           return
      83              :        end if
      84            0 :        n_atm = s%atm_structure_num_pts
      85            0 :        nn_atm = n_atm - 1
      86              :     else
      87              :        n_atm = 0
      88              :        nn_atm = 0
      89              :     end if
      90              : 
      91            0 :     n_env = s%nz
      92              : 
      93            0 :     if (keep_surface_point) then
      94            0 :        nn_env = n_env + n_sg - 1
      95              :     else
      96            0 :        nn_env = n_env - 1 + n_sg - 1
      97              :     end if
      98              : 
      99            0 :     nn = nn_env + nn_atm
     100              : 
     101              :     ! Store global data
     102              : 
     103            0 :     allocate(global_data(4))
     104              : 
     105            0 :     r_outer = Rsun*s%photosphere_r
     106            0 :     m_outer = s%m_grav(1)
     107              : 
     108            0 :     global_data(1) = m_outer
     109            0 :     global_data(2) = log10(s%L(1)/Lsun)
     110            0 :     global_data(3) = log10(r_outer/Rsun)
     111            0 :     global_data(4) = s%star_age
     112              : 
     113              :     ! Store point data
     114              : 
     115            0 :     allocate(point_data(20,nn))
     116              : 
     117            0 :     j = 1
     118              : 
     119              :     ! Atmosphere (we skip the point at the base of the atm to
     120              :     ! smooth the transition)
     121              : 
     122            0 :     atm_loop : do k = 1, n_atm-1
     123            0 :        call store_saio_data_atm(j, k, k_a(1), k_b(1))
     124            0 :        j = j + 1
     125              :     end do atm_loop
     126              : 
     127              :     ! Envelope
     128              : 
     129            0 :     sg = 1
     130              : 
     131            0 :     env_loop : do k = 1, n_env
     132              : 
     133            0 :        if (k == 1 .AND. .NOT. keep_surface_point) cycle env_loop
     134              : 
     135            0 :        call store_saio_data_env(j, k, k_a(sg), k_b(sg))
     136            0 :        j = j + 1
     137              : 
     138            0 :        if (k == k_b(sg)+1) then
     139              : 
     140            0 :           sg = sg + 1
     141              : 
     142            0 :           call store_saio_data_env(j, k, k_a(sg), k_b(sg))
     143            0 :           j = j + 1
     144              : 
     145              :        end if
     146              : 
     147              :     end do env_loop
     148              : 
     149              :     ! Reverse the data ordering (SAIO format is center-to-surface)
     150              : 
     151            0 :     point_data = point_data(:,nn:1:-1)
     152              : 
     153              :     ! Tidy up
     154              : 
     155            0 :     if (ASSOCIATED(s%atm_structure)) then
     156            0 :        deallocate(s%atm_structure)
     157              :     end if
     158              : 
     159            0 :     return
     160              : 
     161              :   contains
     162              : 
     163            0 :     subroutine store_saio_data_atm (j, k, k_a, k_b)
     164              : 
     165              :       integer, intent(in) :: j
     166              :       integer, intent(in) :: k
     167              :       integer, intent(in) :: k_a
     168              :       integer, intent(in) :: k_b
     169              : 
     170              :       ! Store data associated with atmosphere point k into the
     171              :       ! point_data array at position j
     172              : 
     173              :       associate ( &
     174              :            r => point_data(1,j), &
     175              :            m => point_data(2,j), &
     176              :            Lrad => point_data(3,j), &
     177              :            T => point_data(4,j), &
     178              :            rho => point_data(5,j), &
     179              :            P => point_data(6,j), &
     180              :            eps => point_data(7,j), &
     181              :            kap => point_data(8,j), &
     182              :            c_V => point_data(9,j), &
     183              :            chi_rho => point_data(10,j), &
     184              :            chi_T => point_data(11,j), &
     185              :            eps_rho => point_data(12,j), &
     186              :            eps_T => point_data(13,j), &
     187              :            kap_rho => point_data(14,j), &
     188              :            kap_T => point_data(15,j), &
     189              :            nabla => point_data(16,j), &
     190              :            nabla_ad => point_data(17,j), &
     191              :            X => point_data(18,j), &
     192              :            Y => point_data(19,j), &
     193              :            L => point_data(20,j))
     194              : 
     195            0 :         r = s% r(1) + s% atm_structure(atm_delta_r,k)
     196            0 :         m = s% m_grav(1)
     197            0 :         T = exp(s% atm_structure(atm_lnT,k))
     198            0 :         rho = exp(s% atm_structure(atm_lnd,k))
     199            0 :         P = exp(s% atm_structure(atm_lnP,k))
     200            0 :         eps = 0d0
     201            0 :         kap = s% atm_structure(atm_kap,k)
     202            0 :         c_V = s% atm_structure(atm_cv,k)
     203            0 :         chi_rho = s% atm_structure(atm_chiRho,k)
     204            0 :         chi_T = s% atm_structure(atm_chiT,k)
     205            0 :         eps_rho = 0d0
     206            0 :         eps_T = 0d0
     207            0 :         kap_rho = s% atm_structure(atm_dlnkap_dlnd,k)
     208            0 :         kap_T = s% atm_structure(atm_dlnkap_dlnT,k)
     209            0 :         nabla = s% atm_structure(atm_gradT,k)
     210            0 :         nabla_ad = s% atm_structure(atm_grada,k)
     211            0 :         X = eval_face(s%dq, s%X, 1, k_a, k_b, v_lo=0d0, v_hi=1d0)
     212            0 :         Y = eval_face(s%dq, s%Y, 1, k_a, k_b, v_lo=0d0, v_hi=1d0)
     213            0 :         L = s% L(1)
     214              : 
     215            0 :         if (s%atm_structure(atm_tau,k) >= 2d0/3d0) then
     216            0 :            Lrad = (16*pi*clight*crad*s%cgrav(k)*m*T*T*T*T*nabla)/(3*P*kap)
     217              :         else
     218            0 :            Lrad = L
     219              :         end if
     220              : 
     221              :       end associate
     222              : 
     223            0 :       return
     224              : 
     225              :     end subroutine store_saio_data_atm
     226              : 
     227              : 
     228            0 :     subroutine store_saio_data_env (j, k, k_a, k_b)
     229              : 
     230              :       integer, intent(in) :: j
     231              :       integer, intent(in) :: k
     232              :       integer, intent(in) :: k_a
     233              :       integer, intent(in) :: k_b
     234              : 
     235              :       ! Store data for envelope face k into the point_data array at
     236              :       ! position j
     237              : 
     238              :       associate ( &
     239              :            r => point_data(1,j), &
     240              :            m => point_data(2,j), &
     241              :            Lrad => point_data(3,j), &
     242              :            T => point_data(4,j), &
     243              :            rho => point_data(5,j), &
     244              :            P => point_data(6,j), &
     245              :            eps => point_data(7,j), &
     246              :            kap => point_data(8,j), &
     247              :            c_V => point_data(9,j), &
     248              :            chi_rho => point_data(10,j), &
     249              :            chi_T => point_data(11,j), &
     250              :            eps_rho => point_data(12,j), &
     251              :            eps_T => point_data(13,j), &
     252              :            kap_rho => point_data(14,j), &
     253              :            kap_T => point_data(15,j), &
     254              :            nabla => point_data(16,j), &
     255              :            nabla_ad => point_data(17,j), &
     256              :            X => point_data(18,j), &
     257              :            Y => point_data(19,j), &
     258              :            L => point_data(20,j))
     259              : 
     260            0 :         r = s%r(k)
     261            0 :         m = s%m_grav(k)
     262            0 :         T = eval_face(s%dq, s%T, k, 1, s%nz)
     263            0 :         if (s%interpolate_rho_for_pulse_data) then
     264            0 :            rho = eval_face(s%dq, s%rho, k, k_a, k_b)
     265              :         else
     266            0 :            rho = eval_face_rho(s, k, k_a, k_b)
     267              :         end if
     268            0 :         P = eval_face(s%dq, s%Peos, k, 1, s%nz)
     269            0 :         eps = eval_face(s%dq, s%eps_nuc, k, k_a, k_b) + eval_face(s%dq, s%eps_grav_ad%val, k, k_a, k_b)
     270            0 :         c_V = eval_face(s%dq, s%Cv, k, k_a, k_b)
     271            0 :         chi_rho = eval_face(s%dq, s%chiRho, k, k_a, k_b)
     272            0 :         chi_T = eval_face(s%dq, s%chiT, k, k_a, k_b)
     273            0 :         eps_rho = eval_face(s%dq, s%d_epsnuc_dlnd, k, k_a, k_b)
     274            0 :         eps_T = eval_face(s%dq, s%d_epsnuc_dlnT, k, k_a, k_b)
     275            0 :         kap_rho = eval_face(s%dq, s%d_opacity_dlnd, k, k_a, k_b)/kap
     276            0 :         kap_T = eval_face(s%dq, s%d_opacity_dlnT, k, k_a, k_b)/kap
     277            0 :         nabla = s%gradT(k)  ! Not quite right; gradT can be discontinuous
     278            0 :         nabla_ad = eval_face(s%dq, s%grada, k, k_a, k_b)
     279            0 :         X = eval_face(s%dq, s%X, k, k_a, k_b, v_lo=0d0, v_hi=1d0)
     280            0 :         Y = eval_face(s%dq, s%Y, k, k_a, k_b, v_lo=0d0, v_hi=1d0)
     281            0 :         L = s%L(k)
     282              : 
     283            0 :         if (s%tau(k) >= 2d0/3d0) then
     284            0 :            Lrad = (16*pi*clight*crad*s%cgrav(k)*m*T*T*T*T*nabla)/(3*P*kap)
     285              :         else
     286            0 :            Lrad = L
     287              :         end if
     288              : 
     289              :       end associate
     290              : 
     291            0 :       return
     292              : 
     293              :     end subroutine store_saio_data_env
     294              : 
     295              :   end subroutine get_saio_data
     296              : 
     297              : 
     298            0 :   subroutine write_saio_data (id, filename, global_data, point_data, ierr)
     299              : 
     300              :     integer, intent(in)      :: id
     301              :     character(*), intent(in) :: filename
     302              :     real(dp), intent(in)     :: global_data(:)
     303              :     real(dp), intent(in)     :: point_data(:,:)
     304              :     integer, intent(out)     :: ierr
     305              : 
     306              :     type(star_info), pointer :: s
     307              :     integer                  :: iounit
     308              :     integer                  :: nn
     309              :     integer                  :: j
     310              : 
     311              :     ! Write SAIO data to file
     312              : 
     313            0 :     call get_star_ptr(id, s, ierr)
     314            0 :     if (ierr /= 0) then
     315            0 :        write(*,*) 'bad star id for get_fgong_info'
     316            0 :        return
     317              :     end if
     318              : 
     319              :     ! Open the file
     320              : 
     321            0 :     open(newunit=iounit, file=TRIM(filename), status='REPLACE', iostat=ierr)
     322            0 :     if (ierr /= 0) then
     323            0 :        write(*,*) 'failed to open '//TRIM(filename)
     324            0 :        return
     325              :     end if
     326              : 
     327              :     ! Write the data
     328              : 
     329            0 :     nn = SIZE(point_data, 2)
     330              : 
     331            0 :     write(iounit, 100) nn, global_data
     332              : 100 format(I6,99(1PE16.9))
     333              : 
     334            0 :     do j = 1, nn
     335            0 :        write(iounit, 110) point_data(:,j)
     336              : 110    format(5(1PE16.9))
     337              :     end do
     338              : 
     339              :     ! Close the file
     340              : 
     341            0 :     close(iounit)
     342              : 
     343            0 :     return
     344              : 
     345              :   end subroutine write_saio_data
     346              : 
     347              : end module pulse_saio
        

Generated by: LCOV version 2.0-1