class CodeRunner::Veritas

This module reads data from the new diagnostics output file <run_name>.out.nc.

It defines a new generic reader function which can read any variable in the new netcdf file using a standard set of index constraints

This is a customised subclass of the CodeRunner::Run class which allows CodeRunner to run and analyse the Vlasov Maxwell solver Veritas.

It generates the Veritas input file, and both analyses the results and allows easy plotting of them.

Public Class Methods

defaults_file_header() click to toggle source
# File lib/veritascrmod/veritas.rb, line 156
    def self.defaults_file_header
      <<EOF1
############################################################################
#                                                                          #
# Automatically generated defaults file for the Veritas CodeRunner module  #
#                                                                          #
# This defaults file specifies a set of defaults for Veritas which are     #
# used by CodeRunner to set up and run Veritas simulations.                #
#                                                                          #
############################################################################

# Created: #{Time.now.to_s}

@defaults_file_description = ""
EOF1
    end
defaults_file_text_from_input_file(input_file) click to toggle source
# File lib/veritascrmod/veritas.rb, line 449
def self.defaults_file_text_from_input_file(input_file)
        string = defaults_file_header

        hash = parse_input_file(input_file)
        #pp hash; exit
        #ep ['class', self.to_s, 'namelists', rcp.namelists.keys, 'code_long', rcp.code_long, 'namelist_hashes', rcp.namelists.values.map{|v| v.class}]
        rcp.namelists.each do |namelist, namelist_hash|
                #ep namelist
                if namelist_hash[:enumerator]  # ie. This is an indexed namelist
      #p namelist_hash[:enumerator]
                        enumerator = namelist_hash[:enumerator][:name]
                        enum_hash = hash.find{|nml, nmlh| nmlh[enumerator]}
                        next unless enum_hash
                        #pp enum_hash
                        enum = enum_hash[1][enumerator]
                        enum.times{|i| string << namelist_defaults_text(hash, namelist, namelist_hash, i+0)}
                else
                        string << namelist_defaults_text(hash, namelist, namelist_hash)
                end
        end
        string
end
modify_job_script(runner, runs_in, script) click to toggle source
# File lib/veritascrmod/veritas.rb, line 178
def self.modify_job_script(runner, runs_in, script)
  if CODE_OPTIONS[:veritas] and CODE_OPTIONS[:veritas][:list]
    if (list_size = CODE_OPTIONS[:veritas][:list]).kind_of? Integer
      raise "The total number of runs must be a multiple of the list size!" unless runs_in.size % list_size == 0
      pieces = runs_in.pieces(runs_in.size/list_size)
    else
      pieces = [runs_in]
    end
    script = ""
    pieces.each do |runs|
      #ep 'there is a list'
      FileUtils.makedirs('job_lists')
      jid = "#{runs[0].id}-#{runs[-1].id}"
      list_file = "../job_lists/veritas_list_#{jid}.list"
      Dir.chdir('job_chain_files') do
        File.open(list_file,'w') do |file|
          file.puts runs.size
          file.puts runs.map{|r| "../#{r.relative_directory}/\n#{r.run_name}"}.join("\n")
        end
      end
      raise "runs must all have the same nprocs" unless runs.map{|r| r.nprocs}.uniq.size == 1
      runs.each do |r|
        # Make sure the restart file name includes the relative directory for
        # list runs
        #reldir = r.relative_directory
        #puts rdir[0...reldir.size] == reldir, rdir[0...reldir.size], reldir
        #raise ""
        Dir.chdir(r.directory){r.write_input_file}
      end
      #np = runs[0].nprocs.split('x').map{|n| n.to_i}
      #np[0] *= runs.size
      #nprocs = np.map{|n| n.to_s}.join('x')
      #@runner.nprocs = nprocs
      @runner.nprocs = runs[0].nprocs
      ls = ListSubmitter.new(@runner, @runner.nprocs, list_file, jid)
      script <<  'cd job_chain_files; '
      script << ls.run_command
    end
  end
  return script
end

Public Instance Methods

asquared2d_graphkit(options) click to toggle source
# File lib/veritascrmod/veritas.rb, line 262
def asquared2d_graphkit(options)
  real_space_2d_graphkit(options.dup.absorb(signal: 'asquared'))
end
asquared_graphkit(options) click to toggle source
# File lib/veritascrmod/veritas.rb, line 250
def asquared_graphkit(options)
  real_space_graphkit(signal: 'asquared')
end
charge_graphkit(options) click to toggle source
# File lib/veritascrmod/veritas.rb, line 259
def charge_graphkit(options)
  real_space_graphkit(options.dup.absorb(signal: 'charge'))
