Class: CodeRunner::Veritas

Inherits:
Run::FortranNamelist
  • Object
show all
Defined in:
lib/veritascrmod/veritas.rb,
lib/veritascrmod/read_netcdf.rb

Overview

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

Defined Under Namespace

Classes: ListSubmitter, NetcdfSmartReader, SmartGraphKitError

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.defaults_file_headerObject



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# 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) ⇒ Object



449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
# 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) ⇒ Object



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# 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

Instance Method Details

#asquared2d_graphkit(options) ⇒ Object



262
263
264
# File 'lib/veritascrmod/veritas.rb', line 262

def asquared2d_graphkit(options)
  real_space_2d_graphkit(options.dup.absorb(signal: 'asquared'))
end

#asquared_graphkit(options) ⇒ Object



250
251
252
# File 'lib/veritascrmod/veritas.rb', line 250

def asquared_graphkit(options)
  real_space_graphkit(signal: 'asquared')
end

#charge_graphkit(options) ⇒ Object



259
260
261
# File 'lib/veritascrmod/veritas.rb', line 259

def charge_graphkit(options)
  real_space_graphkit(options.dup.absorb(signal: 'charge'))
end

#dist_fn_graphkit(options) ⇒ Object



345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
# 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) ⇒ Object



253
254
255
# File 'lib/veritascrmod/veritas.rb', line 253

def efieldlong_graphkit(options)
  real_space_graphkit(signal: 'Efieldlong')
end

#ey_graphkit(options) ⇒ Object



256
257
258
# File 'lib/veritascrmod/veritas.rb', line 256

def ey_graphkit(options)
  real_space_graphkit(signal: 'Ey')
end

#generate_input_fileObject

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



72
73
74
75
76
77
78
79
80
81
82
83
84
85
# 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_statusObject



124
125
126
127
128
129
130
# File 'lib/veritascrmod/veritas.rb', line 124

def get_status
  if @running
    @status = :Running
  else
    @status = :Complete
  end
end

#graphkit(name, options) ⇒ Object

class ListSubmitter



240
241
242
243
244
245
246
# 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_extensionObject



174
175
176
# File 'lib/veritascrmod/veritas.rb', line 174

def input_file_extension
  '.in'
end

#input_file_headerObject



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# 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_textObject

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



393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
# 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) ⇒ Object



412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
# 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_readerObject



118
119
# File 'lib/veritascrmod/read_netcdf.rb', line 118

def netcdf_smart_reader
end

#openncfileObject



265
266
267
268
269
270
271
272
# 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_stringObject

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



103
104
105
# File 'lib/veritascrmod/veritas.rb', line 103

def parameter_string
  @run_name + ".in"
end

#parameter_transitionObject



107
108
# File 'lib/veritascrmod/veritas.rb', line 107

def parameter_transition
end

#potential_graphkit(options) ⇒ Object



247
248
249
# File 'lib/veritascrmod/veritas.rb', line 247

def potential_graphkit(options)
  real_space_graphkit(signal: 'phi')
end

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



40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/veritascrmod/veritas.rb', line 40

def print_out_line
  #p ['id', id, 'ctd', ctd]
  #p rcp.results.zip(rcp.results.map{|r| send(r)})
  name = @run_name
  name += " (res: #@restart_id)" if @restart_id
  name += " real_id: #@real_id" if @real_id
  beginning = sprintf("%2d:%d %-60s %1s:%2.1f(%s) %3s%1s",  @id, @job_no, name, @status.to_s[0,1],  @run_time.to_f / 60.0, @nprocs.to_s, percent_complete.to_f, "%")
  beginning += " n:#@nlines " if @nlines
  #if ctd and fusionQ
    #beginning += sprintf("Q:%f, Pfusion:%f MW, Ti0:%f keV, Te0:%f keV, n0:%f x10^20", fusionQ, pfus, ti0, te0, ne0)
  #end
  #beginning += "  ---#{@comment}" if @comment
  beginning
end

#process_directory_code_specificObject

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).



116
117
118
119
120
121
122
# 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) ⇒ Object



292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# 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) ⇒ Object



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# 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) ⇒ Object

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



67
68
69
70
# 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) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# 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_outputObject Also known as: vo



92
93
94
# File 'lib/veritascrmod/veritas.rb', line 92

def vim_output
  system "vim -Ro #{output_file} #{error_file}"
end

#vspace_dist_fn_graphkit(options) ⇒ Object



332
333
334
335
336
337
338
339
340
341
342
343
344
# 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) ⇒ Object



312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# 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_fileObject

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



98
99
100
# File 'lib/veritascrmod/veritas.rb', line 98

def write_input_file
  File.open(@run_name + ".in", 'w'){|file| file.puts input_file_text}
end