Skip to content

Commit

Permalink
Fix color file reading when / is in the coloumn names
Browse files Browse the repository at this point in the history
Unformatted reads in fortran with / stop rerading after the /
/ is quite common in color files for [fe/h]. So rewrite the line reading
to do the splt ourselves with a new split_line subroutine in utisl_lib.

Warn other people about this fortran "feature" in the code_style

Fixes MESAHub#379
  • Loading branch information
rjfarmer committed Mar 16, 2022
1 parent 770ac5c commit 4eb1575
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 17 deletions.
29 changes: 12 additions & 17 deletions colors/private/mod_colors.f90
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ subroutine do_colors_init(num_files,fnames,num_colors,ierr)
character(len=*),dimension(:),intent(in) :: fnames
character(len=strlen) :: fname
type (lgt_list), pointer :: thead =>null()
character(len=strlen),dimension(:),pointer :: col_names=>null()

integer, intent(out) :: ierr
integer :: i
Expand Down Expand Up @@ -81,10 +80,8 @@ subroutine do_colors_init(num_files,fnames,num_colors,ierr)
ierr=-1
return
end if

col_names => thead_all(i)%color_names

call init_colors(fname,thead,col_names,thead_all(i)%n_colors,ierr)
call init_colors(fname,thead,thead_all(i)%color_names,thead_all(i)%n_colors,ierr)

thead_all(i)%thead=>thead
bc_total_num_colors=bc_total_num_colors+thead_all(i)%n_colors
Expand All @@ -100,7 +97,7 @@ subroutine init_colors(fname, thead, col_names, n_colors, ierr)
integer, intent(out) :: ierr
character(len=*),intent(in) :: fname
type (lgt_list), pointer :: thead
character(len=*),dimension(:),pointer :: col_names
character(len=*),dimension(:) :: col_names
integer, intent(in) :: n_colors
call Read_Colors_Data(fname, thead, col_names, n_colors, ierr)
end subroutine init_colors
Expand Down Expand Up @@ -217,10 +214,10 @@ subroutine Read_One_Colors_Data(fname, thead, n_colors, col_names, ierr)
type (lgt_list), pointer :: tlist => null()
type (lgz_list), pointer :: zlist => null()
real(dp), dimension(max_num_bcs_per_file) :: colors
character(len=*),dimension(:),pointer,intent(inout) :: col_names

character(len=strlen) :: tmp
character(len=*),dimension(:),intent(out) :: col_names
character(len=256) :: tmp_cols(3+n_colors)

character(len=4096) :: tmp
integer :: num_entries, num_made, IO_UBV

include 'formats'
Expand All @@ -243,16 +240,14 @@ subroutine Read_One_Colors_Data(fname, thead, n_colors, col_names, ierr)
ierr = 0
num_entries = 0
cnt = 0
tmp = ''
!First line should be a header and containing the name of the colours
!#teff logg m_div_h col_1 col_2 etc
read(IO_UBV,fmt=*,iostat=ios) tmp,tmp,tmp,col_names(1:n_colors)
read(IO_UBV,'(a)') tmp

call split_line(tmp,3+n_colors,tmp_cols)

if(index(tmp,'[')/=0) then
write(*,*) 'Do not write metallicity as [Fe/H] use m_div_h in ',trim(fname)
! https://github.com/MESAHub/mesa/issues/379
! Some reason if we have [Fe/H] in tmp we start reading a completly different file
ierr = 1; return
end if
col_names(1:n_colors) = tmp_cols(4:n_colors+3)

do while (.true.)
read(IO_UBV,fmt=*,iostat=ios) lgt, lgg, lgz, colors(1:n_colors)
Expand Down Expand Up @@ -327,7 +322,7 @@ subroutine Read_Colors_Data(fname, thead, col_names, n_colors, ierr)
integer, intent(out) :: ierr ! 0 means ok
type (lgt_list), pointer,intent(inout) :: thead
character (len=*),intent(in) :: fname
character(len=*),dimension(:),pointer :: col_names
character(len=*),dimension(:),intent(out) :: col_names
integer, intent(in) :: n_colors

Call Read_One_Colors_Data(fname, thead, n_colors, col_names, ierr)
Expand Down
14 changes: 14 additions & 0 deletions docs/source/developing/code_style.rst
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,20 @@ different compilers.

Some helpful formats are provided in ``include/formats``.

Unformatted reads
-----------------

.. code-block:: fortran
read(unit,*) x,y,z
Should be avoided when the variables that are strings. This is becuase if the string contains a / (forward-slash) then when doing a unformatted
read frotran will stop reading the line.

Either build a full format statement or read the line into one string and split on whitespace. There is also a function ``split_line`` in
``utils_lib.f90`` that can be used to split a line up based on whitespace.


Constants
---------
Expand Down
34 changes: 34 additions & 0 deletions utils/public/utils_lib.f90
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,40 @@ character(len=strlen) function switch_str(str1,str2,flag)

end function switch_str

subroutine split_line(line, num, out)
! Given a string line, split on whitespace, into num sub-strings storing them in out
character(len=*),intent(in) :: line
integer, intent(in) :: num
character(len=*),dimension(:) :: out

integer :: i,kstart,k

if(size(out)<num) call mesa_error(__FILE__,__LINE__,'out array not large enough for num sub-strings')

out = ''

k = 1
kstart = 1
outer: do i=1, num
inner: do
if(line(k:k)==' ' .and. line(k+1:k+1)==' ' .and. k < len(line)) then
k = k+1
cycle inner
end if

if(line(k:k)==' ' .or. k > len(line))then
!write(*,*) '*',i,kstart,k,line(kstart:k-1)
out(i) = line(kstart:k-1)
k = k+1
kstart = k
cycle outer
end if
k = k + 1
end do inner
end do outer

end subroutine split_line


! backward compatibility so Bill can debug older versions of files without changing these calls
logical function is_bad_num(x)
Expand Down

0 comments on commit 4eb1575

Please sign in to comment.