From ./rn to do_evolve_step

The "Nuts and Bolts" section of the Appendix of the second MESA Instrument paper (starting on page 34) describes how MESA evolves a star for a single step using the top level routine 'do_evolve_step'. This is an excellent high-level overview of how MESA works that came out of last year's summer school.

But how does the code get from you typing ./rn on the command line to actually executing do_evolve_step? The presentation on Tuesday night was a little too impromptu and I made a real hash of it. (Apologies for wasting your time.) Hopefully this will be a bit clearer and fill in some of the gaps.

Let's make a new copy of a MESA working directory and poke around a bit.

cp -r $MESA_DIR/star/work my_work
cd my_work

The executable file that actually gets run when we run MESA is called 'star'. We'll see how it is generated in just a bit. It is important to know that the scripts ./rn and ./re are just convenient wrappers for invoking 'star'.

So let's take a look at ./rn, with some added commentary

#!/bin/bash

# print the SVN revision of the version of MESA that is being used
if [ ! -z "${MESA_DIR}" ]; then
  svn info $MESA_DIR > .svninfo
  grep "Revision" .svninfo
fi

# get rid of any file lingering from a previous restart.  the presence
# or absence of a file with this name is how MESA determines whether
# it is supposed to be doing a restart.  how this works will make more
# sense once you look at ./re
rm -f restart_photo

# print the date & time; run MESA; print the date & time
date;./star;date

And now let's do the same for ./re, which is the command that one uses to resume MESA runs from a saved binary ("photos") file.

#!/bin/bash

# this function checks that the exit code of the previous command.  if
# it did not indicate that it sucessfully completed, the script exits
function check_okay {
    if [ $? -ne 0 ]
    then
        exit 1
    fi
}

# print the first argument given to the bash script
# you invoke ./re as
#   $ ./re <filename>
# where <filename> is one of the files in the photos directory
# so this displays the filename passed to the script.
echo $1

# try to copy the given file from photos/ to a file named
# restart_photo.  if this fails, exit.
cp photos/$1 restart_photo
check_okay

# we see that star is invoked in exactly the same way as in ./rn so
# MESA determines whether a restart is occuring based on the presence
# of a file named restart_photo.  that's why the ./rn script made sure
# to remove such a file before invoking star!
date;./star;date

So how do we get this all-important 'star' executable file in the first place? It is generated by running ./mk which then uses a standard MESA makefile to compile the code. This makefile compiles three files

src/run.f
<MESA_DIR>/star/job/run_star.f
src/run_star_extras.f

and then links with lot of other things to make the 'star' executable.

We looked at run_star_extras.f on Monday night, so now lets look at run.f which is what contains the fortran program declaration for 'star'.

program run
use run_star_support, only: do_read_star_job
use run_star, only: do_run_star

implicit none

integer :: ierr
character (len=32) :: inlist_fname

ierr = 0
! your main inlist file must be called 'inlist'
inlist_fname = 'inlist'

! read the star_job namelist from the inlist
call do_read_star_job(inlist_fname, ierr)
if (ierr /= 0) stop 1

! actually run the star calculations
call do_run_star(inlist_fname)

end program

So this program sends us off to 'do_run_star' in the star/job/run_star.f file and down the rabbit hole we go!

subroutine do_run_star(inlist_fname_arg)
   use run_star_support, only: run1_star
   use run_star_extras
   use star_lib, only: star_shutdown
   character (len=*) :: inlist_fname_arg
   optional inlist_fname_arg
   logical, parameter :: do_pre_load = .true., do_free_star = .true., &
      restart_okay = .true.
   integer :: id, ierr
   logical :: restart
   character (len=256) :: inlist_fname

   ! call your main inlist file 'inlist' unless you choose otherwise
   if (present(inlist_fname_arg)) then
      inlist_fname = inlist_fname_arg
   else
      inlist_fname = 'inlist'
   end if

   ! run the evolution for a single star
   call run1_star( &
      do_pre_load, do_free_star, restart_okay, &
      id, restart, &
      extras_controls, &
      extras_startup, &
      extras_check_model, &
      how_many_extra_history_columns, &
      data_for_extra_history_columns, &
      how_many_extra_profile_columns, &
      data_for_extra_profile_columns, &
      extras_finish_step, &
      extras_after_evolve, &
      ierr, &
      inlist_fname)

   ! clean up after we are done
   call star_shutdown
end subroutine do_run_star

So now the next step is to go look at 'run1_star', which comes from star/job/run_star_support.f. But that's where things really start to happen: the subroutine is over 500 lines long. I provided a pseudocode outline of that function in Monday's run_star_extras.f tutorial, so I urge you to go take a look at that.

Smack dab in the middle of the step_loop in 'run1_star' is a call to 'star_evolve_step', which comes from star/public/star_lib.f. Now we've made it deep enough to star seeing our star program interact with the star module.

In general, each of the modules in MESA (which are the many sub-directories that you see in the main mesa/ directory) are structured in the same way. They provide public constants and subroutines for other programs or modules to interact with: these live in <modulename>/public. Then these public methods will call private methods (which live in <modulename>/private) and it i these private methods where all the work happens.

We can see this clearly by looking at 'star_evolve_step'

! this routine takes one step in the evolution.
! when it returns successfully (i.e, with value = keep_going), the data
! describing the new model can be found in the variables defined in star_def.
integer function star_evolve_step(id, first_try, just_did_backup)
   ! returns either keep_going, redo, retry, backup, or terminate
   use star_def, only: terminate
   use star_def, only: star_info
   use evolve, only: do_evolve_step
   integer, intent(in) :: id
   logical, intent(in) :: first_try 
      ! true on the first try to take this step
      ! false if this is a repeat for a retry or a backup
   logical, intent(in) :: just_did_backup
   type (star_info), pointer :: s
   integer :: ierr
   star_evolve_step = terminate
   ierr = 0
   call star_ptr(id, s, ierr)
   if (ierr /= 0) return
   star_evolve_step = do_evolve_step(id, first_try, just_did_backup)
end function star_evolve_step

which doesn't do too much more than hand us off to 'do_evolve_step', the function that is quite nicely described in the MESA instrument paper. So to keep digging into MESA take a look at that.

Author: Josiah Schwab

Created: 2013-08-13 Tue 22:22

Emacs 24.3.1 (Org mode 8.0.7)

Validate XHTML 1.0