LCOV - code coverage report
Current view: top level - star/private - read_model.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 40.5 % 472 191
Test Date: 2025-12-14 16:52:03 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           18 :       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            1 :       end subroutine finish_load_model
     206              : 
     207              : 
     208            0 :       subroutine do_read_saved_model(s, filename, ierr)
     209            1 :          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            0 :          real(dp) :: initial_mass, initial_z, initial_y, &
     224            0 :             tau_factor, Tsurf_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 :          Tsurf_factor = s% Tsurf_factor
     278            0 :          mixing_length_alpha = s% mixing_length_alpha
     279            0 :          opacity_factor = s% opacity_factor
     280              : 
     281              :          call read_properties(iounit, &
     282              :             net_name, species, nz, year_month_day_when_created, &
     283              :             initial_mass, initial_z, initial_y, mixing_length_alpha, &
     284              :             s% model_number, s% star_age, tau_factor, s% Teff, &
     285              :             s% power_nuc_burn, s% power_h_burn, s% power_he_burn, s% power_z_burn, s% power_photo, &
     286              :             Tsurf_factor, opacity_factor, s% crystal_core_boundary_mass, &
     287              :             s% xmstar, s% R_center, s% L_center, s% v_center, &
     288            0 :             s% cumulative_energy_error, s% num_retries, ierr)
     289              : 
     290              :          if (ierr /= 0 .or. initial_mass < 0 .or. nz < 0 &
     291              :                .or. initial_z < 0 .or. species < 0 .or. &
     292            0 :                is_bad(s% xmstar) .or. &
     293              :                is_bad(initial_mass + initial_z)) then
     294            0 :             ierr = -1
     295            0 :             write(*, *) 'do_read_model: missing required properties'
     296            0 :             write(*,*) 'initial_mass', initial_mass
     297            0 :             write(*,*) 'xmstar', s% xmstar
     298            0 :             write(*,*) 'initial_z', initial_z
     299            0 :             write(*,*) 'nz', nz
     300            0 :             write(*,*) 'species', species
     301            0 :             return
     302              :          end if
     303              : 
     304            0 :          s% init_model_number = s% model_number
     305            0 :          s% time = s% star_age*secyer
     306              : 
     307            0 :          if (abs(tau_factor - s% tau_factor) > tau_factor*1d-9 .and. &
     308              :                s% tau_factor /= s% job% set_to_this_tau_factor) then
     309              :             ! don't change if just set by inlist
     310            0 :             write(*,'(A)')
     311            0 :             write(*,1) 'WARNING: changing to saved tau_factor =', tau_factor
     312            0 :             write(*,'(A)')
     313            0 :             s% tau_factor = tau_factor
     314            0 :             s% force_tau_factor = tau_factor
     315              :          end if
     316              : 
     317            0 :          if (abs(Tsurf_factor - s% Tsurf_factor) > Tsurf_factor*1d-9 .and. &
     318              :                s% Tsurf_factor /= s% job% set_to_this_Tsurf_factor) then
     319              :             ! don't change if just set by inlist
     320            0 :             write(*,'(A)')
     321            0 :             write(*,1) 'WARNING: changing to saved Tsurf_factor =', Tsurf_factor
     322            0 :             write(*,'(A)')
     323            0 :             s% Tsurf_factor = Tsurf_factor
     324            0 :             s% force_Tsurf_factor = Tsurf_factor
     325              :          end if
     326              : 
     327            0 :          if (abs(opacity_factor - s% opacity_factor) > opacity_factor*1d-9 .and. &
     328              :                s% opacity_factor /= s% job% relax_to_this_opacity_factor) then
     329              :             ! don't change if just set by inlist
     330            0 :             write(*,'(A)')
     331            0 :             write(*,1) 'WARNING: changing to saved opacity_factor =', opacity_factor
     332            0 :             write(*,'(A)')
     333            0 :             s% opacity_factor = opacity_factor
     334            0 :             s% force_opacity_factor = opacity_factor
     335              :          end if
     336              : 
     337            0 :          if (abs(mixing_length_alpha - s% mixing_length_alpha) > mixing_length_alpha*1d-9) then
     338            0 :             write(*,'(A)')
     339            0 :             write(*,1) 'WARNING: model saved with mixing_length_alpha =', mixing_length_alpha
     340            0 :             write(*,1) 'but current setting for mixing_length_alpha =', s% mixing_length_alpha
     341            0 :             write(*,'(A)')
     342              :          end if
     343              : 
     344            0 :          s% v_flag = BTEST(file_type, bit_for_velocity)
     345            0 :          s% u_flag = BTEST(file_type, bit_for_u)
     346            0 :          s% rotation_flag = BTEST(file_type, bit_for_rotation)
     347            0 :          s% have_j_rot = BTEST(file_type, bit_for_j_rot)
     348            0 :          s% have_mlt_vc = BTEST(file_type, bit_for_mlt_vc)
     349            0 :          s% D_omega_flag = BTEST(file_type, bit_for_D_omega)
     350            0 :          s% am_nu_rot_flag = BTEST(file_type, bit_for_am_nu_rot)
     351            0 :          s% RTI_flag = BTEST(file_type, bit_for_RTI)
     352            0 :          s% RSP_flag = BTEST(file_type, bit_for_RSP)
     353            0 :          s% RSP2_flag = BTEST(file_type, bit_for_RSP2)
     354            0 :          no_L = BTEST(file_type, bit_for_no_L_basic_variable)
     355              : 
     356              :          if (BTEST(file_type, bit_for_lnPgas)) then
     357              :             write(*,'(A)')
     358              :             write(*,*) 'MESA no longer supports models using lnPgas as a structure variable'
     359              :             write(*,'(A)')
     360              :             ierr = -1
     361              :             return
     362              :          end if
     363              : 
     364            0 :          s% net_name = trim(net_name)
     365            0 :          s% species = species
     366            0 :          s% initial_z = initial_z
     367              : 
     368            0 :          s% mstar = initial_mass*Msun
     369            0 :          if (s% xmstar < 0) then
     370            0 :             s% M_center = 0
     371            0 :             s% xmstar = s% mstar
     372              :          else
     373            0 :             s% M_center = s% mstar - s% xmstar
     374              :          end if
     375            0 :          if (is_bad(s% M_center)) then
     376            0 :             write(*,1) 'M_center mstar xmstar initial_mass', &
     377            0 :                s% M_center, s% mstar, s% xmstar, initial_mass
     378            0 :             call mesa_error(__FILE__,__LINE__,'do_read_saved_model')
     379              :          end if
     380              : 
     381            0 :          call set_net(s, s% net_name, ierr)
     382            0 :          if (ierr /= 0) then
     383              :             write(*,*) &
     384            0 :                'do_read_saved_model failed in set_net for net_name = ' // trim(s% net_name)
     385            0 :             return
     386              :          end if
     387              : 
     388            0 :          call set_var_info(s, ierr)
     389            0 :          if (ierr /= 0) then
     390            0 :             write(*,*) 'do_read_saved_model failed in set_var_info'
     391            0 :             return
     392              :          end if
     393              : 
     394              :          ! fixup chem names now that have nvar_hydro
     395            0 :          call set_chem_names(s)
     396              : 
     397            0 :          s% nz = nz
     398            0 :          call free_star_info_arrays(s)
     399            0 :          call allocate_star_info_arrays(s, ierr)
     400            0 :          if (ierr /= 0) then
     401            0 :             write(*,*) 'do_read_saved_model failed in allocate_star_info_arrays'
     402            0 :             return
     403              :          end if
     404              : 
     405            0 :          allocate(names(species), perm(species))
     406            0 :          call get_chem_col_names(s, iounit, species, names, perm, ierr)
     407            0 :          if (ierr /= 0) then
     408            0 :             deallocate(names, perm)
     409            0 :             write(*,*) 'do_read_saved_model failed in get_chem_col_names'
     410            0 :             return
     411              :          end if
     412              : 
     413            0 :          count = 0
     414            0 :          do i=1,species
     415            0 :             if (perm(i)==0) then
     416            0 :                count = count+1
     417            0 :                write(*,*) "Mod file has isotope ",trim(names(i)), " but that is not in the net"
     418              :             end if
     419              :          end do
     420            0 :          if (count/=0) call mesa_error(__FILE__,__LINE__)
     421              : 
     422            0 :          nvar = s% nvar_total
     423              :          call read1_model( &
     424              :                s, s% species, s% nvar_hydro, nz, iounit, &
     425              :                s% xh, s% xa, s% q, s% dq, s% omega, s% j_rot, &
     426            0 :                perm, ierr)
     427            0 :          deallocate(names, perm)
     428            0 :          if (ierr /= 0) then
     429            0 :             write(*,*) 'do_read_saved_model failed in read1_model'
     430            0 :             return
     431              :          end if
     432              : 
     433            0 :          do_read_prev = BTEST(file_type, bit_for_2models)
     434              :          if (ierr == 0) then
     435            0 :             if (do_read_prev) then
     436            0 :                call read_prev
     437              :             else
     438            0 :                s% generations = 1
     439              :             end if
     440              :          end if
     441              : 
     442            0 :          close(iounit)
     443              : 
     444              : 
     445              :          contains
     446              : 
     447              : 
     448            0 :          subroutine read_prev
     449              :             integer :: k
     450              : 
     451            0 :             do k=1, 3
     452            0 :                read(iounit, *, iostat=ierr)
     453            0 :                if (ierr /= 0) return
     454              :             end do
     455            0 :             call read_prev_properties
     456            0 :             if (ierr /= 0) return
     457              : 
     458              :             ! we do read_prev_properties to set initial timestep,
     459              :             ! but we don't use the previous model
     460              :             ! because we need to have other info about that isn't saved
     461              :             ! such as conv_vel and mixing_type
     462              : 
     463            0 :             s% generations = 1
     464              : 
     465            0 :          end subroutine read_prev
     466              : 
     467              : 
     468            0 :          subroutine read_prev_properties
     469              :             character (len=132) :: line
     470            0 :             real(dp) :: tmp, skip_val
     471              :             include 'formats'
     472              : 
     473            0 :             ierr = 0
     474            0 :             s% dt = -1
     475            0 :             s% mstar_old = -1
     476            0 :             s% dt_next = -1
     477            0 :             s% nz_old = -1
     478              : 
     479              :             do  ! until reach a blank line
     480            0 :                read(iounit, fmt='(a)', iostat=ierr) line
     481            0 :                if (ierr /= 0) return
     482              : 
     483            0 :                if (len_trim(line) == 0) exit  ! blank line
     484              : 
     485            0 :                if (match_keyword('previous n_shells', line, tmp)) then
     486            0 :                   s% nz_old = int(tmp)
     487            0 :                   cycle
     488              :                end if
     489              : 
     490            0 :                if (match_keyword('timestep (seconds)', line, s% dt)) then
     491              :                   cycle
     492              :                end if
     493              : 
     494            0 :                if (match_keyword('previous mass (grams)', line, s% mstar_old)) then
     495              :                   cycle
     496              :                end if
     497              : 
     498            0 :                if (match_keyword('dt_next (seconds)', line, s% dt_next)) then
     499              :                   cycle
     500              :                end if
     501              : 
     502            0 :                if (match_keyword('year_month_day_when_created', line, skip_val)) cycle
     503              : 
     504              :             end do
     505            0 :             if (s% dt < 0) then
     506            0 :                ierr = -1
     507            0 :                write(*, *) 'missing dt for previous model'
     508              :             end if
     509            0 :             if (s% mstar_old < 0) then
     510            0 :                ierr = -1
     511            0 :                write(*, *) 'missing mstar_old for previous model'
     512              :             end if
     513            0 :             if (s% dt_next < 0) then
     514            0 :                ierr = -1
     515            0 :                write(*, *) 'missing dt_next for previous model'
     516              :             end if
     517              : 
     518              :          end subroutine read_prev_properties
     519              : 
     520              : 
     521              :       end subroutine do_read_saved_model
     522              : 
     523              : 
     524            2 :       subroutine read1_model( &
     525              :             s, species, nvar_hydro, nz, iounit, &
     526            2 :             xh, xa, q, dq, omega, j_rot, &
     527            2 :             perm, ierr)
     528              :          use star_utils, only: set_qs
     529              :          use chem_def
     530              :          type (star_info), pointer :: s
     531              :          integer, intent(in) :: species, nvar_hydro, nz, iounit, perm(:)
     532              :          real(dp), dimension(:,:), intent(out) :: xh, xa
     533              :          real(dp), dimension(:), intent(out) :: &
     534              :             q, dq, omega, j_rot
     535              :          integer, intent(out) :: ierr
     536              : 
     537              :          integer :: j, k, n, i_lnd, i_lnT, i_lnR, i_lum, i_w, i_Hp, &
     538              :             i_Et_RSP, i_erad_RSP, i_Fr_RSP, i_v, i_u, i_alpha_RTI, ii
     539           46 :          real(dp), target :: vec_ary(species + nvar_hydro + max_increment)
     540              :          real(dp), pointer :: vec(:)
     541              :          integer :: nvec
     542              : 
     543              :          include 'formats'
     544              : 
     545            2 :          ierr = 0
     546            2 :          vec => vec_ary
     547              : 
     548            2 :          i_lnd = s% i_lnd
     549            2 :          i_lnT = s% i_lnT
     550            2 :          i_lnR = s% i_lnR
     551            2 :          i_lum = s% i_lum
     552            2 :          i_w = s% i_w
     553            2 :          i_Hp = s% i_Hp
     554            2 :          i_v = s% i_v
     555            2 :          i_u = s% i_u
     556            2 :          i_alpha_RTI = s% i_alpha_RTI
     557            2 :          i_Et_RSP = s% i_Et_RSP
     558            2 :          i_erad_RSP = s% i_erad_RSP
     559            2 :          i_Fr_RSP = s% i_Fr_RSP
     560              : 
     561              :          n = species + nvar_hydro + 1  ! + 1 is for dq
     562              :          if (s% rotation_flag) n = n+increment_for_rotation_flag  ! read omega
     563              :          if (s% have_j_rot) n = n+increment_for_have_j_rot  ! read j_rot
     564              :          if (s% have_mlt_vc) n = n+increment_for_have_mlt_vc
     565              :          if (s% D_omega_flag) n = n+increment_for_D_omega_flag  ! read D_omega
     566              :          if (s% am_nu_rot_flag) n = n+increment_for_am_nu_rot_flag  ! read am_nu_rot
     567              :          if (s% RTI_flag) n = n+increment_for_RTI_flag  ! read alpha_RTI
     568              :          if (s% RSP_flag) n = n+increment_for_RSP_flag  ! read RSP_et, erad, Fr
     569              :          if (s% RSP2_flag) n = n+increment_for_RSP2_flag  ! read w, Hp
     570              : 
     571            4 : !$omp critical (read1_model_loop)
     572              : ! make this a critical section to so don't have to dynamically allocate buf
     573         4932 :          do k = 1, nz
     574         4930 :             read(iounit,'(a)',iostat=ierr) buf
     575         4930 :             if (ierr /= 0) then
     576            0 :                write(*,3) 'read failed i', k, nz
     577            0 :                exit
     578              :             end if
     579         4930 :             call str_to_vector(buf, vec, nvec, ierr)
     580         4930 :             if (ierr /= 0) then
     581            0 :                write(*,*) 'str_to_vector failed'
     582            0 :                write(*,'(a,i8,1x,a)') 'buf', k, trim(buf)
     583            0 :                exit
     584              :             end if
     585         4930 :             j = int(vec(1))
     586         4930 :             if (j /= k) then
     587            0 :                ierr = -1
     588            0 :                write(*, *) 'error in reading model data   j /= k'
     589            0 :                write(*, *) 'species', species
     590            0 :                write(*, *) 'j', j
     591            0 :                write(*, *) 'k', k
     592            0 :                write(*,'(a,1x,a)') 'buf', trim(buf)
     593            0 :                exit
     594              :             end if
     595              :             j = 1
     596         4930 :             j=j+1; xh(i_lnd,k) = vec(j)
     597         4930 :             j=j+1; xh(i_lnT,k) = vec(j)
     598         4930 :             j=j+1; xh(i_lnR,k) = vec(j)
     599         4930 :             if (s% RSP_flag) then
     600            0 :                j=j+1; xh(i_Et_RSP,k) = vec(j)
     601            0 :                j=j+1; xh(i_erad_RSP,k) = vec(j)
     602            0 :                j=j+1; xh(i_Fr_RSP,k) = vec(j)
     603         4930 :             else if (s% RSP2_flag) then
     604            0 :                j=j+1; xh(i_w,k) = vec(j)
     605            0 :                j=j+1; xh(i_Hp,k) = vec(j)
     606              :             end if
     607         4930 :             if (i_lum /= 0) then
     608         4930 :                j=j+1; xh(i_lum,k) = vec(j)
     609              :             else
     610            0 :                j=j+1; s% L(k) = vec(j)
     611              :             end if
     612         4930 :             j=j+1; dq(k) = vec(j)
     613         4930 :             if (s% v_flag) then
     614            0 :                j=j+1; xh(i_v,k) = vec(j)
     615              :             end if
     616         4930 :             if (s% rotation_flag) then
     617            0 :                j=j+1; omega(k) = vec(j)
     618              :             end if
     619         4930 :             if (s% have_j_rot) then
     620              :                !NOTE: MESA version 10108 was first to store j_rot in saved files
     621            0 :                j=j+1; j_rot(k) = vec(j)
     622              :             end if
     623         4930 :             if (s% D_omega_flag) then
     624            0 :                j=j+1;  ! skip saving the file data
     625              :             end if
     626         4930 :             if (s% am_nu_rot_flag) then
     627            0 :                j=j+1;  ! skip saving the file data
     628              :             end if
     629         4930 :             if (s% u_flag) then
     630            0 :                j=j+1; xh(i_u,k) = vec(j)
     631              :             end if
     632         4930 :             if (s% RTI_flag) then
     633            0 :                j=j+1; xh(i_alpha_RTI,k) = vec(j)
     634              :             end if
     635         4930 :             if (s% have_mlt_vc) then
     636            0 :                j=j+1; s% mlt_vc(k) = vec(j); s% conv_vel(k) = vec(j)
     637              :             end if
     638         4930 :             if (j+species > nvec) then
     639            0 :                ierr = -1
     640            0 :                write(*, *) 'error in reading model data  j+species > nvec'
     641            0 :                write(*, *) 'j+species', j+species
     642            0 :                write(*, *) 'nvec', nvec
     643            0 :                write(*, *) 'j', j
     644            0 :                write(*, *) 'species', species
     645            0 :                write(*,'(a,1x,a)') 'buf', trim(buf)
     646            0 :                exit
     647              :             end if
     648        49302 :             do ii=1,species
     649        44370 :                xa(perm(ii),k) = vec(j+ii)
     650              :             end do
     651              :          end do
     652              : !$omp end critical (read1_model_loop)
     653            2 :          if (ierr /= 0) then
     654            0 :             write(*,*) 'read1_model_loop failed'
     655            0 :             return
     656              :          end if
     657              : 
     658            2 :          if (s% rotation_flag .and. .not. s% D_omega_flag) &
     659            0 :             s% D_omega(1:nz) = 0d0
     660              : 
     661            2 :          if (s% rotation_flag .and. .not. s% am_nu_rot_flag) &
     662            0 :             s% am_nu_rot(1:nz) = 0d0
     663              : 
     664            2 :          call set_qs(s, nz, q, dq, ierr)
     665            2 :          if (ierr /= 0) then
     666            0 :             write(*,*) 'set_qs failed in read1_model sum(dq)', sum(dq(1:nz))
     667            0 :             return
     668              :          end if
     669              : 
     670            2 :       end subroutine read1_model
     671              : 
     672              : 
     673            0 :       subroutine do_read_saved_model_number(fname, model_number, ierr)
     674              :          character (len=*), intent(in) :: fname
     675              :          integer, intent(inout) :: model_number
     676              :          integer, intent(out) :: ierr
     677              :          character (len=strlen) :: net_name
     678              :          integer :: species, n_shells, &
     679              :             num_retries, year_month_day_when_created
     680            0 :          real(dp) :: m_div_msun, initial_z, &
     681            0 :             mixing_length_alpha, star_age, &
     682            0 :             Teff, tau_factor, Tsurf_factor, opacity_factor, crystal_core_boundary_mass, &
     683            0 :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     684            0 :             xmstar, R_center, L_center, v_center, cumulative_energy_error
     685              :          call 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              :             Tsurf_factor, opacity_factor, crystal_core_boundary_mass, &
     691              :             xmstar, R_center, L_center, v_center, &
     692            0 :             cumulative_energy_error, num_retries, ierr)
     693            2 :       end subroutine do_read_saved_model_number
     694              : 
     695              : 
     696            0 :       subroutine do_read_saved_model_properties(fname, &
     697              :             net_name, species, n_shells, year_month_day_when_created, &
     698              :             m_div_msun, initial_z, mixing_length_alpha, &
     699              :             model_number, star_age, tau_factor, Teff, &
     700              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     701              :             Tsurf_factor, opacity_factor, crystal_core_boundary_mass, &
     702              :             xmstar, R_center, L_center, v_center, &
     703              :             cumulative_energy_error, num_retries, ierr)
     704              :          use utils_lib
     705              :          character (len=*), intent(in) :: fname
     706              :          character (len=*), intent(inout) :: net_name
     707              :          integer, intent(inout) :: species, n_shells, &
     708              :             year_month_day_when_created, num_retries, model_number
     709              :          real(dp), intent(inout) :: m_div_msun, initial_z, &
     710              :             mixing_length_alpha, star_age, tau_factor, Teff, &
     711              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     712              :             Tsurf_factor, opacity_factor, crystal_core_boundary_mass, &
     713              :             xmstar, R_center, L_center, v_center, cumulative_energy_error
     714              :          integer, intent(out) :: ierr
     715              :          integer :: iounit
     716            0 :          real(dp) :: initial_y
     717            0 :          ierr = 0
     718            0 :          open(newunit=iounit, file=trim(fname), action='read', status='old', iostat=ierr)
     719            0 :          if (ierr /= 0) then
     720            0 :             write(*, *) 'failed to open ' // trim(fname)
     721            0 :             return
     722              :          end if
     723            0 :          read(iounit, *, iostat=ierr)
     724            0 :          if (ierr /= 0) then
     725            0 :             close(iounit)
     726            0 :             return
     727              :          end if
     728            0 :          read(iounit, *, iostat=ierr)
     729            0 :          if (ierr /= 0) then
     730            0 :             close(iounit)
     731            0 :             return
     732              :          end if
     733              :          call read_properties(iounit, &
     734              :             net_name, species, n_shells, year_month_day_when_created, &
     735              :             m_div_msun, initial_z, initial_y, mixing_length_alpha, &
     736              :             model_number, star_age, tau_factor, Teff, &
     737              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     738              :             Tsurf_factor, opacity_factor, crystal_core_boundary_mass, &
     739              :             xmstar, R_center, L_center, v_center, &
     740            0 :             cumulative_energy_error, num_retries, ierr)
     741            0 :          close(iounit)
     742              :       end subroutine do_read_saved_model_properties
     743              : 
     744              : 
     745            0 :       subroutine do_read_net_name(iounit, net_name, ierr)
     746              :          integer, intent(in) :: iounit
     747              :          character (len=*), intent(inout) :: net_name
     748              :          integer, intent(out) :: ierr
     749              :          integer :: species, n_shells, &
     750              :             year_month_day_when_created, model_number, num_retries
     751            0 :          real(dp) :: m_div_msun, initial_z, initial_y, &
     752            0 :             mixing_length_alpha, star_age, tau_factor, Teff, &
     753            0 :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     754            0 :             Tsurf_factor, opacity_factor, crystal_core_boundary_mass, &
     755            0 :             xmstar, R_center, L_center, v_center, cumulative_energy_error
     756              :          call read_properties(iounit, &
     757              :             net_name, species, n_shells, year_month_day_when_created, &
     758              :             m_div_msun, initial_z, initial_y, mixing_length_alpha, &
     759              :             model_number, star_age, tau_factor, Teff, &
     760              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     761              :             Tsurf_factor, opacity_factor, crystal_core_boundary_mass, &
     762              :             xmstar, R_center, L_center, v_center, &
     763            0 :             cumulative_energy_error, num_retries, ierr)
     764            0 :       end subroutine do_read_net_name
     765              : 
     766              : 
     767            0 :       subroutine do_read_saved_model_age(fname, star_age, ierr)
     768              :          character (len=*), intent(in) :: fname
     769              :          real(dp), intent(inout) :: star_age
     770              :          integer, intent(out) :: ierr
     771              :          character (len=strlen) :: net_name
     772              :          integer :: species, n_shells, model_number, &
     773              :             num_retries, year_month_day_when_created
     774            0 :          real(dp) :: m_div_msun, initial_z, &
     775            0 :             mixing_length_alpha, cumulative_energy_error, &
     776            0 :             Teff, tau_factor, Tsurf_factor, &
     777            0 :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     778            0 :             opacity_factor, crystal_core_boundary_mass, &
     779            0 :             xmstar, R_center, L_center, v_center
     780              :          call do_read_saved_model_properties(fname, &
     781              :             net_name, species, n_shells, year_month_day_when_created, &
     782              :             m_div_msun, initial_z, 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              :             Tsurf_factor, opacity_factor, crystal_core_boundary_mass, &
     786              :             xmstar, R_center, L_center, v_center, &
     787            0 :             cumulative_energy_error, num_retries, ierr)
     788            0 :       end subroutine do_read_saved_model_age
     789              : 
     790              : 
     791           18 :       subroutine read_properties(iounit, &
     792              :             net_name, species, n_shells, year_month_day_when_created, &
     793              :             m_div_msun, initial_z, initial_y, mixing_length_alpha, &
     794              :             model_number, star_age, tau_factor, Teff, &
     795              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     796              :             Tsurf_factor, opacity_factor, crystal_core_boundary_mass, &
     797              :             xmstar, R_center, L_center, v_center, &
     798              :             cumulative_energy_error, num_retries, ierr)
     799              :          integer, intent(in) :: iounit
     800              :          character (len=*), intent(inout) :: net_name
     801              :          integer, intent(inout) :: species, n_shells, &
     802              :             year_month_day_when_created, model_number, num_retries
     803              :          real(dp), intent(inout) :: m_div_msun, initial_z, initial_y, &
     804              :             mixing_length_alpha, star_age, tau_factor, Teff, &
     805              :             power_nuc_burn, power_h_burn, power_he_burn, power_z_burn, power_photo, &
     806              :             Tsurf_factor, opacity_factor, crystal_core_boundary_mass, &
     807              :             xmstar, R_center, L_center, v_center, cumulative_energy_error
     808              :          integer, intent(out) :: ierr
     809              :          character (len=132) :: line
     810           18 :          real(dp) :: tmp
     811              :          ierr = 0
     812              :          do  ! until reach a blank line
     813           62 :             read(iounit, fmt='(a)', iostat=ierr) line
     814           62 :             if (ierr /= 0) return
     815           62 :             if (len_trim(line) == 0) return  ! blank line
     816           44 :             if (match_keyword_for_string('net_name', line, net_name)) then; cycle; end if
     817           43 :             if (match_keyword('species', line, tmp)) then; species = int(tmp); cycle; end if
     818           42 :             if (match_keyword('n_shells', line, tmp)) then; n_shells = int(tmp); cycle; end if
     819           25 :             if (match_keyword('model_number', line, tmp)) then; model_number = int(tmp); cycle; end if
     820           25 :             if (match_keyword('M/Msun', line, m_div_msun)) cycle
     821            8 :             if (match_keyword('star_age', line, star_age)) cycle
     822            8 :             if (match_keyword('initial_z', line, initial_z)) cycle
     823            7 :             if (match_keyword('initial_y', line, initial_y)) cycle
     824            6 :             if (match_keyword('mixing_length_alpha', line, mixing_length_alpha)) cycle
     825            6 :             if (match_keyword('tau_factor', line, tau_factor)) cycle
     826            6 :             if (match_keyword('Teff', line, Teff)) cycle
     827            6 :             if (match_keyword('power_nuc_burn', line, power_nuc_burn)) cycle
     828            6 :             if (match_keyword('power_h_burn', line, power_h_burn)) cycle
     829            6 :             if (match_keyword('power_he_burn', line, power_he_burn)) cycle
     830            6 :             if (match_keyword('power_z_burn', line, power_z_burn)) cycle
     831            6 :             if (match_keyword('power_photo', line, power_photo)) cycle
     832            6 :             if (match_keyword('Tsurf_factor', line, Tsurf_factor)) cycle
     833            6 :             if (match_keyword('opacity_factor', line, opacity_factor)) cycle
     834            6 :             if (match_keyword('crystal_core_boundary_mass', line, crystal_core_boundary_mass)) cycle
     835            6 :             if (match_keyword('xmstar', line, xmstar)) cycle
     836            6 :             if (match_keyword('R_center', line, R_center)) cycle
     837            6 :             if (match_keyword('L_center', line, L_center)) cycle
     838            6 :             if (match_keyword('v_center', line, v_center)) cycle
     839            6 :             if (match_keyword('cumulative_energy_error', line, cumulative_energy_error)) cycle
     840            6 :             if (match_keyword('year_month_day_when_created', line, tmp)) then
     841            1 :                year_month_day_when_created = int(tmp); cycle; end if
     842            5 :             if (match_keyword('tau_photosphere', line, tmp)) cycle
     843            5 :             if (match_keyword('num_retries', line, tmp)) then; num_retries = int(tmp); cycle; end if
     844              :          end do
     845              :       end subroutine read_properties
     846              : 
     847              : 
     848          270 :       logical function match_keyword(key, txt, value)
     849              :          ! returns true if leading non-blank part of txt is same as key.
     850              :          ! i.e., skips leading blanks in txt before testing equality.
     851              :          character (len=*), intent(in) :: key, txt
     852              :          real(dp), intent(inout) :: value
     853              :          integer :: i, j, k, ierr
     854          270 :          i = len(key)
     855          270 :          k = len(txt)
     856          270 :          j = 1
     857         6028 :          do while (j <= k .and. txt(j:j) == ' ')
     858         6028 :             j = j+1
     859              :          end do
     860          270 :          match_keyword = (txt(j:j+i-1) == key)
     861          270 :          ierr = 0
     862          270 :          if (match_keyword) then
     863           38 :             read(txt(j+i:k), fmt=*, iostat=ierr) value
     864          270 :             if (ierr /= 0) match_keyword = .false.
     865              :          end if
     866          270 :       end function match_keyword
     867              : 
     868              : 
     869           44 :       logical function match_keyword_for_string(key, txt, value)
     870              :          ! returns true if leading non-blank part of txt is same as key.
     871              :          ! i.e., skips leading blanks in txt before testing equality.
     872              :          character (len=*), intent(in) :: key, txt
     873              :          character (len=*), intent(inout) :: value
     874              :          integer :: i, j, k, str_len
     875              :          logical, parameter :: dbg = .false.
     876           44 :          i = len(key)
     877           44 :          k = len(txt)
     878           44 :          j = 1
     879         1099 :          do while (j <= k .and. txt(j:j) == ' ')
     880         1099 :             j = j+1
     881              :          end do
     882           44 :          match_keyword_for_string = (txt(j:j+i-1) == key)
     883           44 :          if (.not. match_keyword_for_string) return
     884              :          if (dbg) then
     885              :             write(*,*) 'matching ' // trim(key)
     886              :             write(*,*) 'txt ' // trim(txt)
     887              :          end if
     888              :          j = j+i
     889            4 :          do while (j <= k .and. txt(j:j) == ' ')
     890            4 :             j = j+1
     891              :          end do
     892            1 :          if (j > k) then
     893           44 :             match_keyword_for_string = .false.
     894              :             if (dbg) write(*,*) 'j > k'
     895              :             return
     896              :          end if
     897            1 :          if (txt(j:j) /= '''') then
     898           44 :             match_keyword_for_string = .false.
     899              :             if (dbg) write(*,*) 'no leading quote'
     900              :             return
     901              :          end if
     902            1 :          j = j+1
     903            1 :          i = 1
     904            1 :          str_len = len(value)
     905           10 :          do while (j <= k .and. txt(j:j) /= '''')
     906            9 :             value(i:i) = txt(j:j)
     907            9 :             i = i+1
     908           10 :             j = j+1
     909              :          end do
     910          248 :          do while (i <= str_len)
     911          247 :             value(i:i) = ' '
     912          247 :             i = i+1
     913              :          end do
     914              :          if (dbg) write(*,*) 'value <' // trim(value) // ">"
     915              :       end function match_keyword_for_string
     916              : 
     917              : 
     918           17 :       subroutine get_chem_col_names(s, iounit, species, names, perm, ierr)
     919              :          use chem_def, only: iso_name_length
     920              :          use chem_lib, only: chem_get_iso_id
     921              :          type (star_info), pointer :: s
     922              :          integer, intent(in) :: iounit, species
     923              :          character(len=iso_name_length), intent(out) :: names(species)
     924              :          integer, intent(out) :: perm(species)
     925              :          integer, intent(out) :: ierr
     926              : 
     927              :          character (len=50000) :: buffer
     928              :          character (len=20) :: string
     929              :          integer :: n, i, j1, j2, str_len, l, indx, j, num_found
     930              : 
     931           17 :          ierr = 0
     932           17 :          read(iounit,fmt='(a)',iostat=ierr) buffer
     933           17 :          if (ierr /= 0) return
     934              : 
     935           17 :          n = len_trim(buffer)
     936           17 :          i = 0
     937           17 :          num_found = 0
     938              :        token_loop: do  ! have non-empty buffer
     939         4964 :             i = i+1
     940         4964 :             if (i > n) then
     941            0 :                write(*,*) 'get_chem_col_names: failed to find all of the names'
     942            0 :                ierr = -1
     943            0 :                return
     944              :             end if
     945         4964 :             if (buffer(i:i) == char(9)) cycle token_loop  ! skip tabs
     946              :             select case(buffer(i:i))
     947              :                case (' ')
     948              :                   cycle token_loop  ! skip spaces
     949              :                case default
     950              :                   j1 = i; j2 = i
     951              :                   name_loop: do
     952          629 :                      if (i+1 > n) exit name_loop
     953          612 :                      if (buffer(i+1:i+1) == ' ') exit name_loop
     954          408 :                      if (buffer(i+1:i+1) == '(') exit name_loop
     955              :                      if (buffer(i+1:i+1) == ')') exit name_loop
     956              :                      if (buffer(i+1:i+1) == ',') exit name_loop
     957              :                      i = i+1
     958          221 :                      j2 = i
     959              :                   end do name_loop
     960          221 :                   str_len = len(string)
     961          221 :                   l = j2-j1+1
     962          221 :                   if (l > str_len) then
     963            0 :                      l = str_len
     964            0 :                      j2 = l+j1-1
     965              :                   end if
     966          221 :                   string(1:l) = buffer(j1:j2)
     967         4012 :                   do j = l+1, str_len
     968         4012 :                      string(j:j) = ' '
     969              :                   end do
     970              : 
     971          221 :                   indx = chem_get_iso_id(string)
     972              : 
     973         5185 :                   if (indx > 0) then
     974          136 :                      num_found = num_found+1
     975          136 :                      names(num_found) = trim(string)
     976          136 :                      perm(num_found) = s% net_iso(indx)
     977              :                      !write(*,*) trim(string), num_found, perm(num_found)
     978          136 :                      if (num_found == species) return
     979              :                   end if
     980              : 
     981              :             end select
     982              :          end do token_loop
     983              : 
     984           17 :       end subroutine get_chem_col_names
     985              : 
     986              :       end module read_model
        

Generated by: LCOV version 2.0-1