class MyCLI

Public Instance Methods

default(filename) click to toggle source
# File bin/mesa, line 180
  def default(filename)
    return unless check_for_mesa_dir
    defaults_dir = File.join(ENV['MESA_DIR'], 'star', 'defaults')
    suffix = case
    when %w{star_job controls pgstar}.include?(filename) then '.defaults'
    when %w{profile_columns history_columns}.include?(filename) then '.list'
    else
      puts <<-BAD_NAME
      Invalid file name: #{filename}. Must use 'star_job', 'controls', 'pgstar',
      'profile_columns', or 'history_columns'.
      BAD_NAME
      return
    end
    editor = ENV['EDITOR'] || 'less'
    system("#{editor} #{File.join(defaults_dir, filename)}#{suffix}")
  end
install(ver_number, custom_name=nil) click to toggle source
# File bin/mesa, line 212
def install(ver_number, custom_name=nil)

  # download proper version of MESA via SVN
  puts "Downloading MESA version #{ver_number}. This will take awhile."
  puts ''
  dir_name = custom_name || "mesa-r#{ver_number}"
  dir_name = File.absolute_path(dir_name)
  svn_uri = 'https://subversion.assembla.com/svn/mesa\^mesa/trunk'.freeze
  system("svn co -r #{ver_number} #{svn_uri} #{dir_name}")
  puts "Downloaded MESA version #{ver_number}."
  puts ''

  # install MESA
  unless have_mesasdk?
    puts "Installation failed: MESA SDK not set up properly."
    puts ''
    return
  end
  puts "Now installing. This will take awhile."
  puts ''
  start_dir = FileUtils::pwd
  FileUtils::cd dir_name
  system("./clean")
  system("./install")
  FileUtils::cd(start_dir)

  # detect login scripts
  shell = options[:shell]
  possible_scripts = ALL_POSSIBLE_SCRIPTS[shell] || []

  # stop if basic installation or if we don't know how to handle the shell

  if options[:basic] or possible_scripts.empty?
    if possible_scripts.empty? and not options[:basic]
      puts "Don't know how to adjust login scripts for shell #{shell}. Exiting."
      puts ''
    end
    puts "Installed MESA version #{ver_number} in #{dir_name}. Your login " +
    "scripts likely still need to be updated. See \"Set your environment " +
    "variables\" in http://mesa.sourceforge.net/prereqs.html for details."
    puts ''
    return
  end

  # detect login scripts
  possible_scripts.map! { |script| File.join(ENV['HOME'], script) }
  login_scripts = []
  possible_scripts.each do |script|
    login_scripts << script if File.exist?(script)
  end

  # update login scripts to set MESA_DIR properly
  have_fixed = login_scripts.empty?
  login_scripts.each do |script|
    fixed_this_one = adjust_script(script, dir_name, shell)
    have_fixed = fixed_this_one unless have_fixed
  end
end
new(new_dir="work") click to toggle source
# File bin/mesa, line 46
def new(new_dir="work")
  return unless check_for_mesa_dir
  work_dir = File.join(ENV['MESA_DIR'], 'star', 'work')
  new_loc = new_dir
  basename = File.basename(new_loc)
  FileUtils.cp_r(work_dir, new_loc, :verbose => true)
  unless options[:simple]
    old_inlist_name = File.join(new_loc, "inlist_project")
    short_name = "inlist_#{basename}"
    new_inlist_name = File.join(new_loc, short_name)
    File.rename(old_inlist_name, new_inlist_name)
    if options[:pgstar]
      create_control_inlist(new_loc, short_name, short_name, short_name)
    else
      create_control_inlist(new_loc, short_name, short_name)
    end
    create_ms_file(new_inlist_name, File.join(new_loc, basename + '.rb'))
  end
end
point(inlist) click to toggle source
# File bin/mesa, line 70
def point(inlist)
  if options[:pgstar]
    create_control_inlist(Dir.pwd, inlist, inlist, inlist)
  else
    create_control_inlist(Dir.pwd, inlist, inlist)
  end
