LCOV - code coverage report
Current view: top level - star/private - read_model.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 41.9 % 437 183
Test Date: 2026-05-05 00:32:19 Functions: 46.2 % 13 6

            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 read_model
      21              : 
      22              :       use star_private_def
      23              :       use const_def, only: dp, msun, secyer
      24              : 
      25              :       implicit none
      26              : 
      27              :       integer, parameter :: bit_for_zams_file = 0
      28              :       integer, parameter :: bit_for_lnPgas = 1  ! OBSOLETE: includes lnPgas variables in place of lnd
      29              :       integer, parameter :: bit_for_2models = 2
      30              :       integer, parameter :: bit_for_velocity = 3
      31              :       integer, parameter :: bit_for_rotation = 4
      32              :       integer, parameter :: bit_for_mlt_vc = 5
      33              :       integer, parameter :: bit_for_RSP2 = 6
      34              :       integer, parameter :: bit_for_RTI = 7
      35              :       !integer, parameter ::  = 8
      36              :       integer, parameter :: bit_for_u = 9
      37              :       integer, parameter :: bit_for_D_omega = 10
      38              :       integer, parameter :: bit_for_am_nu_rot = 11
      39              :       integer, parameter :: bit_for_j_rot = 12
      40              :       !integer, parameter ::  = 13
      41              :       !integer, parameter ::  = 14
      42              :       integer, parameter :: bit_for_RSP = 15
      43              :       integer, parameter :: bit_for_no_L_basic_variable = 16
      44              : 
      45              :       integer, parameter :: increment_for_rotation_flag = 1
      46              :       integer, parameter :: increment_for_have_j_rot = 1
      47              :       integer, parameter :: increment_for_have_mlt_vc = 1
      48              :       integer, parameter :: increment_for_D_omega_flag = 1
      49              :       integer, parameter :: increment_for_am_nu_rot_flag = 1
      50              :       integer, parameter :: increment_for_RTI_flag = 1
      51              :       integer, parameter :: increment_for_RSP_flag = 3
      52              :       integer, parameter :: increment_for_RSP2_flag = 1
      53              : 
      54              :       integer, parameter :: max_increment = increment_for_rotation_flag &
      55              :                                           + increment_for_have_j_rot &
      56              :                                           + increment_for_have_mlt_vc &
      57              :                                           + increment_for_D_omega_flag &
      58              :                                           + increment_for_am_nu_rot_flag &
      59              :                                           + increment_for_RTI_flag &
      60              :                                           + increment_for_RSP_flag &
      61              :                                           + increment_for_RSP2_flag
      62              : 
      63              :       integer, parameter :: mesa_zams_file_type = 2**bit_for_zams_file
      64              : 
      65              :       character (len=100000) :: buf
      66              : 
      67              :       contains
      68              : 
      69            4 :       subroutine finish_load_model(s, restart, ierr)
      70              :          use hydro_vars, only: set_vars
      71              :          use star_utils, only: set_m_and_dm, set_m_grav_and_grav, set_dm_bar, &
      72              :             total_angular_momentum, reset_epsnuc_vectors, set_qs
      73              :          use hydro_rotation, only: use_xh_to_update_i_rot_and_j_rot, &
      74              :             set_i_rot_from_omega_and_j_rot, use_xh_to_update_i_rot, set_rotation_info
      75              :          use hydro_RSP2, only: set_RSP2_vars
      76              :          use tdc_hydro, only: set_viscosity_vars_TDC
      77              :          use RSP, only: RSP_setup_part1, RSP_setup_part2
      78              :          use report, only: do_report
      79              :          use alloc, only: fill_ad_with_zeros
      80              :          use brunt, only: do_brunt_B, do_brunt_N2
      81              :          type (star_info), pointer :: s
      82              :          logical, intent(in) :: restart
      83              :          integer, intent(out) :: ierr
      84              :          integer :: k, nz
      85              :          include 'formats'
      86              :          ierr = 0
      87            1 :          nz = s% nz
      88         2465 :          s% brunt_B(1:nz) = 0  ! temporary proxy for brunt_B
      89            1 :          call set_qs(s, nz, s% q, s% dq, ierr)
      90            1 :          if (ierr /= 0) then
      91            0 :             write(*,*) 'set_qs failed in finish_load_model'
      92            0 :             return
      93              :          end if
      94            1 :          call set_m_and_dm(s)
      95            1 :          call set_m_grav_and_grav(s)
      96            1 :          call set_dm_bar(s, nz, s% dm, s% dm_bar)
      97              : 
      98            1 :          call reset_epsnuc_vectors(s)
      99              : 
     100            1 :          s% star_mass = s% mstar/msun
     101              : 
     102            1 :          if (s% rotation_flag) then
     103              :             ! older MESA versions stored only omega in saved models. However, when
     104              :             ! using rotation dependent moments of inertia one actually needs to store
     105              :             ! the angular momentum in order to initialize the model. This flag is here
     106              :             ! to account for the loading of old saved models.
     107            0 :             if (s% have_j_rot) then
     108              :                !if (restart) then
     109              :                   ! only need to compute irot, w_div_w_crit_roche is stored in photos
     110              :                !   call set_i_rot_from_omega_and_j_rot(s)
     111              :                !else
     112              :                   ! need to set w_div_w_crit_roche as well
     113            0 :                call use_xh_to_update_i_rot(s)
     114            0 :                do k=1, s% nz
     115            0 :                   s% omega(k) = s% j_rot(k)/s% i_rot(k)% val
     116              :                end do
     117              :                !end if
     118              :             else
     119              :                ! need to recompute irot and jrot
     120            0 :                call use_xh_to_update_i_rot_and_j_rot(s)
     121              :             end if
     122              :             ! this ensures fp, ft, r_equatorial and r_polar are set by the end
     123              :             !call set_rotation_info(s, .true., ierr)
     124              :             !if (ierr /= 0) then
     125              :             !   write(*,*) &
     126              :             !      'finish_load_model failed in set_rotation_info'
     127              :             !   return
     128              :             !end if
     129              :          end if
     130              : 
     131              :          ! clear some just to avoid getting NaNs at start
     132              :          ! e.g., from profile_starting_model
     133         2465 :          s% D_mix(1:nz) = 0
     134         2465 :          s% adjust_mlt_gradT_fraction(1:nz) = -1
     135         2465 :          s% eps_mdot(1:nz) = 0
     136         2465 :          s% dvc_dt_TDC(1:nz) = 0
     137            1 :          call fill_ad_with_zeros(s% eps_grav_ad,1,-1)
     138         2465 :          s% ergs_error(1:nz) = 0
     139            1 :          if (.not. restart) s% have_ST_start_info = .false.
     140            1 :          if (s% do_element_diffusion) s% edv(:,1:nz) = 0
     141            1 :          if (s% u_flag) then
     142            0 :             call fill_ad_with_zeros(s% u_face_ad,1,-1)
     143            0 :             call fill_ad_with_zeros(s% P_face_ad,1,-1)
     144              :          end if
     145              : 
     146         2465 :          s% flux_limit_R(1:nz) = 0
     147         2465 :          s% flux_limit_lambda(1:nz) = 0
     148              : 
     149            1 :          if (s% RSP_flag) then
     150            0 :             call RSP_setup_part1(s, restart, ierr)
     151            0 :             if (ierr /= 0) then
     152            0 :                write(*,*) 'finish_load_model: RSP_setup_part1 returned ierr', ierr
     153            0 :                return
     154              :             end if
     155              :          end if
     156              : 
     157            1 :          if (.not. s% have_mlt_vc) then
     158            1 :             s% okay_to_set_mlt_vc = .true.
     159              :          end if
     160              : 
     161            1 :          s% doing_finish_load_model = .true.
     162            1 :          call set_vars(s, s% dt, ierr)
     163            1 :          if (ierr == 0 .and. s% RSP2_flag) call set_RSP2_vars(s,ierr)
     164              :          if (ierr == 0 .and. s% TDC_alpha_M > 0 &
     165              :                .and. s% MLT_option == 'TDC' &
     166            1 :                .and. .not. (s% RSP2_flag .or. s% RSP_flag)) &
     167            0 :             call set_viscosity_vars_TDC(s,ierr)
     168            1 :          s% doing_finish_load_model = .false.
     169            1 :          if (ierr /= 0) then
     170            0 :             write(*,*) 'finish_load_model: failed in set_vars'
     171            0 :             return
     172              :          end if
     173              : 
     174            1 :          if (s% rotation_flag) s% total_angular_momentum = total_angular_momentum(s)
     175              : 
     176            1 :          if (s% RSP_flag) then
     177            0 :             call RSP_setup_part2(s, restart, ierr)
     178            0 :             if (ierr /= 0) then
     179            0 :                write(*,*) 'finish_load_model: RSP_setup_part2 returned ierr', ierr
     180            0 :                return
     181              :             end if
     182              :          end if
     183              : 
     184            1 :          s% doing_finish_load_model = .true.
     185              : 
     186            1 :          if(s% calculate_Brunt_B) call do_brunt_B(s, 1, s%nz, ierr)
     187            1 :          if (ierr /= 0) then
     188            0 :             write(*,*) 'finish_load_model: failed in do_brunt_b'
     189            0 :             return
     190              :          end if
     191              : 
     192            1 :          if(s% calculate_Brunt_N2) call do_brunt_N2(s, 1, s%nz, ierr)
     193            1 :          if (ierr /= 0) then
     194            0 :             write(*,*) 'finish_load_model: failed in do_brunt_N2'
     195            0 :             return
     196              :          end if
     197              : 
     198            1 :          call do_report(s, ierr)
     199            1 :          s% doing_finish_load_model = .false.
     200            1 :          if (ierr /= 0) then
     201            0 :             write(*,*) 'finish_load_model: failed in do_report'
     202            0 :             return
     203              :          end if
     204              : 
     205              :       end subroutine finish_load_model
     206              : 
     207              : 
     208            0 :       subroutine do_read_saved_model(s, filename, ierr)
     209              :          use utils_lib
     210              :          use utils_def
     211              :          use chem_def
     212              :          use net, only: set_net
     213              :          use alloc, only: set_var_info, &
     214              :             free_star_info_arrays, allocate_star_info_arrays, set_chem_names
     215              :          use star_utils, only: yrs_for_init_timestep, set_phase_of_evolution
     216              :          type (star_info), pointer :: s
     217              :          character (len=*), intent(in) :: filename
     218              :          integer, intent(out) :: ierr
     219              : 
     220              :          integer :: iounit, n, i, t, file_type, &
     221              :             year_month_day_when_created, nz, species, nvar, count
     222              :          logical :: do_read_prev, no_L
     223              :          real(dp) :: initial_mass, initial_z, initial_y, &
     224              :             tau_factor, opacity_factor, mixing_length_alpha
     225              :          character (len=strlen) :: buffer, string
     226              :          character (len=net_name_len) :: net_name
     227            0 :          character(len=iso_name_length), pointer :: names(:)  ! (species)
     228            0 :          integer, pointer :: perm(:)  ! (species)
     229              : 
     230              :          include 'formats'
     231              : 
     232            0 :          ierr = 0
     233            0 :          open(newunit=iounit, file=trim(filename), status='old', action='read', iostat=ierr)
     234            0 :          if (ierr /= 0) then
     235            0 :             write(*,*) 'open failed', ierr, iounit
     236            0 :             write(*, '(a)') 'failed to open ' // trim(filename)
     237            0 :             return
     238              :          end if
     239              : 
     240              :          ! use token to get file_type so can have comments at start of file
     241            0 :          n = 0
     242            0 :          i = 0
     243            0 :          t = token(iounit, n, i, buffer, string)
     244            0 :          if (t == eof_token) then
     245            0 :             write(*, '(a)') 'failed to find file type at start of ' // trim(filename)
     246            0 :             return
     247              :          end if
     248            0 :          if (t /= name_token) then
     249            0 :             write(*, '(a)') 'failed to find file type at start of ' // trim(filename)
     250            0 :             return
     251              :          end if
     252            0 :          read(string,fmt=*,iostat=ierr) file_type
     253            0 :          if (ierr /= 0) then
     254            0 :             write(*, '(a)') 'failed to find file type at start of ' // trim(filename)
     255            0 :             return
     256              :          end if
     257              : 
     258            0 :          read(iounit, *, iostat=ierr)  ! skip the blank line after the file type
     259            0 :          if (ierr /= 0) then
     260              :             return
     261              :          end if
     262              : 
     263              :          ! refuse to load old models using lnPgas as a structure variable
     264            0 :          if (BTEST(file_type, bit_for_lnPgas)) then
     265            0 :             write(*,'(A)')
     266            0 :             write(*,*) 'MESA no longer supports models using lnPgas as a structure variable'
     267            0 :             write(*,'(A)')
     268            0 :             ierr = -1
     269            0 :             return
     270              :          end if
     271              : 
     272            0 :          s% model_number = 0
     273            0 :          s% star_age = 0
     274            0 :          s% xmstar = -1
     275              : 
     276            0 :          tau_factor = s% tau_factor
     277            0 :          mixing_length_alpha = s% mixing_length_alpha
     278            0 :          opacity_factor = s% opacity_factor
     279              : 
     280              :          call read_properties(iounit, &
     281              :             net_name, species, nz, year_month_day_when_created, &
     282              :             initial_mass, initial_z, initial_y, mixing_length_alpha, &
     283              :             s% model_number, s% star_age, tau_factor, s% Teff, &
     284              :             s% power_nuc_burn, s% power_h_burn, s% power_he_burn, s% power_z_burn, s% power_photo, &
     285              :             opacity_factor, s% crystal_core_boundary_mass, &
     286              :             s% xmstar, s% R_center, s% L_center, s% v_center, &
     287            0 :             s% cumulative_energy_error, s% num_retries, ierr)
     288              : 
     289              :          if (ierr /= 0 .or. initial_mass < 0 .or. nz < 0 &
     290              :                .or. initial_z < 0 .or. species < 0 .or. &
     291            0 :                is_bad(s% xmstar) .or. &
     292              :                is_bad(initial_mass + initial_z)) then
     293            0 :             ierr = -1
     294            0 :             write(*, *) 'do_read_model: missing required properties'
     295            0 :             write(*,*) 'initial_mass', initial_mass
     296            0 :             write(*,*) 'xmstar', s% xmstar
     297            0 :             write(*,*) 'initial_z', initial_z
     298            0 :             write(*,*) 'nz', nz
     299            0 :             write(*,*) 'species', species
     300            0 :             return
     301              :          end if
     302              : 
     303            0 :          s% init_model_number = s% model_number
     304            0 :          s% time = s% star_age*secyer
     305              : 
     306            0 :          if (abs(tau_factor - s% tau_factor) > tau_factor*1d-9 .and. &
     307              :                s% tau_factor /= s% job% set_to_this_tau_factor) then
     308              :             ! don't change if just set by inlist
     309            0 :             write(*,'(A)')
     310            0 :             write(*,1) 'WARNING: changing to saved tau_factor =', tau_factor
     311            0 :             write(*,'(A)')
     312            0 :             s% tau_factor = tau_factor
     313            0 :             s% force_tau_factor = tau_factor
     314              :          end if
     315              : 
     316            0 :          if (abs(opacity_factor - s% opacity_factor) > opacity_factor*1d-9 .and. &
     317              :                s% opacity_factor /= s% job% relax_to_this_opacity_factor) then
     318              :             ! don't change if just set by inlist
     319            0 :             write(*,'(A)')
     320            0 :             write(*,1) 'WARNING: changing to saved opacity_factor =', opacity_factor
     321            0 :             write(*,'(A)')
     322            0 :             s% opacity_factor = opacity_factor
     323            0 :             s% force_opacity_factor = opacity_factor
     324              :          end if
     325              : 
     326            0 :          if (abs(mixing_length_alpha - s% mixing_length_alpha) > mixing_length_alpha*1d-9) then
     327            0 :             write(*,'(A)')
     328            0 :             write(*,1) 'WARNING: model saved with mixing_length_alpha =', mixing_length_alpha
     329            0 :             write(*,1) 'but current setting for mixing_length_alpha =', s% mixing_length_alpha
     330            0 :             write(*,'(A)')
     331              :          end if
     332              : 
     333            0 :          s% v_flag = BTEST(file_type, bit_for_velocity)
     334            0 :          s% u_flag = BTEST(file_type, bit_for_u)
     335            0 :          s% rotation_flag = BTEST(file_type, bit_for_rotation)
     336            0 :          s% have_j_rot = BTEST(file_type, bit_for_j_rot)
     337            0 :          s% have_mlt_vc = BTEST(file_type, bit_for_mlt_vc)
     338            0 :          s% D_omega_flag = BTEST(file_type, bit_for_D_omega)
     339            0 :          s% am_nu_rot_flag = BTEST(file_type, bit_for_am_nu_rot)
     340            0 :          s% RTI_flag = BTEST(file_type, bit_for_RTI)
     341            0 :          s% RSP_flag = BTEST(file_type, bit_for_RSP)
     342            0 :          s% RSP2_flag = BTEST(file_type, bit_for_RSP2)
     343            0 :          no_L = BTEST(file_type, bit_for_no_L_basic_variable)
     344              : 
     345              :          if (BTEST(file_type, bit_for_lnPgas)) then
     346              :             write(*,'(A)')
     347              :             write(*,*) 'MESA no longer supports models using lnPgas as a structure variable'
     348              :             write(*,'(A)')
     349              :             ierr = -1
     350              :             return
     351              :          end if
     352              : 
     353            0 :          s% net_name = trim(net_name)
     354            0 :          s% species = species
     355            0 :          s% initial_z = initial_z
     356              : 
     357            0 :          s% mstar = initial_mass*Msun
     358            0 :          if (s% xmstar < 0) then
     359            0 :             s% M_center = 0
     360            0 :             s% xmstar = s% mstar
     361              :          else
     362            0 :             s% M_center = s% mstar - s% xmstar
     363              :          end if
     364            0 :          if (is_bad(s% M_center)) then
     365            0 :             write(*,1) 'M_center mstar xmstar initial_mass', &
     366            0 :                s% M_center, s% mstar, s% xmstar, initial_mass
     367            0 :             call mesa_error(__FILE__,__LINE__,'do_read_saved_model')
     368              :          end if
     369              : 
     370            0 :          call set_net(s, s% net_name, ierr)
     371            0 :          if (ierr /= 0) then
     372              :             write(*,*) &
     373            0 :                'do_read_saved_model failed in set_net for net_name = ' // trim(s% net_name)
     374            0 :             return
     375              :          end if
     376              : 
     377            0 :          call set_var_info(s, ierr)
     378            0 :          if (ierr /= 0) then
     379            0 :             write(*,*) 'do_read_saved_model failed in set_var_info'
     380            0 :             return
     381              :          end if
     382              : 
     383              :          ! fixup chem names now that have nvar_hydro
     384            0 :          call set_chem_names(s)
     385              : 
     386            0 :          s% nz = nz
     387            0 :          call free_star_info_arrays(s)
     388            0 :          call allocate_star_info_arrays(s, ierr)
     389            0 :          if (ierr /= 0) then
     390            0 :             write(*,*) 'do_read_saved_model failed in allocate_star_info_arrays'
     391            0 :             return
     392              :          end if
     393              : 
     394            0 :          allocate(names(species), perm(species))
     395            0 :          call get_chem_col_names(s, iounit, species, names, perm, ierr)
     396            0 :          if (ierr /= 0) then
     397            0 :             deallocate(names, perm)
     398            0 :             write(*,*) 'do_read_saved_model failed in get_chem_col_names'
     399            0 :             return
     400              :          end if
     401              : 
     402            0 :          count = 0
     403            0 :          do i=1,species
     404            0 :             if (perm(i)==0) then
     405            0 :                count = count+1
     406            0 :                write(*,*) "Mod file has isotope ",trim(names(i)), " but that is not in the net"
     407              :             end if
     408              :          end do
     409            0 :          if (count/=0) call mesa_error(__FILE__,__LINE__)
     410              : 
     411            0 :          nvar = s% nvar_total
     412              :          call read1_model( &
     413              :                s, s% species, s% nvar_hydro, nz, iounit, &
     414              :                s% xh, s% xa, s% q, s% dq, s% omega, s% j_rot, &
     415            0 :                perm, ierr)
     416            0 :          deallocate(names, perm)
     417            0 :          if (ierr /= 0) then
     418            0 :             write(*,*) 'do_read_saved_model failed in read1_model'
     419            0 :             return
     420              :          end if
     421              : 
     422            0 :          do_read_prev = BTEST(file_type, bit_for_2models)
     423              :          if (ierr == 0) then
     424            0 :             if (do_read_prev) then
     425            0 :                call read_prev
     426              :             else
     427            0 :                s% generations = 1
     428              :             end if
     429              :          end if
     430              : 
     431            0 :          close(iounit)
     432              : 
     433              : 
     434              :          contains
     435              : 
     436              : 
     437            0 :          subroutine read_prev
     438              :             integer :: k
     439              : 
     440            0 :             do k=1, 3
     441            0 :                read(iounit, *, iostat=ierr)
     442            0 :                if (ierr /= 0) return
     443              :             end do
     444            0 :             call read_prev_properties
     445            0 :             if (ierr /= 0) return
     446              : 
     447              :             ! we do read_prev_properties to set initial timestep,
     448              :             ! but we don't use the previous model
     449              :             ! because we need to have other info about that isn't saved
     450              :             ! such as conv_vel and mixing_type
     451              : 
     452            0 :             s% generations = 1
     453              : 
     454              :          end subroutine read_prev
     455              : 
     456              : 
     457            0 :          subroutine read_prev_properties
     458              :             character (len=132) :: line
     459              :             real(dp) :: tmp, skip_val
     460              :             include 'formats'
     461              : 
     462            0 :             ierr = 0
     463            0 :             s% dt = -1
     464            0 :             s% mstar_old = -1
     465            0 :             s% dt_next = -1
     466            0 :             s% nz_old = -1
     467              : 
     468              :             do  ! until reach a blank line
     469            0 :                read(iounit, fmt='(a)', iostat=ierr) line
     470            0 :                if (ierr /= 0) return
     471              : 
     472            0 :                if (len_trim(line) == 0) exit  ! blank line
     473              : 
     474            0 :                if (match_keyword('previous n_shells', line, tmp)) then
     475            0 :                   s% nz_old = int(tmp)
     476            0 :                   cycle
     477              :                end if
     478              : 
     479            0 :                if (match_keyword('timestep (seconds)', line, s% dt)) then
     480              :                   cycle
     481              :                end if
     482              : 
     483            0 :                if (match_keyword('previous mass (grams)', line, s% mstar_old)) then
     484              :                   cycle
     485              :                end if
     486              : 
     487            0 :                if (match_keyword('dt_next (seconds)', line, s% dt_next)) then
     488              :                   cycle
     489              :                end if
     490              : 
     491            0 :                if (match_keyword('year_month_day_when_created', line, skip_val)) cycle
     492              : 
     493              :             end do
     494            0 :             if (s% dt < 0) then
     495            0 :                ierr = -1
     496            0 :                write(*, *) 'missing dt for previous model'
     497              :             end if
     498            0 :             if (s% mstar_old < 0) then
     499            0 :                ierr = -1
     500            0 :                write(*, *) 'missing mstar_old for previous model'
     501              :             end if
     502            0 :             if (s% dt_next < 0) then
     503            0 :                ierr = -1
     504            0 :                write(*, *) 'missing dt_next for previous model'
     505              :             end if
     506              : 
     507              :          end subroutine read_prev_properties
     508              : 
     509              : 
     510              :       end subroutine do_read_saved_model
     511              : 
     512              : 
     513            2 :       subroutine read1_model( &
     514              :             s, species, nvar_hydro, nz, iounit, &
     515            2 :             xh, xa, q, dq, omega, j_rot, &
     516            2 :             perm, ierr)
     517              :          use star_utils, only: set_qs
     518              :          use chem_def
     519              :          type (star_info), pointer :: s
     520              :          integer, intent(in) :: species, nvar_hydro, nz, iounit, perm(:)
     521              :          real(dp), dimension(:,:), intent(out) :: xh, xa
     522              :          real(dp), dimension(:), intent(out) :: &
     523              :             q, dq, omega, j_rot
     524              :          integer, intent(out) :: ierr
     525              : 
     526              :          integer :: j, k, n, i_lnd, i_lnT, i_lnR, i_lum, i_w, i_Hp, &
     527              :             i_Et_RSP, i_erad_RSP, i_Fr_RSP, i_v, i_u, i_alpha_RTI, ii
     528            2 :          real(dp), target :: vec_ary(species + nvar_hydro + max_increment)
     529              :          real(dp), pointer :: vec(:)
     530              :          integer :: nvec
     531              : 
     532              :          include 'formats'
     533              : 
     534            2 :          ierr = 0
     535            2 :          vec => vec_ary
     536              : 
     537            2 :          i_lnd = s% i_lnd
     538            2 :          i_lnT = s% i_lnT
     539            2 :          i_lnR = s% i_lnR
     540            2 :          i_lum = s% i_lum
     541            2 :          i_w = s% i_w
     542            2 :          i_Hp = s% i_Hp
     543            2 :          i_v = s% i_v
     544            2 :          i_u = s% i_u
     545            2 :          i_alpha_RTI = s% i_alpha_RTI
     546            2 :          i_Et_RSP = s% i_Et_RSP
     547            2 :          i_erad_RSP = s% i_erad_RSP
     548            2 :          i_Fr_RSP = s% i_Fr_RSP
     549              : 
     550              :          n = species + nvar_hydro + 1  ! + 1 is for dq
     551              :          if (s% rotation_flag) n = n+increment_for_rotation_flag  ! read omega
     552              :          if (s% have_j_rot) n = n+increment_for_have_j_rot  ! read j_rot
     553              :          if (s% have_mlt_vc) n = n+increment_for_have_mlt_vc
     554              :          if (s% D_omega_flag) n = n+increment_for_D_omega_flag  ! read D_omega
     555              :          if (s% am_nu_rot_flag) n = n+increment_for_am_nu_rot_flag  ! read am_nu_rot
     556              :          if (s% RTI_flag) n = n+increment_for_RTI_flag  ! read alpha_RTI
     557              :          if (s% RSP_flag) n = n+increment_for_RSP_flag  ! read RSP_et, erad, Fr
     558              :          if (s% RSP2_flag) n = n+increment_for_RSP2_flag  ! read w, Hp
     559              : 
     560            4 : !$omp critical (read1_model_loop)
     561              : ! make this a critical section to so don't have to dynamically allocate buf
     562         4932 :          do k = 1, nz
     563         4930 :             read(iounit,'(a)',iostat=ierr) buf
     564         4930 :             if (ierr /= 0) then
     565            0 :                write(*,3) 'read failed i', k, nz
     566            0 :                exit
     567              :             end if
     568         4930 :             call str_to_vector(buf, vec, nvec, ierr)
     569         4930 :             if (ierr /= 0) then
     570            0 :                write(*,*) 'str_to_vector failed'
     571            0 :                write(*,'(a,i8,1x,a)') 'buf', k, trim(buf)
     572            0 :                exit
     573              :             end if
     574         4930 :             j = int(vec(1))
     575         4930 :             if (j /= k) then
     576            0 :                ierr = -1
     577            0 :                write(*, *) 'error in reading model data   j /= k'
     578            0 :                write(*, *) 'species', species
     579            0 :                write(*, *) 'j', j
     580            0 :                write(*, *) 'k', k
     581            0 :                write(*,'(a,1x,a)') 'buf', trim(buf)
     582            0 :                exit
     583              :             end if
     584              :             j = 1
     585         4930 :             j=j+1; xh(i_lnd,k) = vec(j)
     586         4930 :             j=j+1; xh(i_lnT,k) = vec(j)
     587         4930 :             j=j+1; xh(i_lnR,k) = vec(j)
     588         4930 :             if (s% RSP_flag) then
     589            0 :                j=j+1; xh(i_Et_RSP,k) = vec(j)
     590            0 :                j=j+1; xh(i_erad_RSP,k) = vec(j)
     591            0 :                j=j+1; xh(i_Fr_RSP,k) = vec(j)
     592         4930 :             else if (s% RSP2_flag) then
     593            0 :                j=j+1; xh(i_w,k) = vec(j)
     594            0 :                j=j+1; xh(i_Hp,k) = vec(j)
     595              :             end if
     596         4930 :             if (i_lum /= 0) then
     597         4930 :                j=j+1; xh(i_lum,k) = vec(j)
     598              :             else
     599            0 :                j=j+1; s% L(k) = vec(j)
     600              :             end if
     601         4930 :             j=j+1; dq(k) = vec(j)
     602         4930 :             if (s% v_flag) then
     603            0 :                j=j+1; xh(i_v,k) = vec(j)
     604              :             end if
     605         4930 :             if (s% rotation_flag) then
     606            0 :                j=j+1; omega(k) = vec(j)
     607              :             end if
     608         4930 :             if (s% have_j_rot) then
     609              :                !NOTE: MESA version 10108 was first to store j_rot in saved files
     610            0 :                j=j+1; j_rot(k) = vec(j)
     611              :             end if
     612         4930 :             if (s% D_omega_flag) then
     613            0 :                j=j+1  ! skip saving the file data
     614              :             end if
     615         4930 :             if (s% am_nu_rot_flag) then
     616            0 :                j=j+1  ! skip saving the file data
     617              :             end if
     618         4930 :             if (s% u_flag) then
     619            0 :                j=j+1; xh(i_u,k) = vec(j)
     620              :             end if
     621         4930 :             if (s% RTI_flag) then
     622            0 :                j=j+1; xh(i_alpha_RTI,k) = vec(j)
     623              :             end if
     624         4930 :             if (s% have_mlt_vc) then
     625            0 :                j=j+1; s% mlt_vc(k) = vec(j); s% conv_vel(k) = vec(j)
     626              :             end if
     627         4930 :             if (j+species > nvec) then
     628            0 :                ierr = -1
     629            0 :                write(*, *) 'error in reading model data  j+species > nvec'
     630            0 :                write(*, *) 'j+species', j+species
     631            0 :                write(*, *) 'nvec', nvec
     632            0 :                write(*, *) 'j', j
     633            0 :                write(*, *) 'species', species
     634            0 :                write(*,'(a,1x,a)') 'buf', trim(buf)
     635            0 :                exit
     636              :             end if
     637        49302 :             do ii=1,species
     638        44370 :                xa(perm(ii),k) = vec(j+ii)
     639              :             end do
     640              :          end do
     641              : !$omp end critical (read1_model_loop)
     642            2 :          if (ierr /= 0) then
     643            0 :             write(*,*) 'read1_model_loop failed'
     644            0 :             return
     645              :          end if
     646              : 
     647            2 :          if (s% rotation_flag .and. .not. s% D_omega_flag) &
     648            0 :             s% D_omega(1:nz) = 0d0
     649              : 
     650            2 :          if (s% rotation_flag .and. .not. s% am_nu_rot_flag) &
     651            0 :             s% am_nu_rot(1:nz) = 0d0
     652              : 
     653            2 :          call set_qs(s, nz, q, dq, ierr)
     654            2 :          if (ierr /= 0) then
     655            0 :             write(*,*) 'set_qs failed in read1_model sum(dq)', sum(dq(1:nz))
     656            0 :             return
     657              :          end if
     658              : 
     659              :       end subroutine read1_model
     660              : 
     661              : 
     662            0 :       subroutine do_read_saved_model_number(fname, model_number, ierr)
     663              :          character (len=*), intent(in) :: fname
     664              :          integer, intent(inout) :: model_number
     665              :          integer, intent(out) :: ierr
     666              :          character (len=strlen) :: net_name
     667              :          integer :: species, n_shells, &
     668              :             num_retries, year_month_day_when_created
     669              :          real(dp) :: m_div_msun, initial_z, &
     670              :             mixing_length_alpha, star_age, &
     671              :             Teff, tau_factor, opacity_factor, crystal_core_boundary_mass, &
     672              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     673              :             xmstar, R_center, L_center, v_center, cumulative_energy_error
     674              :          call do_read_saved_model_properties(fname, &
     675              :             net_name, species, n_shells, year_month_day_when_created, &
     676              :             m_div_msun, initial_z, mixing_length_alpha, &
     677              :             model_number, star_age, tau_factor, Teff, &
     678              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     679              :             opacity_factor, crystal_core_boundary_mass, &
     680              :             xmstar, R_center, L_center, v_center, &
     681            0 :             cumulative_energy_error, num_retries, ierr)
     682            0 :       end subroutine do_read_saved_model_number
     683              : 
     684              : 
     685            0 :       subroutine do_read_saved_model_properties(fname, &
     686              :             net_name, species, n_shells, year_month_day_when_created, &
     687              :             m_div_msun, initial_z, mixing_length_alpha, &
     688              :             model_number, star_age, tau_factor, Teff, &
     689              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     690              :             opacity_factor, crystal_core_boundary_mass, &
     691              :             xmstar, R_center, L_center, v_center, &
     692              :             cumulative_energy_error, num_retries, ierr)
     693              :          use utils_lib
     694              :          character (len=*), intent(in) :: fname
     695              :          character (len=*), intent(inout) :: net_name
     696              :          integer, intent(inout) :: species, n_shells, &
     697              :             year_month_day_when_created, num_retries, model_number
     698              :          real(dp), intent(inout) :: m_div_msun, initial_z, &
     699              :             mixing_length_alpha, star_age, tau_factor, Teff, &
     700              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     701              :             opacity_factor, crystal_core_boundary_mass, &
     702              :             xmstar, R_center, L_center, v_center, cumulative_energy_error
     703              :          integer, intent(out) :: ierr
     704              :          integer :: iounit
     705              :          real(dp) :: initial_y
     706            0 :          ierr = 0
     707            0 :          open(newunit=iounit, file=trim(fname), action='read', status='old', iostat=ierr)
     708            0 :          if (ierr /= 0) then
     709            0 :             write(*, *) 'failed to open ' // trim(fname)
     710            0 :             return
     711              :          end if
     712            0 :          read(iounit, *, iostat=ierr)
     713            0 :          if (ierr /= 0) then
     714            0 :             close(iounit)
     715            0 :             return
     716              :          end if
     717            0 :          read(iounit, *, iostat=ierr)
     718            0 :          if (ierr /= 0) then
     719            0 :             close(iounit)
     720            0 :             return
     721              :          end if
     722              :          call read_properties(iounit, &
     723              :             net_name, species, n_shells, year_month_day_when_created, &
     724              :             m_div_msun, initial_z, initial_y, mixing_length_alpha, &
     725              :             model_number, star_age, tau_factor, Teff, &
     726              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     727              :             opacity_factor, crystal_core_boundary_mass, &
     728              :             xmstar, R_center, L_center, v_center, &
     729            0 :             cumulative_energy_error, num_retries, ierr)
     730            0 :          close(iounit)
     731              :       end subroutine do_read_saved_model_properties
     732              : 
     733              : 
     734            0 :       subroutine do_read_net_name(iounit, net_name, ierr)
     735              :          integer, intent(in) :: iounit
     736              :          character (len=*), intent(inout) :: net_name
     737              :          integer, intent(out) :: ierr
     738              :          integer :: species, n_shells, &
     739              :             year_month_day_when_created, model_number, num_retries
     740              :          real(dp) :: m_div_msun, initial_z, initial_y, &
     741              :             mixing_length_alpha, star_age, tau_factor, Teff, &
     742              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     743              :             opacity_factor, crystal_core_boundary_mass, &
     744              :             xmstar, R_center, L_center, v_center, cumulative_energy_error
     745              :          call read_properties(iounit, &
     746              :             net_name, species, n_shells, year_month_day_when_created, &
     747              :             m_div_msun, initial_z, initial_y, mixing_length_alpha, &
     748              :             model_number, star_age, tau_factor, Teff, &
     749              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     750              :             opacity_factor, crystal_core_boundary_mass, &
     751              :             xmstar, R_center, L_center, v_center, &
     752            0 :             cumulative_energy_error, num_retries, ierr)
     753            0 :       end subroutine do_read_net_name
     754              : 
     755              : 
     756            0 :       subroutine do_read_saved_model_age(fname, star_age, ierr)
     757              :          character (len=*), intent(in) :: fname
     758              :          real(dp), intent(inout) :: star_age
     759              :          integer, intent(out) :: ierr
     760              :          character (len=strlen) :: net_name
     761              :          integer :: species, n_shells, model_number, &
     762              :             num_retries, year_month_day_when_created
     763              :          real(dp) :: m_div_msun, initial_z, &
     764              :             mixing_length_alpha, cumulative_energy_error, &
     765              :             Teff, tau_factor, &
     766              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     767              :             opacity_factor, crystal_core_boundary_mass, &
     768              :             xmstar, R_center, L_center, v_center
     769              :          call do_read_saved_model_properties(fname, &
     770              :             net_name, species, n_shells, year_month_day_when_created, &
     771              :             m_div_msun, initial_z, mixing_length_alpha, &
     772              :             model_number, star_age, tau_factor, Teff, &
     773              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     774              :             opacity_factor, crystal_core_boundary_mass, &
     775              :             xmstar, R_center, L_center, v_center, &
     776            0 :             cumulative_energy_error, num_retries, ierr)
     777            0 :       end subroutine do_read_saved_model_age
     778              : 
     779              : 
     780           18 :       subroutine read_properties(iounit, &
     781              :             net_name, species, n_shells, year_month_day_when_created, &
     782              :             m_div_msun, initial_z, initial_y, mixing_length_alpha, &
     783              :             model_number, star_age, tau_factor, Teff, &
     784              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     785              :             opacity_factor, crystal_core_boundary_mass, &
     786              :             xmstar, R_center, L_center, v_center, &
     787              :             cumulative_energy_error, num_retries, ierr)
     788              :          integer, intent(in) :: iounit
     789              :          character (len=*), intent(inout) :: net_name
     790              :          integer, intent(inout) :: species, n_shells, &
     791              :             year_month_day_when_created, model_number, num_retries
     792              :          real(dp), intent(inout) :: m_div_msun, initial_z, initial_y, &
     793              :             mixing_length_alpha, star_age, tau_factor, Teff, &
     794              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     795              :             opacity_factor, crystal_core_boundary_mass, &
     796              :             xmstar, R_center, L_center, v_center, cumulative_energy_error
     797              :          integer, intent(out) :: ierr
     798              :          character (len=132) :: line
     799              :          real(dp) :: tmp
     800              :          ierr = 0
     801              :          do  ! until reach a blank line
     802           62 :             read(iounit, fmt='(a)', iostat=ierr) line
     803           62 :             if (ierr /= 0) return
     804           62 :             if (len_trim(line) == 0) return  ! blank line
     805           44 :             if (match_keyword_for_string('net_name', line, net_name)) then; cycle; end if
     806           43 :             if (match_keyword('species', line, tmp)) then; species = int(tmp); cycle; end if
     807           42 :             if (match_keyword('n_shells', line, tmp)) then; n_shells = int(tmp); cycle; end if
     808           25 :             if (match_keyword('model_number', line, tmp)) then; model_number = int(tmp); cycle; end if
     809           25 :             if (match_keyword('M/Msun', line, m_div_msun)) cycle
     810            8 :             if (match_keyword('star_age', line, star_age)) cycle
     811            8 :             if (match_keyword('initial_z', line, initial_z)) cycle
     812            7 :             if (match_keyword('initial_y', line, initial_y)) cycle
     813            6 :             if (match_keyword('mixing_length_alpha', line, mixing_length_alpha)) cycle
     814            6 :             if (match_keyword('tau_factor', line, tau_factor)) cycle
     815            6 :             if (match_keyword('Teff', line, Teff)) cycle
     816            6 :             if (match_keyword('power_nuc_burn', line, power_nuc_burn)) cycle
     817            6 :             if (match_keyword('power_h_burn', line, power_h_burn)) cycle
     818            6 :             if (match_keyword('power_he_burn', line, power_he_burn)) cycle
     819            6 :             if (match_keyword('power_z_burn', line, power_z_burn)) cycle
     820            6 :             if (match_keyword('power_photo', line, power_photo)) cycle
     821            6 :             if (match_keyword('opacity_factor', line, opacity_factor)) cycle
     822            6 :             if (match_keyword('crystal_core_boundary_mass', line, crystal_core_boundary_mass)) cycle
     823            6 :             if (match_keyword('xmstar', line, xmstar)) cycle
     824            6 :             if (match_keyword('R_center', line, R_center)) cycle
     825            6 :             if (match_keyword('L_center', line, L_center)) cycle
     826            6 :             if (match_keyword('v_center', line, v_center)) cycle
     827            6 :             if (match_keyword('cumulative_energy_error', line, cumulative_energy_error)) cycle
     828            6 :             if (match_keyword('year_month_day_when_created', line, tmp)) then
     829            1 :                year_month_day_when_created = int(tmp); cycle; end if
     830            5 :             if (match_keyword('tau_photosphere', line, tmp)) cycle
     831            5 :             if (match_keyword('num_retries', line, tmp)) then; num_retries = int(tmp); cycle; end if
     832              :          end do
     833              :       end subroutine read_properties
     834              : 
     835              : 
     836          264 :       logical function match_keyword(key, txt, value)
     837              :          ! returns true if leading non-blank part of txt is same as key.
     838              :          ! i.e., skips leading blanks in txt before testing equality.
     839              :          character (len=*), intent(in) :: key, txt
     840              :          real(dp), intent(inout) :: value
     841              :          integer :: i, j, k, ierr
     842          264 :          i = len(key)
     843          264 :          k = len(txt)
     844          264 :          j = 1
     845         5912 :          do while (j <= k .and. txt(j:j) == ' ')
     846         5912 :             j = j+1
     847              :          end do
     848          264 :          match_keyword = (txt(j:j+i-1) == key)
     849          264 :          ierr = 0
     850          264 :          if (match_keyword) then
     851           38 :             read(txt(j+i:k), fmt=*, iostat=ierr) value
     852          264 :             if (ierr /= 0) match_keyword = .false.
     853              :          end if
     854          264 :       end function match_keyword
     855              : 
     856              : 
     857           44 :       logical function match_keyword_for_string(key, txt, value)
     858              :          ! returns true if leading non-blank part of txt is same as key.
     859              :          ! i.e., skips leading blanks in txt before testing equality.
     860              :          character (len=*), intent(in) :: key, txt
     861              :          character (len=*), intent(inout) :: value
     862              :          integer :: i, j, k, str_len
     863              :          logical, parameter :: dbg = .false.
     864           44 :          i = len(key)
     865           44 :          k = len(txt)
     866           44 :          j = 1
     867         1099 :          do while (j <= k .and. txt(j:j) == ' ')
     868         1099 :             j = j+1
     869              :          end do
     870           44 :          match_keyword_for_string = (txt(j:j+i-1) == key)
     871           44 :          if (.not. match_keyword_for_string) return
     872              :          if (dbg) then
     873              :             write(*,*) 'matching ' // trim(key)
     874              :             write(*,*) 'txt ' // trim(txt)
     875              :          end if
     876              :          j = j+i
     877            4 :          do while (j <= k .and. txt(j:j) == ' ')
     878            4 :             j = j+1
     879              :          end do
     880            1 :          if (j > k) then
     881           44 :             match_keyword_for_string = .false.
     882              :             if (dbg) write(*,*) 'j > k'
     883              :             return
     884              :          end if
     885            1 :          if (txt(j:j) /= '''') then
     886           44 :             match_keyword_for_string = .false.
     887              :             if (dbg) write(*,*) 'no leading quote'
     888              :             return
     889              :          end if
     890            1 :          j = j+1
     891            1 :          i = 1
     892            1 :          str_len = len(value)
     893           10 :          do while (j <= k .and. txt(j:j) /= '''')
     894            9 :             value(i:i) = txt(j:j)
     895            9 :             i = i+1
     896           10 :             j = j+1
     897              :          end do
     898          248 :          do while (i <= str_len)
     899          247 :             value(i:i) = ' '
     900          247 :             i = i+1
     901              :          end do
     902              :          if (dbg) write(*,*) 'value <' // trim(value) // ">"
     903              :       end function match_keyword_for_string
     904              : 
     905              : 
     906           17 :       subroutine get_chem_col_names(s, iounit, species, names, perm, ierr)
     907              :          use chem_def, only: iso_name_length
     908              :          use chem_lib, only: chem_get_iso_id
     909              :          type (star_info), pointer :: s
     910              :          integer, intent(in) :: iounit, species
     911              :          character(len=iso_name_length), intent(out) :: names(species)
     912              :          integer, intent(out) :: perm(species)
     913              :          integer, intent(out) :: ierr
     914              : 
     915              :          character (len=50000) :: buffer
     916              :          character (len=20) :: string
     917              :          integer :: n, i, j1, j2, str_len, l, indx, j, num_found
     918              : 
     919              :          ierr = 0
     920           17 :          read(iounit,fmt='(a)',iostat=ierr) buffer
     921           17 :          if (ierr /= 0) return
     922              : 
     923           17 :          n = len_trim(buffer)
     924           17 :          i = 0
     925           17 :          num_found = 0
     926              :        token_loop: do  ! have non-empty buffer
     927         4964 :             i = i+1
     928         4964 :             if (i > n) then
     929            0 :                write(*,*) 'get_chem_col_names: failed to find all of the names'
     930            0 :                ierr = -1
     931            0 :                return
     932              :             end if
     933         4964 :             if (buffer(i:i) == char(9)) cycle token_loop  ! skip tabs
     934              :             select case(buffer(i:i))
     935              :                case (' ')
     936              :                   cycle token_loop  ! skip spaces
     937              :                case default
     938              :                   j1 = i; j2 = i
     939              :                   name_loop: do
     940          629 :                      if (i+1 > n) exit name_loop
     941          612 :                      if (buffer(i+1:i+1) == ' ') exit name_loop
     942          408 :                      if (buffer(i+1:i+1) == '(') exit name_loop
     943              :                      if (buffer(i+1:i+1) == ')') exit name_loop
     944              :                      if (buffer(i+1:i+1) == ',') exit name_loop
     945              :                      i = i+1
     946          221 :                      j2 = i
     947              :                   end do name_loop
     948          221 :                   str_len = len(string)
     949          221 :                   l = j2-j1+1
     950          221 :                   if (l > str_len) then
     951            0 :                      l = str_len
     952            0 :                      j2 = l+j1-1
     953              :                   end if
     954          221 :                   string(1:l) = buffer(j1:j2)
     955         4012 :                   do j = l+1, str_len
     956         4012 :                      string(j:j) = ' '
     957              :                   end do
     958              : 
     959          221 :                   indx = chem_get_iso_id(string)
     960              : 
     961         5185 :                   if (indx > 0) then
     962          136 :                      num_found = num_found+1
     963          136 :                      names(num_found) = trim(string)
     964          136 :                      perm(num_found) = s% net_iso(indx)
     965              :                      !write(*,*) trim(string), num_found, perm(num_found)
     966          136 :                      if (num_found == species) return
     967              :                   end if
     968              : 
     969              :             end select
     970              :          end do token_loop
     971              : 
     972              :       end subroutine get_chem_col_names
     973              : 
     974              :       end module read_model
        

Generated by: LCOV version 2.0-1