end
dist_fn_graphkit(options) click to toggle source
# File lib/veritascrmod/veritas.rb, line 345
def dist_fn_graphkit(options)
  t = options[:t]
  p = options[:particle]
  raise "Please supply :t" unless t
  raise "Please supply :particle" unless p
  mat = openncfile do |f| 
    m = GSL::Matrix.alloc(f.dim("x_finest").length, f.dim("p_finest").length)
    nlevels = f.dim("level").length
    nlevels.times.to_a.reverse.each do |l|
    #[2].each do |l|
      factor = (@r||2)**l 
      # NB the Ruby netCDF interface is (very annoyingly) written in column major (Fortran) style
      nrectangles = f.var("level_rnum").get('index'=> [l,p,t])[0]
      nrectangles.times do |r|
        urid = f.var('urid').get('index'=>[r,l,p,t])[0]
        md = f.var('rectangle_metadata').get('start'=>[0,0,urid], 'end'=>[-1,-1,urid])[true,true,0]
        x_indices = f.var("integer_blob_data").get('start'=>[md[0,0]], 'end'=>[md[1,0]])
        p_indices = f.var("integer_blob_data").get('start'=>[md[0,1]], 'end'=>[md[1,1]])
        fdata = f.var("double_blob_data").get('start'=>[md[0,2]], 'end'=>[md[1,2]])
        p_size = md[1,1] - md[0,1] + 1
        x_indices.to_a.each_with_index do |ixglobal,ixrec|
          p_indices.to_a.each_with_index do |ipglobal,iprec|
            index = ixrec*p_size + iprec
            #ep ["index", index, "fsize", md[1,2]-md[0,2]+1, 'ix', ixrec, 'ip', iprec, 'p_size', p_size, 'level', l, 'ixglobal', ixglobal, 'factor', factor]
            for i in 0...factor
              for j in 0...factor
                m[ixglobal*factor+i,ipglobal*factor+j] = fdata[index]
              end 
            end
          end
        end
      end
    end
    m
  end
  #mat = mat.log if (options[:log])
  shape = mat.shape
  p 'shape', mat.shape
  x = shape[0].times.to_a.reverse
  t = shape[1].times.to_a.reverse
  kit = GraphKit.quick_create([x, t, mat])
  #kit.live = true
  kit.gp.view = "map"
  kit.gp.palette = "rgb 23,28,3"
  kit.data[0].gp.with = "pm3d"
  kit
end
efieldlong_graphkit(options) click to toggle source
# File lib/veritascrmod/veritas.rb, line 253
def efieldlong_graphkit(options)
  real_space_graphkit(signal: 'Efieldlong')
end
ey_graphkit(options) click to toggle source
# File lib/veritascrmod/veritas.rb, line 256
def ey_graphkit(options)
  real_space_graphkit(signal: 'Ey')
end
generate_input_file() click to toggle source

This is a hook which gets called just before submitting a simulation. It sets up the folder and generates any necessary input files.

# File lib/veritascrmod/veritas.rb, line 72
def generate_input_file
    FileUtils.makedirs("output/rectangleData")
    #@run_name += "_t"
    if @restart_id
      @runner.run_list[@restart_id].restart(self)
    end
    #if uses_ecom?
      #setup_ecom
    #elsif uses_chease?
      #setup_chease
    #end
    #check_parameters
    write_input_file
end
get_status() click to toggle source
# File lib/veritascrmod/veritas.rb, line 124
def get_status
  if @running
    @status = :Running
  else
    @status = :Complete
  end
end
graphkit(name, options) click to toggle source
# File lib/veritascrmod/veritas.rb, line 240
def graphkit(name, options)
  if name =~ /^nc/
    smart_graphkit(options.absorb(graphkit_name: name))
  else
    send((name + '_graphkit').to_sym, options)
  end
end
input_file_extension() click to toggle source
# File lib/veritascrmod/veritas.rb, line 174
def input_file_extension
  '.in'
end
input_file_header() click to toggle source
# File lib/veritascrmod/veritas.rb, line 134
    def input_file_header
      <<EOF
!==============================================================================
!     Veritas INPUT FILE automatically generated by CodeRunner
!==============================================================================
!
!  Veritas is a 1D continuum solver for the Vlasov-Maxwell system
!
!   See http://ft.nephy.chalmers.se/veritas/
!
!  CodeRunner is a framework for the automated running and analysis
!  of large simulations.
!
!   See http://coderunner.sourceforge.net
!
!  Created #{Time.now.to_s}
!      by CodeRunner version #{CodeRunner::CODE_RUNNER_VERSION.to_s}
!
!==============================================================================

EOF
    end
input_file_text() click to toggle source

Override CodeRunner for 0-based# Override CodeRunner for 0-based# Override CodeRunner for 0-based

