Class: CodeRunner::Trinity
- Inherits:
-
Run::FortranNamelist
- Object
- Run::FortranNamelist
- CodeRunner::Trinity
- Includes:
- ActualParameterValues, OutputFiles, TrinityGraphKits
- Defined in:
- lib/trinitycrmod/trinity.rb,
lib/trinitycrmod/trinity_gs2.rb,
lib/trinitycrmod/output_files.rb,
lib/trinitycrmod/check_parameters.rb,
lib/trinitycrmod/actual_parameter_values.rb,
lib/trinitycrmod/graphs.rb
Overview
This is a customised subclass of the CodeRunner::Run class which allows CodeRunner to run and analyse the multiscale gyrokinetic turbulent transport solver Trinity.
It generates the Trinity input file, and both analyses the results and allows easy plotting of them. It also interfaces with the GS2 CodeRunner module to allow analysis of the individual GS2 results if GS2 is being used as the flux code.
Defined Under Namespace
Modules: ActualParameterValues, OutputFiles, TrinityGraphKits
Class Method Summary collapse
- .defaults_file_header ⇒ Object
- .get_input_help_from_source_code(source_folder) ⇒ Object
-
.use_new_defaults_file_with_gs2(name = ARGV[-3], trinity_input_file = ARGV[-2], gs2_input_file = ARGV[-1]) ⇒ Object
This function creates a new Trinity defaults file, with Trinity parameters taken from trinity_input_file, and GS2 parameters taken from gs2_input_file.
Instance Method Summary collapse
- #check_flux_option ⇒ Object
- #check_geometery ⇒ Object
- #check_parallelisation ⇒ Object
- #check_parameters ⇒ Object
-
#evaluate_defaults_file(filename) ⇒ Object
Override standard CodeRunner method to allow for Gs2 variables.
- #generate_component_runs ⇒ Object
-
#generate_gs2_input_files ⇒ Object
Writes the gs2 input files, creating separate subfolders for them if @subfolders is .true.
-
#generate_input_file ⇒ Object
This is a hook which gets called just before submitting a simulation.
-
#get_2d_array_float(outfile, column_header, index_header) ⇒ Object
Return a two-dimensional array of floatingpoint numbers from the file ending in outfile, from the column whose header matches column_header, indexed by index_header.
- #get_completed_timesteps ⇒ Object
- #get_global_results ⇒ Object
- #get_status ⇒ Object
- #graphkit(name, options) ⇒ Object
- #gs2_runs ⇒ Object
- #input_file_header ⇒ Object
-
#list(var) ⇒ Object
Returns a hash of the specified dimension in the form value where index is 1-based Dimension can be: :t :rho :rho_cc.
-
#n_flux_tubes ⇒ Object
The number of separate flux tube results needed for the jacobian.
-
#parameter_string ⇒ Object
Parameters which follow the Trinity executable, in this case just the input file.
- #parameter_transition ⇒ Object
-
#print_out_line ⇒ Object
A hook which gets called when printing the standard run information to the screen using the status command.
-
#process_directory_code_specific ⇒ Object
This method, as its name suggests, is called whenever CodeRunner is asked to analyse a run directory.
- #save ⇒ Object
- #vim_output ⇒ Object (also: #vo)
-
#write_input_file ⇒ Object
This command uses the infrastructure provided by Run::FortranNamelist, provided by CodeRunner itself.
Methods included from TrinityGraphKits
#ang_mom_prof_graphkit, #eln_hflux_gb_prof_graphkit, #eln_hflux_prof_graphkit, #eln_pwr_prof_graphkit, #eln_temp_prof_graphkit, #fluxes_prof_graphkit, #ion_hflux_gb_prof_graphkit, #ion_hflux_prof_graphkit, #ion_pwr_prof_graphkit, #ion_temp_prof_graphkit, #lflux_gb_prof_graphkit, #nt_prof_graphkit, #pbalance_prof_graphkit, #prof_graphkit, #torque_prof_graphkit
Methods included from ActualParameterValues
#dflx_stencil_actual, #evolve_grads_only_actual, #fork_flag_actual
Methods included from OutputFiles
#fluxes_outfile, #info_outfile, #nt_outfile, #pbalance_outfile, #time_outfile, #view_outfiles
Class Method Details
.defaults_file_header ⇒ Object
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 |
# File 'lib/trinitycrmod/trinity.rb', line 339 def self.defaults_file_header <<EOF1 ############################################################################ # # # Automatically generated defaults file for the Trinity CodeRunner module # # # # This defaults file specifies a set of defaults for Trinity which are # # used by CodeRunner to set up and run Trinity simulations. # # # ############################################################################ # Created: #{Time.now.to_s} @defaults_file_description = "" EOF1 end |
.get_input_help_from_source_code(source_folder) ⇒ Object
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/trinitycrmod/trinity.rb', line 287 def self.get_input_help_from_source_code(source_folder) source = get_aggregated_source_code_text(source_folder) rcp.namelists.each do |nmlst, hash| hash[:variables].each do |var, var_hash| # next unless var == :w_antenna var = var_hash[:code_name] || var values_text = source.scan(Regexp.new("\\W#{var}\\s*=\\s*.+")).join("\n") ep values_text values = scan_text_for_variables(values_text).map{|(v,val)| val} values.uniq! # ep values if var == :nbeta values.delete_if{|val| val.kind_of? String} if values.find{|val| val.kind_of? Numeric} values.delete_if{|val| val.kind_of? String and not String::FORTRAN_BOOLS.include? val} if values.find{|val| val.kind_of? String and String::FORTRAN_BOOLS.include? val} # values.sort! # ep var # ep values sample_val = values[0] p sample_val help = values_text.scan(/ !(.*)/).flatten[0] p help #gets var_hash[:help] = help var_hash[:description] = help save_namelists end end end |
.use_new_defaults_file_with_gs2(name = ARGV[-3], trinity_input_file = ARGV[-2], gs2_input_file = ARGV[-1]) ⇒ Object
This function creates a new Trinity defaults file, with Trinity parameters taken from trinity_input_file, and GS2 parameters taken from gs2_input_file. The file is then moved to the CodeRunner central defaults location, the current folder is configured to use the defaults file.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/trinitycrmod/trinity_gs2.rb', line 16 def self.use_new_defaults_file_with_gs2(name = ARGV[-3], trinity_input_file = ARGV[-2], gs2_input_file = ARGV[-1]) raise "Please specify a name, a trinity input file and a gs2 input file" if name == "use_new_gs2_defaults_file" defaults_filename = "#{name}_defaults.rb" tmp_filename = "#{name}_gs2tmp_defaults.rb" central_defaults_filename = rcp.user_defaults_location + "/" + defaults_filename FileUtils.rm(name + '_defaults.rb') if FileTest.exist?(name + '_defaults.rb') FileUtils.rm(central_defaults_filename) if FileTest.exist?(central_defaults_filename) FileUtils.rm(tmp_filename) if FileTest.exist?(tmp_filename) raise "Defaults file: #{central_defaults_filename} already exists" if FileTest.exist? central_defaults_filename make_new_defaults_file(name, trinity_input_file) CodeRunner::Gs2.make_new_defaults_file(name + '_gs2tmp', gs2_input_file) File.open(defaults_filename, 'a'){|file| file.puts <<EOF2 gs2_runs.each do |run| run.instance_eval do #{File.read(tmp_filename).gsub(/\A|\n/, "\n ")} end end EOF2 } FileUtils.mv(defaults_filename, central_defaults_filename) FileUtils.rm(tmp_filename) CodeRunner.fetch_runner(C: rcp.code, m: (rcp.modlet? ? rcp.modlet : nil), D: name) end |
Instance Method Details
#check_flux_option ⇒ Object
21 22 23 24 25 |
# File 'lib/trinitycrmod/check_parameters.rb', line 21 def check_flux_option if @flux_option == "gs2" error("subfolders must be .true. ") unless @subfolders and @subfolders.fortran_true? end end |
#check_geometery ⇒ Object
11 12 13 |
# File 'lib/trinitycrmod/check_parameters.rb', line 11 def check_geometery error( "Can't find geo_file #@geo_file (the path of geo file should be either absolute or set relative to the run folder #@directory). If you are not using a geometry file for this run please unset the parameter geo_file.") if @geo_file and not FileTest.exist? @geo_file end |
#check_parallelisation ⇒ Object
15 16 17 18 19 |
# File 'lib/trinitycrmod/check_parameters.rb', line 15 def check_parallelisation error("nrad must be explicitly specified") unless @nrad error("Number of jobs: #{n_flux_tubes} must evenly divide the number of processors: #{actual_number_of_processors} when fork_flag is .true.") if fork_flag_actual.fortran_true? and not actual_number_of_processors%n_flux_tubes == 0 end |
#check_parameters ⇒ Object
3 4 5 6 7 8 9 |
# File 'lib/trinitycrmod/check_parameters.rb', line 3 def check_parameters check_geometery check_parallelisation check_flux_option end |
#evaluate_defaults_file(filename) ⇒ Object
Override standard CodeRunner method to allow for Gs2 variables
63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/trinitycrmod/trinity_gs2.rb', line 63 def evaluate_defaults_file(filename) text = File.read(filename) text.scan(/^\s*@(\w+)/) do var_name = $~[1].to_sym next if var_name == :defaults_file_description unless rcp.variables.include? var_name or Gs2.rcp.variables.include? var_name warning("---#{var_name}---, specified in #{File.(filename)}, is not a variable. This could be an error") end end instance_eval(text) end |
#generate_component_runs ⇒ Object
175 176 177 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 |
# File 'lib/trinitycrmod/trinity.rb', line 175 def generate_component_runs #puts "HERE" @component_runs ||= [] if @flux_option == "gs2" #puts "HERE" for i in 0...n_flux_tubes component = (@component_runs[i] ||= Gs2.new(@runner).create_component) component.component_runs = [] #component.runner = nil #pp component; STDIN.gets #component.instance_variables.each{|var| puts var; pp var; puts Marshal.dump(component.instance_variable_get(var)); STDIN.gets} #puts Marshal.dump(component); STDIN.gets #pp component; STDIN.gets #p component.class component.job_no = @job_no component.status = @status #p ["HERE2", @component_runs.size, @component_runs[i]] #Dir.chdir(@directory) { compdir = "flux_tube_#{i+1}" Dir.chdir(compdir){component.process_directory} if FileTest.exist? compdir #} component.component_runs = [] #@component_runs.push component component.real_id = @id #@gs2_run_list[i] = component #pp component; STDIN.gets #component.runner = nil #puts Marshal.dump(component); STDIN.gets #pp component; STDIN.gets #component.component_runs = [] end end end |
#generate_gs2_input_files ⇒ Object
Writes the gs2 input files, creating separate subfolders for them if @subfolders is .true.
120 121 122 123 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 152 153 154 155 |
# File 'lib/trinitycrmod/trinity.rb', line 120 def generate_gs2_input_files # At the moment we must use subfolders for i in 0...n_flux_tubes #gs2run = gs2_run(:base).dup #gs2_run(i).instance_variables.each do |var| #gs2run.instance_variable_set(var, gs2_run(i).instance_variable_get(var)) #end gs2run = gs2_runs[i] #p ['i',i] if @subfolders and @subfolders.fortran_true? gs2run.directory = @directory + "/flux_tube_#{i+1}" FileUtils.makedirs(gs2run.directory) gs2run.relative_directory = @relative_directory + "/flux_tube_#{i+1}" gs2run.restart_dir = gs2run.directory + "/nc" else gs2run.directory = @directory gs2run.relative_directory = @relative_directory end gs2run.run_name = @run_name + (i+1).to_s gs2run.nprocs = @nprocs if i==0 block = Proc.new{ingen} else block = Proc.new{} end Dir.chdir(gs2run.directory){gs2run.generate_input_file(&block); gs2run.write_info} ### Hack the input file so that gs2 gets the location of # the restart dir correctly within trinity if @subfolders and @subfolders.fortran_true? infile = gs2run.directory + "/" + gs2run.run_name + ".in" text = File.read(infile) File.open(infile, 'w'){|f| f.puts text.sub(/restart_dir\s*=\s*"nc"/, "restart_dir = \"flux_tube_#{i+1}/nc\"")} end end end |
#generate_input_file ⇒ Object
This is a hook which gets called just before submitting a simulation. It sets up the folder and generates any necessary input files.
87 88 89 90 91 92 |
# File 'lib/trinitycrmod/trinity.rb', line 87 def generate_input_file @run_name += "_t" check_parameters write_input_file generate_gs2_input_files if @flux_option == "gs2" end |
#get_2d_array_float(outfile, column_header, index_header) ⇒ Object
Return a two-dimensional array of floatingpoint numbers from the file ending in outfile,
from the column whose header matches column_header, indexed by index_header. See
TextDataTools::Column::DataFile for more information. Outfile is a symbol, use e.g. :nt
for data from 'run_name.nt'.
44 45 46 47 48 |
# File 'lib/trinitycrmod/output_files.rb', line 44 def get_2d_array_float(outfile, column_header, index_header) cache[:array_2d] = {} unless [:Complete, :Failed].include? @status cache[:array_2d] ||= {} cache[:array_2d][[outfile, column_header, index_header]] ||= send(outfile + :_outfile).get_2d_array_float(column_header, index_header) end |
#get_completed_timesteps ⇒ Object
264 265 266 267 268 269 270 |
# File 'lib/trinitycrmod/trinity.rb', line 264 def get_completed_timesteps Dir.chdir(@directory) do @completed_timesteps = time_outfile.exists? ? time_outfile.get_1d_array_integer(/itstep/).max : 0 end end |
#get_global_results ⇒ Object
273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/trinitycrmod/trinity.rb', line 273 def get_global_results @fusionQ = info_outfile.get_variable_value('Q').to_f @pfus = info_outfile.get_variable_value(/fusion\s+power/i).to_f @pnet = info_outfile.get_variable_value(/net\s+power/i).to_f @aux_power = info_outfile.get_variable_value(/aux.*\s+power/i).to_f @alpha_power = info_outfile.get_variable_value(/alpha\s+power/i).to_f @rad_power = info_outfile.get_variable_value(/radiated\s+power/i).to_f @ne0 = info_outfile.get_variable_value(/core\s+density/i).to_f @ti0 = info_outfile.get_variable_value(/core\s+T_i/i).to_f @te0 = info_outfile.get_variable_value(/core\s+T_e/i).to_f @omega0 = info_outfile.get_variable_value(/core\s+omega/i).to_f #p 'send(fusionQ)', send(:fusionQ) end |
#get_status ⇒ Object
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/trinitycrmod/trinity.rb', line 246 def get_status if @running get_completed_timesteps if completed_timesteps == 0 @status = :NotStarted else @status = :Incomplete end else get_completed_timesteps if File.read(output_file) =~/trinity\s+finished/i @status = :Complete else @status = :Failed end end end |
#graphkit(name, options) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/trinitycrmod/graphs.rb', line 91 def graphkit(name, ) [:t].each do |var| #ep 'index', var if [var].class == Symbol and [var] == :all [var] = list(var).values elsif [var+:_index].class == Symbol and [var+:_index] == :all #ep 'Symbol' [var+:_index] = list(var).keys end if [var].class == Array return [var].map{|value| graphkit(name, .dup.absorb({var => value}))}.sum elsif [var+:_index].class == Array #ep 'Array' return [var+:_index].map{|value| graphkit(name, .dup.absorb({var+:_index => value}))}.sum end if [var].class == Symbol and [var] == :max [var] = list(var).values.max elsif [var+:_index].class == Symbol and [var+:_index] == :max ep 'Symbol' [var+:_index] = list(var).keys.max end end if meth = TrinityGraphKits.instance_methods.find{|m| m.to_s == name + '_graphkit'} return send(meth, ) else raise "GraphKit not found: #{name}" end end |
#gs2_runs ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/trinitycrmod/trinity_gs2.rb', line 47 def gs2_runs #puts "2@COMMMMMMMMMMMMMPOOOOOOOOOOOOOONNNETN", @component_runs generate_component_runs if not (@component_runs and @component_runs.size > 0) #p ["@COMMMMMMMMMMMMMPOOOOOOOOOOOOOONNNETN", @component_runs] @component_runs #@gs2_run_list ||= {} #raise TypeError.new("@runner is nil") if @runner.nil? #@gs2_run_list[key] ||= Gs2.new(@runner) ##if key != :base ##raise "key in gs2_run must be either :base or an integer" unless key.kind_of? Integer ##@gs2_run_list[key] ||= @gs2_run_list[:base].dup ##end #@gs2_run_list[key] end |
#input_file_header ⇒ Object
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
# File 'lib/trinitycrmod/trinity.rb', line 317 def input_file_header <<EOF !============================================================================== ! Trinity INPUT FILE automatically generated by CodeRunner !============================================================================== ! ! Trinity is a multiscale turbulent transport code for fusion plasmas. ! ! See http://gyrokinetics.sourceforge.net ! ! 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 |
#list(var) ⇒ Object
Returns a hash of the specified dimension in the form value where index is 1-based Dimension can be: :t :rho :rho_cc
55 56 57 58 59 60 61 62 |
# File 'lib/trinitycrmod/output_files.rb', line 55 def list(var) case var when :t hash = {} get_2d_array_float(:nt, /1:\s+time/, /1:\s+time/).map{|arr| arr[0]}.each_with_index{|t,i| hash[i+1] = t} hash end end |
#n_flux_tubes ⇒ Object
The number of separate flux tube results needed for the jacobian
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/trinitycrmod/trinity.rb', line 96 def n_flux_tubes d1 = dflx_stencil_actual - 1 ngrads =d1 * case @grad_option when "tigrad", "ngrad", "lgrad" 1 when "tgrads" 2 when "ltgrads", "ntgrads" 3 when "all" 4 else raise "unknown grad_option: #@grad_option" end if evolve_grads_only_actual.fortran_true? njac = ngrads + 1 else njac = 2*ngrads+1 end #p 'nraaad', @nrad (@nrad-1) * njac end |
#parameter_string ⇒ Object
Parameters which follow the Trinity executable, in this case just the input file.
168 169 170 |
# File 'lib/trinitycrmod/trinity.rb', line 168 def parameter_string @run_name + ".trin" end |
#parameter_transition ⇒ Object
172 173 |
# File 'lib/trinitycrmod/trinity.rb', line 172 def parameter_transition end |
#print_out_line ⇒ Object
A hook which gets called when printing the standard run information to the screen using the status command.
64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/trinitycrmod/trinity.rb', line 64 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, "%") if ctd 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_specific ⇒ Object
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).
236 237 238 239 240 241 242 243 244 |
# File 'lib/trinitycrmod/trinity.rb', line 236 def process_directory_code_specific get_status #p ['id is', id, 'ctd is ', ctd] if ctd get_global_results end #p ['fusionQ is ', fusionQ] @percent_complete = completed_timesteps.to_f / ntstep.to_f * 100.0 end |
#save ⇒ Object
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/trinitycrmod/trinity.rb', line 211 def save #@gs2_run_list.values.each{|r| r.runner = nil; r.component_runs = []} if @gs2_run_list.kind_of? Hash super #@gs2_run_list.values.each{|r| r.runner = @runner} if @gs2_run_list.kind_of? Hash #logf(:save) #raise CRFatal.new("Something has gone horribly wrong: runner.class is #{@runner.class} instead of CodeRunner") unless @runner.class.to_s == "CodeRunner" #runner, @runner = @runner, nil #@system_triers, old_triers = nil, @system_triers #@component_runs.each{|run| run.runner = nil; run.component_runs = []} if @component_runs ##@component_runs.each{|run| run.runner = nil} if @component_runs ## logi(self) ##pp self ##@component_runs.each{|ph| ph.instance_variables.each{|var| puts var; pp ph.instance_variable_get(var); STDIN.gets; puts ph.Marshal.dump(instance_variable_get(var))}} if @component_runs ##instance_variables.each{|var| puts var; instance_variable_get(var); puts Marshal.dump(instance_variable_get(var)); STDIN.gets} #Dir.chdir(@directory){File.open(".code_runner_run_data", 'w'){|file| file.puts Marshal.dump(self)}} #@runner = runner #@component_runs.each{|run| run.runner = runner} if @component_runs #@system_triers = old_triers end |
#vim_output ⇒ Object Also known as: vo
157 158 159 |
# File 'lib/trinitycrmod/trinity.rb', line 157 def vim_output system "vim -Ro #{output_file} #{error_file} #@directory/#@run_name.error #@directory/#@run_name.out " end |
#write_input_file ⇒ Object
This command uses the infrastructure provided by Run::FortranNamelist, provided by CodeRunner itself.
163 164 165 |
# File 'lib/trinitycrmod/trinity.rb', line 163 def write_input_file File.open(@run_name + ".trin", 'w'){|file| file.puts input_file_text} end |