end
rates(reaction, outfile = '') click to toggle source
# File bin/mesa, line 294
def rates(reaction, outfile = '')
  return unless check_for_mesa_dir
  cache_dir = File.join(ENV['MESA_DIR'], 'data', 'rates_data', 'cache')

  # set up regular expressions; allow for specific ending number (first case)
  # or leave it ambiguous (second case)
  if reaction =~ /_\d$/
    matcher = /r_?#{reaction}\.bin/
  else
    matcher = /r_?#{reaction}_(\d)\.bin/
  end

  # search for matching cache files. Return if none are found and find lowest
  # "number" cache file if multiple matches are found
  rate_files = Dir.entries(cache_dir).select { |f| f =~ matcher }
  case rate_files.length
  when 0
    puts "No reactions matching #{reaction} found in #{cache_dir}. Exiting."
    return
  when 1
    rate_file = File.join(cache_dir, rate_files[0])
  else
    min_num = nil
    rate_file = nil
    rate_files.each do |f|
      if min_num.nil? or matcher.match(f).captures.first.to_i < min_num
        min_num = matcher.match(f).captures.first.to_i
        rate_file = File.join(cache_dir, f)
      end
    end
  end

  data = ''
  # Execute the `show_rates` function and capture the output
  visit File.join(ENV['MESA_DIR'], 'rates', 'test') do
    data = `./show_rates #{rate_file}`
  end

  # scrub the output for poorly formatted floats

  lines = data.split("\n")[4..-1]
  t8 = []
  sigv = []
  float_matcher = /(\d\.\d+)D?(\-|\+)(\d+)/i
  lines.each do |line|
    new_t8, new_sigv = line.split
    new_t8 =~ float_matcher
    t8 << $1.to_f * (10**(exp_sign($2) * $3.to_i))
    new_sigv =~ float_matcher
    sigv << $1.to_f * (10**(exp_sign($2) * $3.to_i))
  end
  lines = t8.zip(sigv).map do |pair|
    sprintf("%-26.16e", pair[0]) + sprintf("%-26.16e", pair[1])
  end
  data = lines.join("\n")

  # save output to screen or to file
  if outfile.empty?
    puts data
  else
    File.open(outfile, 'w') do |f|
      f.puts data
    end
  end
end
test(test_case=nil, new_dir=nil) click to toggle source
# File bin/mesa, line 100
def test(test_case=nil, new_dir=nil)
  return unless check_for_mesa_dir

  test_suite_dir = File.join(ENV['MESA_DIR'], 'star', 'test_suite')
  if options[:list] or test_case.nil?
    puts "test cases in #{test_suite_dir}:"
    puts Dir.entries(test_suite_dir).select { |entry| entry[0] != '.' }
    return
  end

  work_dir = File.join(test_suite_dir, test_case)
  unless File.directory?(work_dir)
    puts "Unable to locate test suite case #{test_case} in directory " +
    test_suite_dir + ". Exiting."
    return
  end
  new_dir ||= File.join(FileUtils::pwd, test_case)
  FileUtils.cp_r(work_dir, new_dir, :verbose => true)
  inlist_files = Dir.glob(File.join(new_dir,"inlist*"))
  inlist_files.each do |inlist_file|

    # remove references to a new MESA_DIR
    inlist_lines = IO.readlines(inlist_file).reject do |line|
      line.downcase =~ /mesa_dir/
    end

    # remove references to inlist_test_suite
    bad_numbers = []
    bad_namelists = []
    inlist_lines.each do |line|
      if line =~ /inlist_test_suite/
        line =~ /extra_(.+)_inlist(\d)/
        bad_namelists << $1
        bad_numbers << $2
      end
    end
    bad_combos = bad_namelists.zip(bad_numbers)
    bad_words = []
    bad_combos.each do |namelist, number|
      bad_words << "read_extra_#{namelist}_inlist#{number}"
      bad_words << "extra_#{namelist}_inlist#{number}_name"
    end
    inlist_lines.reject! do |line|
      any_found = false
      bad_words.each do |bad_word|
        if line.include?(bad_word)
          any_found = true
          break
        end
      end
      any_found
    end

    # make local paths fully-qualified
    new_inlist_lines = inlist_lines.map do |line|
      if line =~ /((\.\.\/)+)/
        line.sub(/((\.\.\/)+)/, File.expand_path(File.join(work_dir, $1))+'/')
      else
        line
      end
    end

    # write out cleaned up inlist
    IO.write(inlist_file, new_inlist_lines.join)
  end

  # Clean up makefule
  makefile = File.join(new_dir, 'make', 'makefile')
  make_lines = IO.readlines(makefile)

  # Make sure MESA_DIR is not set in makefile
  make_lines.reject! { |line| line =~ /\A\s*MESA_DIR/ }

  # Make sure no local references to files in mesa tree are made
  make_lines.reject! { |line| line =~ /\.\.\/\.\./ }
  make_lines.reject! { |line| line.empty? }
  IO.write(makefile, make_lines.join)
