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

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2010-2018  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_gyre
      21              : 
      22              :   use star_private_def
      23              :   use const_def, only: dp, pi, four_thirds, rsun
      24              :   use utils_lib
      25              :   use atm_def
      26              :   use atm_support
      27              :   use eps_grav
      28              :   use pulse_utils
      29              : 
      30              :   implicit none
      31              : 
      32              :   private
      33              :   public :: get_gyre_data
      34              :   public :: write_gyre_data
      35              : 
      36              : contains
      37              : 
      38            0 :   subroutine get_gyre_data (id, &
      39              :        add_center_point, keep_surface_point, add_atmosphere, global_data, point_data, ierr)
      40              : 
      41              :     integer, intent(in)                        :: id
      42              :     logical, intent(in)                        :: add_center_point
      43              :     logical, intent(in)                        :: keep_surface_point
      44              :     logical, intent(in)                        :: add_atmosphere
      45              :     real(dp), allocatable, intent(out)         :: global_data(:)
      46              :     real(dp), allocatable, target, intent(out) :: point_data(:,:)
      47              :     integer, intent(out)                       :: ierr
      48              : 
      49              :     type(star_info), pointer :: s
      50            0 :     integer, allocatable     :: k_a(:)
      51            0 :     integer, allocatable     :: k_b(:)
      52              :     integer                  :: n_sg
      53              :     integer                  :: n_atm
      54              :     integer                  :: nn_atm
      55              :     integer                  :: n_env
      56              :     integer                  :: nn_env
      57              :     integer                  :: nn
      58              :     real(dp), pointer        :: r(:) => NULL()
      59              :     real(dp), pointer        :: m(:) => NULL()
      60              :     real(dp), pointer        :: L(:) => NULL()
      61              :     real(dp), pointer        :: P(:) => NULL()
      62              :     real(dp), pointer        :: T(:) => NULL()
      63              :     real(dp), pointer        :: rho(:) => NULL()
      64              :     real(dp), pointer        :: nabla(:) => NULL()
      65              :     real(dp), pointer        :: N2(:) => NULL()
      66              :     real(dp), pointer        :: Gamma_1(:) => NULL()
      67              :     real(dp), pointer        :: nabla_ad(:) => NULL()
      68              :     real(dp), pointer        :: delta(:) => NULL()
      69              :     real(dp), pointer        :: kap(:) => NULL()
      70              :     real(dp), pointer        :: kap_kap_T(:) => NULL()
      71              :     real(dp), pointer        :: kap_kap_rho(:) => NULL()
      72              :     real(dp), pointer        :: eps_nuc(:) => NULL()
      73              :     real(dp), pointer        :: eps_eps_T(:) => NULL()
      74              :     real(dp), pointer        :: eps_eps_rho(:) => NULL()
      75              :     real(dp), pointer        :: eps_grav(:) => NULL()
      76              :     real(dp), pointer        :: Omega_rot(:) => NULL()
      77            0 :     real(dp)                 :: r_outer
      78            0 :     real(dp)                 :: m_outer
      79              :     integer                  :: j
      80              :     integer                  :: k
      81              :     integer                  :: sg
      82              : 
      83              :     ! Get model data for GYRE output
      84              : 
      85            0 :     call get_star_ptr(id, s, ierr)
      86            0 :     if (ierr /= 0) then
      87            0 :        write(*,*) 'bad star id for get_gyre_data'
      88            0 :        return
      89              :     end if
      90              : 
      91              :     ! Set up segment indices
      92              : 
      93              :     call set_segment_indices(s, k_a, k_b, add_center_point)
      94              : 
      95            0 :     n_sg = SIZE(k_a)
      96              : 
      97              :     ! Determine data dimensions
      98              : 
      99            0 :     if (add_atmosphere) then
     100            0 :        call build_atm(s, s%L(1), s%r(1), s%Teff, s%m_grav(1), s%cgrav(1), ierr)
     101            0 :        if (ierr /= 0) then
     102            0 :           write(*,*) 'failed in build_atm'
     103            0 :           return
     104              :        end if
     105            0 :        n_atm = s%atm_structure_num_pts
     106            0 :        nn_atm = n_atm - 1
     107              :     else
     108              :        n_atm = 0
     109              :        nn_atm = 0
     110              :     end if
     111              : 
     112            0 :     n_env = s%nz
     113              : 
     114            0 :     if (keep_surface_point) then
     115            0 :        nn_env = n_env + n_sg - 1
     116              :     else
     117            0 :        nn_env = n_env - 1 + n_sg - 1
     118              :     end if
     119              : 
     120            0 :     if (add_center_point) then
     121            0 :        nn = nn_env + nn_atm + 1
     122              :     else
     123            0 :        nn = nn_env + nn_atm
     124              :     end if
     125              : 
     126              :     ! Allocate arrays & set up data pointers
     127              : 
     128            0 :     allocate(global_data(3))
     129              : 
     130              :     ! Set up data pointers
     131              : 
     132            0 :     select case(s%gyre_data_schema)
     133              : 
     134              :     case(101,110)
     135              : 
     136            0 :        allocate(point_data(18,nn))
     137              : 
     138            0 :        r => point_data(1,:)
     139            0 :        m => point_data(2,:)
     140            0 :        L => point_data(3,:)
     141            0 :        P => point_data(4,:)
     142            0 :        T => point_data(5,:)
     143            0 :        rho => point_data(6,:)
     144            0 :        nabla => point_data(7,:)
     145            0 :        N2 => point_data(8,:)
     146            0 :        Gamma_1 => point_data(9,:)
     147            0 :        nabla_ad => point_data(10,:)
     148            0 :        delta => point_data(11,:)
     149            0 :        kap => point_data(12,:)
     150            0 :        kap_kap_T => point_data(13,:)
     151            0 :        kap_kap_rho => point_data(14,:)
     152            0 :        eps_nuc => point_data(15,:)
     153            0 :        eps_eps_T => point_data(16,:)
     154            0 :        eps_eps_rho => point_data(17,:)
     155            0 :        Omega_rot => point_data(18,:)
     156              : 
     157              :     case(120)
     158              : 
     159            0 :        allocate(point_data(19,nn))
     160              : 
     161            0 :        r => point_data(1,:)
     162            0 :        m => point_data(2,:)
     163            0 :        L => point_data(3,:)
     164            0 :        P => point_data(4,:)
     165            0 :        T => point_data(5,:)
     166            0 :        rho => point_data(6,:)
     167            0 :        nabla => point_data(7,:)
     168            0 :        N2 => point_data(8,:)
     169            0 :        Gamma_1 => point_data(9,:)
     170            0 :        nabla_ad => point_data(10,:)
     171            0 :        delta => point_data(11,:)
     172            0 :        kap => point_data(12,:)
     173            0 :        kap_kap_T => point_data(13,:)
     174            0 :        kap_kap_rho => point_data(14,:)
     175            0 :        eps_nuc => point_data(15,:)
     176            0 :        eps_eps_T => point_data(16,:)
     177            0 :        eps_eps_rho => point_data(17,:)
     178            0 :        eps_grav => point_data(18,:)
     179            0 :        Omega_rot => point_data(19,:)
     180              : 
     181              :     case default
     182              : 
     183            0 :        write(*,*) 'invalid gyre_data_schema'
     184            0 :        ierr = -1
     185            0 :        return
     186              : 
     187              :     end select
     188              : 
     189              :     ! If necessary, update the eps_grav data in the model
     190              : 
     191            0 :     if (ASSOCIATED(eps_grav)) then
     192              : 
     193            0 :        do k = 1, s%nz
     194            0 :           call eval_eps_grav_and_partials(s, k, ierr)
     195            0 :           if (ierr /= 0) then
     196            0 :              write(*,*) 'failed in call to eval_eps_grav_and_partials'
     197            0 :              return
     198              :           end if
     199              :        end do
     200              : 
     201              :     end if
     202              : 
     203              :     ! Store global data
     204              : 
     205            0 :     r_outer = Rsun*s%photosphere_r
     206            0 :     m_outer = s%m_grav(1)
     207              : 
     208            0 :     global_data(1) = m_outer
     209            0 :     global_data(2) = r_outer
     210            0 :     global_data(3) = s%L(1)
     211              : 
     212              :     ! Store point data
     213              : 
     214            0 :     j = 1
     215              : 
     216              :     ! Atmosphere (we skip the point at the base of the atm to smooth
     217              :     ! the transition)
     218              : 
     219            0 :     atm_loop : do k = 1, n_atm-1
     220            0 :        call store_point_data_atm(j, k)
     221            0 :        j = j + 1
     222              :     end do atm_loop
     223              : 
     224              :     ! Envelope
     225              : 
     226            0 :     sg = 1
     227              : 
     228            0 :     env_loop : do k = 1, n_env
     229              : 
     230            0 :        if (k == 1 .AND. .NOT. keep_surface_point) cycle env_loop
     231              : 
     232            0 :        call store_point_data_env(j, k, k_a(sg), k_b(sg))
     233            0 :        j = j + 1
     234              : 
     235            0 :        if (k == k_b(sg)+1) then
     236              : 
     237            0 :           sg = sg + 1
     238              : 
     239            0 :           call store_point_data_env(j, k, k_a(sg), k_b(sg))
     240            0 :           j = j + 1
     241              : 
     242              :        end if
     243              : 
     244              :     end do env_loop
     245              : 
     246              :     ! Center
     247              : 
     248            0 :     if (add_center_point) then
     249            0 :        call store_point_data_ctr(j, k_a(n_sg), k_b(n_sg))
     250            0 :        j = j + 1
     251              :     end if
     252              : 
     253              :     ! Check that all point data has correctly been calculated
     254              : 
     255            0 :     if (j /= nn+1) call mesa_error(__FILE__,__LINE__,'Invalid cell index in get_gyre_data')
     256              : 
     257              :     ! Reverse the data ordering (GYRE format is center-to-surface)
     258              : 
     259            0 :     point_data = point_data(:,nn:1:-1)
     260              : 
     261              :     ! Tidy up
     262              : 
     263            0 :     if (ASSOCIATED(s%atm_structure)) then
     264            0 :        deallocate(s%atm_structure)
     265              :     end if
     266              : 
     267            0 :     return
     268              : 
     269              :   contains
     270              : 
     271            0 :     subroutine store_point_data_atm (j, k)
     272              : 
     273              :       integer, intent(in) :: j
     274              :       integer, intent(in) :: k
     275              : 
     276            0 :       real(dp) :: grav
     277              : 
     278              :       ! Store data associated with atmosphere point k into the
     279              :       ! point_data array at position j
     280              : 
     281            0 :       r(j) = s%r(1) + s%atm_structure(atm_delta_r,k)
     282            0 :       m(j) = s%m_grav(1)  !+ s%atm_structure(atm_delta_m,k)
     283            0 :       L(j) = s%L(1)
     284              : 
     285            0 :       P(j) = exp(s%atm_structure(atm_lnP,k))
     286            0 :       rho(j) = exp(s%atm_structure(atm_lnd,k))
     287            0 :       T(j) = exp(s%atm_structure(atm_lnT,k))
     288              : 
     289            0 :       Gamma_1(j) = s%atm_structure(atm_gamma1,k)
     290            0 :       nabla_ad(j) = s%atm_structure(atm_grada,k)
     291            0 :       delta(j) = s%atm_structure(atm_chiT,k)/s%atm_structure(atm_chiRho,k)
     292            0 :       nabla(j) = s%atm_structure(atm_gradT,k)
     293              : 
     294            0 :       grav = s%cgrav(1)*m(j)/(r(j)*r(j))
     295            0 :       N2(j) = grav*grav*(rho(j)/P(j))*delta(j)*(nabla_ad(j) - nabla(j))
     296              : 
     297            0 :       kap(j) = s%atm_structure(atm_kap,k)
     298            0 :       kap_kap_T(j) = kap(j)*s%atm_structure(atm_dlnkap_dlnT,k)
     299            0 :       kap_kap_rho(j) = kap(j)*s%atm_structure(atm_dlnkap_dlnd,k)
     300              : 
     301            0 :       eps_nuc(j) = 0d0
     302            0 :       eps_eps_T(j) = 0d0
     303            0 :       eps_eps_rho(j) = 0d0
     304            0 :       if (ASSOCIATED(eps_grav)) eps_grav(j) = 0d0
     305              : 
     306            0 :       if (s%rotation_flag) then
     307            0 :          Omega_rot(j) = s%omega(1)
     308              :       else
     309            0 :          Omega_rot(j) = 0d0
     310              :       end if
     311              : 
     312            0 :       return
     313              : 
     314              :     end subroutine store_point_data_atm
     315              : 
     316              : 
     317            0 :     subroutine store_point_data_env (j, k, k_a, k_b)
     318              : 
     319              :       integer, intent(in) :: j
     320              :       integer, intent(in) :: k
     321              :       integer, intent(in) :: k_a
     322              :       integer, intent(in) :: k_b
     323              : 
     324              :       ! Store data associated with envelope face k into the point_data
     325              :       ! array at position j
     326              : 
     327            0 :       r(j) = s%r(k)
     328            0 :       m(j) = s%m_grav(k)
     329            0 :       L(j) = s%L(k)
     330              : 
     331            0 :       P(j) = eval_face(s%dq, s%Peos, k, 1, s%nz)
     332            0 :       if (s%interpolate_rho_for_pulse_data) then
     333            0 :          rho(j) = eval_face(s%dq, s%rho, k, k_a, k_b)
     334              :       else
     335            0 :          rho(j) = eval_face_rho(s, k, k_a, k_b)
     336              :       end if
     337            0 :       T(j) = eval_face(s%dq, s%T, k, 1, s%nz)
     338              : 
     339            0 :       N2(j) = eval_face_A_ast(s, k, k_a, k_b)*s%grav(k)/s%r(k)
     340            0 :       Gamma_1(j) = eval_face(s%dq, s%gamma1, k, k_a, k_b)
     341            0 :       nabla_ad(j) = eval_face(s%dq, s%grada, k, k_a, k_b)
     342            0 :       delta(j) = eval_face(s%dq, s%chiT, k, k_a, k_b)/eval_face(s%dq, s%chiRho, k, k_a, k_b)
     343            0 :       nabla(j) = s%gradT(k)  ! Not quite right; gradT can be discontinuous
     344              : 
     345            0 :       kap(j) = eval_face(s%dq, s%opacity, k, k_a, k_b)
     346            0 :       kap_kap_T(j) = eval_face(s%dq, s%d_opacity_dlnT, k, k_a, k_b)
     347            0 :       kap_kap_rho(j) = eval_face(s%dq, s%d_opacity_dlnd, k, k_a, k_b)
     348              : 
     349            0 :       eps_nuc(j) = eval_face(s%dq, s%eps_nuc, k, k_a, k_b)
     350            0 :       eps_eps_T(j) = eval_face(s%dq, s%d_epsnuc_dlnT, k, k_a, k_b)
     351            0 :       eps_eps_rho(j) = eval_face(s%dq, s%d_epsnuc_dlnd, k, k_a, k_b)
     352            0 :       if (ASSOCIATED(eps_grav)) eps_grav(j) = eval_face(s%dq, s%eps_grav_ad%val, k, k_a, k_b)
     353              : 
     354            0 :       if (s%rotation_flag) then
     355            0 :          Omega_rot(j) = s%omega(k)  ! Not quite right; omega can be discontinuous
     356              :       else
     357            0 :          Omega_rot = 0d0
     358              :       end if
     359              : 
     360            0 :       return
     361              : 
     362              :     end subroutine store_point_data_env
     363              : 
     364              : 
     365            0 :     subroutine store_point_data_ctr (j, k_a, k_b)
     366              : 
     367              :       integer, intent(in) :: j
     368              :       integer, intent(in) :: k_a
     369              :       integer, intent(in) :: k_b
     370              : 
     371            0 :       real(dp) :: d2P_dr2_c
     372              : 
     373              :       ! Store data for the center into the point_data array at position j
     374              : 
     375            0 :       r(j) = 0d0
     376            0 :       m(j) = 0d0
     377            0 :       L(j) = 0d0
     378              : 
     379            0 :       P(j) = eval_center(s%rmid, s%Peos, 1, s%nz)
     380            0 :       if (s%interpolate_rho_for_pulse_data) then
     381            0 :          rho(j) = eval_center(s%rmid, s%rho, k_a, k_b)
     382              :       else
     383            0 :          rho(j) = eval_center_rho(s, k_b)
     384              :       end if
     385              :       ! at the centre d²P/dr² = -4πGρ²/3
     386            0 :       d2P_dr2_c = -four_thirds*pi*s% cgrav(s% nz)*rho(j)**2
     387            0 :       P(j) = s%Peos(s% nz) - 0.5d0*d2P_dr2_c*s% rmid(s% nz)**2
     388            0 :       T(j) = eval_center(s%rmid, s%T, 1, s%nz)
     389              : 
     390            0 :       N2(j) = 0d0
     391            0 :       Gamma_1(j) = eval_center(s%rmid, s%gamma1, k_a, k_b)
     392            0 :       nabla_ad(j) = eval_center(s%rmid, s%grada, k_a, k_b)
     393            0 :       delta(j) = eval_center(s%rmid, s%chiT, k_a, k_b)/eval_center(s%rmid, s%chiRho, k_a, k_b)
     394            0 :       nabla(j) = eval_center(s%r, s%gradT, k_a, k_b)
     395              : 
     396            0 :       kap(j) = eval_center(s%rmid, s%opacity, k_a, k_b)
     397            0 :       kap_kap_T(j) = eval_center(s%rmid, s%d_opacity_dlnT, k_a, k_b)
     398            0 :       kap_kap_rho(j) = eval_center(s%rmid, s%d_opacity_dlnd, k_a, k_b)
     399              : 
     400            0 :       eps_nuc(j) = eval_center(s%rmid, s%eps_nuc, k_a, k_b)
     401            0 :       eps_eps_T(j) = eval_center(s%rmid, s%d_epsnuc_dlnT, k_a, k_b)
     402            0 :       eps_eps_rho(j) = eval_center(s%rmid, s%d_epsnuc_dlnd, k_a, k_b)
     403            0 :       if (ASSOCIATED(eps_grav)) eps_grav(j) = eval_center(s%rmid, s%eps_grav_ad%val, k_a, k_b)
     404              : 
     405            0 :       if (s%rotation_flag) then
     406            0 :          Omega_rot(j) = eval_center(s%r, s%omega, k_a, k_b)
     407              :       else
     408            0 :          Omega_rot(j) = 0d0
     409              :       end if
     410              : 
     411              : 
     412            0 :       return
     413              : 
     414              :     end subroutine store_point_data_ctr
     415              : 
     416              :   end subroutine get_gyre_data
     417              : 
     418              : 
     419            0 :   subroutine write_gyre_data (id, filename, global_data, point_data, ierr)
     420              : 
     421              :     integer, intent(in)      :: id
     422              :     character(*), intent(in) :: filename
     423              :     real(dp), intent(in)     :: global_data(:)
     424              :     real(dp), intent(in)     :: point_data(:,:)
     425              :     integer, intent(out)     :: ierr
     426              : 
     427              :     type(star_info), pointer :: s
     428              :     integer                  :: iounit
     429              :     integer                  :: nn
     430              :     integer                  :: j
     431              : 
     432              :     ! Write GYRE data to file
     433              : 
     434            0 :     call get_star_ptr(id, s, ierr)
     435            0 :     if (ierr /= 0) then
     436            0 :        write(*,*) 'bad star id for write_gyre_data'
     437            0 :        return
     438              :     end if
     439              : 
     440            0 :     select case(s%gyre_data_schema)
     441              :     case(101,120)
     442              :     case default
     443            0 :        write(*,*) 'invalid gyre_data_schema'
     444            0 :        ierr = -1
     445            0 :        return
     446              :     end select
     447              : 
     448              :     ! Open the file
     449              : 
     450            0 :     open(newunit=iounit, file=TRIM(filename), status='REPLACE', iostat=ierr)
     451            0 :     if (ierr /= 0) then
     452            0 :        write(*,*) 'failed to open '//TRIM(filename)
     453            0 :        return
     454              :     end if
     455              : 
     456              :     ! Write the data
     457              : 
     458            0 :     nn = SIZE(point_data, 2)
     459              : 
     460            0 :     write(iounit, 100) nn, global_data, s%gyre_data_schema
     461              : 100 format(I6, 3(1X,1PE26.16), 1X, I6)
     462              : 
     463            0 :     do j = 1, nn
     464            0 :        write(iounit, 110) j, point_data(:,j)
     465              : 110    format(I6, 99(1X,1PE26.16))
     466              :     end do
     467              : 
     468              :     ! Close the file
     469              : 
     470            0 :     close(iounit)
     471              : 
     472            0 :     return
     473              : 
     474              :   end subroutine write_gyre_data
     475              : 
     476              : end module pulse_gyre
        

Generated by: LCOV version 2.0-1