# File lib/veritascrmod/veritas.rb, line 393
def input_file_text
        text = input_file_header
        rcp.namelists.each do |namelist, hash|
                next if hash[:should_include].kind_of? String and not eval(hash[:should_include])
                if en = hash[:enumerator] # Single = is deliberate!
                        next unless send(en[:name])
                        send(en[:name]).times do |i|
                                next unless hash[:variables].keys.inject(false){|b, v| b or !send(v+"_#{i+0}".to_sym).nil?} # i.e. at least one variable must be non-nil
                                text << namelist_text(namelist, i+0)
                        end
                else
                        next unless hash[:variables].keys.inject(false){|b, v| b or !send(v).nil?} # i.e. at least one variable must be non-nil
                        text << namelist_text(namelist)
                end
                        
                        
        end
        text
end
namelist_text(namelist, enum = nil) click to toggle source
# File lib/veritascrmod/veritas.rb, line 412
def namelist_text(namelist, enum = nil)
        hash = rcp.namelists[namelist]
        text = ""
        ext = enum ? "_#{enum}" : ""
        text << "!#{'='*30}\n!#{hash[:description]} #{enum} \n!#{'='*30}\n" if hash[:description]
        text << "&#{namelist}#{ext}\n"
        hash[:variables].each do |var, var_hash|
                code_var = (var_hash[:code_name] or var)
                cr_var = var+ext.to_sym 
                value = send(cr_var)
                if send(cr_var) and (not var_hash[:should_include] or  eval(var_hash[:should_include]))
                        if value.kind_of? Array
                                value.each_with_index do |v, i|
                                        output = formatted_variable_output(v)
                                        text << " #{code_var}(#{i+0}) = #{output} #{var_hash[:description] ? "! #{var_hash[:description]}": ""}\n"
                                end
                        else
                                output = formatted_variable_output(value)
                                text << " #{code_var} = #{output} #{var_hash[:description] ? "! #{var_hash[:description]}": ""}\n"
                        end
                elsif rcp.namelists_to_print_not_specified? and rcp.namelists_to_print_not_specified.include?(namelist) 
                        text << "  ! #{code_var} not specified --- #{var_hash[:description]}\n"
                end
        end
        text << "/\n\n"
        text
end
netcdf_smart_reader() click to toggle source
# File lib/veritascrmod/read_netcdf.rb, line 118
def netcdf_smart_reader
end
openncfile() { |file| ... } click to toggle source
# File lib/veritascrmod/veritas.rb, line 265
def openncfile
  require 'numru/netcdf'
  res = nil
  file = NumRu::NetCDF.open("#@directory/#@run_name.nc")
  res = yield(file)
  file.close
  res
end
parameter_string() click to toggle source

Parameters which follow the Veritas executable, in this case just the input file.

# File lib/veritascrmod/veritas.rb, line 103
def parameter_string
  @run_name + ".in"
end
parameter_transition() click to toggle source
# File lib/veritascrmod/veritas.rb, line 107
def parameter_transition
end
potential_graphkit(options) click to toggle source
# File lib/veritascrmod/veritas.rb, line 247
def potential_graphkit(options)
  real_space_graphkit(signal: 'phi')
end
print_out_line() click to toggle source

A hook which gets called when printing the standard run information to the screen using the status command.

process_directory_code_specific() click to toggle source

This method, as its name suggests, is called whenever CodeRunner is asked to analyse a run directory. This happens if the run status is not :Complete, or if the user has specified recalc_all(-A on the command line) or reprocess_all (-a on the command line).

# File lib/veritascrmod/veritas.rb, line 116
def process_directory_code_specific
  get_status
  if FileTest.exist? 'output/time.txt'
    @nlines = File.read('output/time.txt').split("\n").size
  end

end
real_space_2d_graphkit(options) click to toggle source
# File lib/veritascrmod/veritas.rb, line 292
def real_space_2d_graphkit(options)
  t = options[:t]
  raise "Please supply :t" unless t
  Dir.chdir(@directory) do
    vec = openncfile{|f| f.var(options[:signal]).get('start'=>[0,t], 'end'=>[-1,t])} 
    mat = GSL::Matrix.alloc(vec.size, 2)
    for i in 0...vec.size
      mat[i,0] = mat[i,1] = vec[i]
    end
    shape = mat.shape
    p 'shape', mat.shape
    x = shape[0].times.to_a
    t = shape[1].times.to_a
    kit = GraphKit.quick_create([x, t, mat])
    kit.gp.view = "map"
    kit.gp.palette = "rgb 23,28,3"
    kit.data[0].gp.with = "pm3d"
    kit
  end