end
version() click to toggle source
# File bin/mesa, line 19
def version
  return unless check_for_mesa_dir
  v_num = IO.read(File.join(ENV['MESA_DIR'], 'data', 'version_number')).to_i
  puts v_num
  return v_num
end

Private Instance Methods

add_assignment_to_script(script, dir_name, shell="bash") click to toggle source
# File bin/mesa, line 433
def add_assignment_to_script(script, dir_name, shell="bash")
  contents = IO.readlines(script)
  contents << "\n"
  contents << '# Added by mesa install tool on ' + Time.now.to_s + ".\n"
  contents << assignment_line('MESA_DIR', dir_name, shell)
  IO.write(script, contents.join)
  puts "Added MESA_DIR environment variable to #{script}."
end
adjust_script(script, dir_name, shell="bash") click to toggle source
# File bin/mesa, line 399
def adjust_script(script, dir_name, shell="bash")
  have_fixed = false
  case shell
  when %w{bash zsh}
    # read in script to array of strings
    contents = IO.readlines(script)

    # identify lines with MESA_DIR assignment
    lines_to_fix = []
    contents.each_with_index do |line, i|
      if line =~ /export MESA_DIR=.*/
        lines_to_fix << i
      end
    end

    # adjust MESA_DIR location and document changes
    lines_to_fix.reverse.each do |i|
      contents[i].sub!(/=.*/, "=#{dir_name}")
      contents.insert(i, '# ' + "Changed MESA_DIR to #{dir_name} on " +
        "#{Time.now.ctime} from mesa install script.\n")
    end

    # write out adjusted contents to file
    if have_fixed
      IO.write(script, contents.join)
      puts "Adjusted MESA_DIR variable in #{script}."
    end

  else
    raise "Cannot adjust #{script} because shell \"#{shell}\" is unsupported."
  end
  return have_fixed
end
assignment_line(var_name, value, shell) click to toggle source
# File bin/mesa, line 442
def assignment_line(var_name, value, shell)
  case shell
  when bash
    "export #{var_name}=#{value}\n"
  else
    raise "Cannot make assignments for shell #{shell} because #{shell} is " +
    "not a supported shell."
  end
end
check_for_mesa_dir() click to toggle source
# File bin/mesa, line 368
def check_for_mesa_dir
  return true if ENV['MESA_DIR']

  puts "WARNING: No environment variable MESA_DIR found. Exiting."
  return false
end
create_control_inlist(dir, star_job, controls, pgstar = "inlist_pgstar") click to toggle source
# File bin/mesa, line 386
def create_control_inlist(dir, star_job, controls, pgstar = "inlist_pgstar")
  Inlist.make_inlist(File.join(dir, 'inlist')) do
        read_extra_star_job_inlist1 true
        extra_star_job_inlist1_name star_job

        read_extra_controls_inlist1 true
        extra_controls_inlist1_name controls

        read_extra_pgstar_inlist1 true
        extra_pgstar_inlist1_name pgstar
  end
end
create_ms_file(inlist_name, ms_name) click to toggle source
# File bin/mesa, line 361
def create_ms_file(inlist_name, ms_name)
  ms_name += '.rb' unless ms_name[-3..-1] == '.rb'
  source = File.join(inlist_name)
  output = File.join(ms_name)
  Inlist.inlist_to_mesascript(source, output) if $use_mesascript
end
exp_sign(str) click to toggle source
# File bin/mesa, line 459
def exp_sign(str)
  case str
  when '-'
    return -1
  when '+'
    return 1
  else
    raise "invalid sign: #{exp_sign}"
  end
end
have_mesasdk?() click to toggle source
# File bin/mesa, line 375
def have_mesasdk?
  return true if ENV['MESASDK_ROOT']

  puts "No environment variable MESASDK_ROOT found. Be sure to download and "+
  "install the latest MESA SDK for your system from "+
  "http://www.astro.wisc.edu/~townsend/static.php?ref=mesasdk, being sure to"+
  "set the MESASDK_ROOT environment variable and sourcing the SDK " +
  "initialization script."
  return false
end
visit(new_dir) { || ... } click to toggle source
# File bin/mesa, line 452
def visit(new_dir)
  old_dir = Dir.pwd
  Dir.chdir(new_dir)
  yield
  Dir.chdir(old_dir)
end