end
real_space_graphkit(options) click to toggle source
# File lib/veritascrmod/veritas.rb, line 273
def real_space_graphkit(options)
  Dir.chdir(@directory) do
    if pt = options[:particle]
      mat = openncfile{|f| f.var(options[:signal]).get('start'=>[0,pt,0], 'end'=>[-1,pt,-1])}[true,0,true]
    else
      raise "Please specify particle" if ['charge'].include? options[:signal]
      mat = openncfile{|f| f.var(options[:signal]).get} 
    end
    shape = mat.shape
    p 'shape', mat.shape
    x = shape[0].times.to_a
    t = shape[1].times.to_a
    kit = GraphKit.quick_create([x, t, mat])
    kit.gp.view = "map"
    kit.gp.palette = "rgb 23,28,3"
    kit.data[0].gp.with = "pm3d"
    kit
  end
end
restart(new_run) click to toggle source

Modify new_run so that it becomes a restart of self. Adusts all the parameters of the new run to be equal to the parameters of the run that calls this function, and sets up its run name correctly

# File lib/veritascrmod/veritas.rb, line 67
def restart(new_run)
  (rcp.variables).each{|v| new_run.set(v, send(v)) if send(v) or new_run.send(v)}
  raise "restart not implemented yet"
end
smart_graphkit(options) click to toggle source
# File lib/veritascrmod/read_netcdf.rb, line 124
def smart_graphkit(options)
  case options[:command]
  when :help
    "A smart graphkit is a direct plot of a given variable from the new netcdf file. The name of the graphkit is the name of the variable prefixed by 'cdf_'. To plot, for example, the heat flux vs time, you would give the graph name cdf_heat_flux_tot. You can use index specifiers in the the options; for example, to plot the potential as a function of kx and ky for a given time index, you would use the graph name cdf_phi2_by_mode, and the options {t_index: n}. To plot the potential as function of kx for a given ky and time would use the options {t_index, n, Y_index: m}. For each dimension you can specify the index, or a minium and/or maximum."
  when :options
    [:nmat_index, :t_index, :tspec_index, :iter_index]
  else
    case options[:graphkit_name]
    when /_vs_/
      kits = options[:graphkit_name].sub(/^nc_/, '').split(/_vs_/).map{|n| netcdf_smart_reader.graphkit(n, options)}
      kit = kits[-1]
      raise SmartGraphKitError.new("Number of axes does not match number of variables") if kits.size != kit.naxes
      for i in 0...kit.data.size
        if kit.naxes > 1
          kit.data[i].x = kits[0].data[i].y
        end
        if kit.naxes > 2
          kit.data[i].x = kits[0].data[i].z
          kit.data[i].y = kits[1].data[i].z
        end
      end
      kit.autocreate
      kit
    else
      openncfile{|f| NetcdfSmartReader.new(f).graphkit(options[:graphkit_name].sub(/^nc_/, ''), options)}
    end
  end
end
vim_output() click to toggle source
# File lib/veritascrmod/veritas.rb, line 92
def vim_output
  system "vim -Ro #{output_file} #{error_file}"
end
Also aliased as: vo
vo()
Alias for: vim_output
vspace_dist_fn_graphkit(options) click to toggle source
# File lib/veritascrmod/veritas.rb, line 332
def vspace_dist_fn_graphkit(options)
  kit = dist_fn_graphkit(options)
  mat = kit.data[0].z.data
  pvec = GSL::Vector.alloc(mat.shape[1])
  pvec = 0.0
  for i in 0...mat.shape[0]
    pvec = pvec + mat.row(i)
  end
  kit2 = GraphKit.quick_create([kit.data[0].y.data, pvec])
  kit2.data[0].gp.with = "lp"
  kit2.gp.logscale = "y"
  kit2
end
waveandparticles_graphkit(options) click to toggle source
# File lib/veritascrmod/veritas.rb, line 312
def waveandparticles_graphkit(options)
  kit = GraphKit::MultiKit.new([
    asquared2d_graphkit(options),
    dist_fn_graphkit(options)
  ])
  kit[0].gp.size = "1.0,0.3"
  kit[0].gp.origin = "0.0,0.7"
  kit[1].gp.size = "1.0,0.9"
  kit[1].gp.origin = "0.0,-0.1"
  kit[1].gp.cbrange = "[0:]"
  kit.each do |k|
    k.key="off"
    k.xlabel=nil
    k.ylabel=nil
    k.gp.xtics = "unset"
    k.gp.ytics = "unset"
    k.title = nil
  end
  kit
end
write_input_file() click to toggle source

This command uses the infrastructure provided by Run::FortranNamelist, provided by CodeRunner itself.

# File lib/veritascrmod/veritas.rb, line 98
def write_input_file
  File.open(@run_name + ".in", 'w'){|file| file.puts input_file_text}
end