class CodeRunner class Gs2 MAX_NAME_SIZE = 310 def warning(message) eputs "Warning: " + message; sleep 0.3 end class InputFileError < StandardError end def error(message) raise InputFileError.new("Error: " + message) end def test_failed(namelist, var, gs2_var, tst) return < 1 for linear runs.") if @nonlinear_mode == "off" and (!@nperiod or @nperiod == 1) warning("Recommend nperiod = 1 for nonlinear runs.") if @nonlinear_mode == "on" and (@nperiod > 1) warning("Consider using field_option = local and associated optimizations.") if @field_option and @field_option == "implicit" ################################# # Parallelisation/Layout Errors # ################################# # Best linear run layout is lexys warning("The best layout for linear runs is usually lexys.") if @nonlinear_mode=="off" and not @layout=="lexys" # Best nonlinear run layout is xyles warning("The best layout for nonlinear runs is usually xyles.") if @nonlinear_mode=="on" and not @layout=="xyles" # Check whether we are parallelising over x warning("Parallelising over x: suggest total number of processors should be: #{max_nprocs_no_x}") if actual_number_of_processors > max_nprocs_no_x and not @grid_option == "single" ######################### # Initialisation Errors # ######################### # Check if restart folder exists if @restart_file and @restart_file =~ /^(?[^\/]+)\// folder = $~[:folder] warning("Folder #{folder}, specified in restart_file, not present. NetCDF save may fail") unless FileTest.exist?(folder) end error("Setting @restart_file as an empty string will result in hidden restart files.") if @restart_file == "" error("ginit_option is 'many' but is_a_restart is false") if @ginit_option == "many" and not @is_a_restart error("chop_side should not be used (remove test if default changes from T to F)") if !@chop_side or @chop_side.fortran_true? ##################### # Diagnostic errors # ##################### #Check whether useful diagnostics have been omitted. not_set = [:write_verr, :save_for_restart, :write_nl_flux, :write_final_fields, :write_final_moments].find_all do |diagnostic| not (send(diagnostic) and send(diagnostic).fortran_true?) end if not_set.size > 0 str = not_set.inject("") do |s, diagnostic| s + "\n\t#{diagnostic} --- " + rcp.namelists[diagnostics_namelist][:variables][diagnostic][:description] rescue s end warning("The following useful diagnostics were not set:" + str) if str.length > 0 end warning("You are running in nonlinear mode but have not switched the nonlinear flux diagnostic.") if not (@write_nl_flux and @write_nl_flux.fortran_true?) and @nonlinear_mode == "on" #{ #write_verr: "Velocity space diagnostics will not be output for this run" #}.each do |var, warn| #warning(v"#{var} not set or .false. --- " + warn) unless send(var) and send(var).fortran_true? #end error("Please specify nwrite") unless @nwrite error("Please specify nstep") unless @nstep warning("You will write out diagnostics less than 50 times") if @nstep/@nwrite < 50 ######################## # Miscellaneous errors # ######################## error("The run name for this run is too long. Please move some of the variable settings to the local defaults file.") if @relative_directory.size + @run_name.size > MAX_NAME_SIZE warning("You are submitting a nonlinear run with no dissipation.") if @nonlinear_mode == "on" and @hyper_option=="none" and @collision_model=="none" warning("You have no spacial implicitness: (bakdif) for one of your species. Be prepared for numerical instabilities!") if (1..@nspec).to_a.find{|i| bd = send("bakdif_#{i}") and bd == 0} warning("The system will abort with rapid timestep changes...") if !@abort_rapid_time_step_change or @abort_rapid_time_step_change.fortran_true? warning("local_field_solve is an old variable that should not really be used.") if @local_field_solve and @local_field_solve.fortran_true? ############################# # Boundary Condition Errors # ############################# warning("Boundary option should be periodic for shat = 1e-6.") if (!@boundary_option or @boundary_option != "periodic") and ((@s_hat_input and @s_hat_input.abs == 1.0e-6) or (@shat and @shat.abs == 1.0e-6)) warning("Boundary option should be default (unconnected) for single and range mode with shat > 0.") if (@boundary_option != "default") and ((@s_hat_input and @s_hat_input.abs > 1.0e-6) or (@shat and @shat.abs > 1.0e-6)) and (@grid_option == "single" or @grid_option == "range") warning("Boundary option should be linked for box mode with shat > 0.") if (!@boundary_option or @boundary_option != "linked") and ((@s_hat_input and @s_hat_input.abs > 1.0e-6) or (@shat and @shat.abs > 1.0e-6)) and @grid_option == "box" error("Set nonad_zero = true.") if @nonad_zero and not @nonad_zero.fortran_true? ################### # Spectrogk tests # ################### # if spectrogk? if @force_5d and @force_5d.fortran_true? warning("Must specify interpolation method with phi_method.") if not (@phi_method) end end ################ # Damping Rate # ################ error("Linear runs with hyperviscosity are NOT recommended!") if @nonlinear_mode=="off" and (@hyper_option and @hyper_option=="visc_only") and (@d_hypervisc and @d_hypervisc!=0) warning("Amplitude dependent part of hyperviscosity being ignored since const_amp = true") if (@hyper_option and @hyper_option=="visc_only") and (@const_amp and @const_amp.fortran_true?) ################### # Geometry Errors # ################### error("You must set bishop = 4 for Miller(local) geometry. Remember also that s_hat_input will override shat") if (@bishop!=4 and (@local_eq and @local_eq.fortran_true?)) error("Shift should be > 0 for s-alpha equilibrium.") if @equilibrium_option=="s-alpha" and (@shift and @shift < 0) error("Shift should be < 0 for Miller equilibrium.") if @equilibrium_option=="eik" and @local_eq.fortran_true? and (@shift and @shift > 0) error("irho must be 2 for Miller equilibrium.") if @equilibrium_option=="eik" and @local_eq.fortran_true? and (@irho and @irho!=2) warning("Note that shat != s_hat_input") if @shat and @s_hat_input and @shat!=@s_hat_input ################## # Species Errors # ################## error("Must set z = -1 for electron species.") if (@type_2 and @z_2 and @type_2=='electron' and @z_2 != -1) ################# # Optimisations # ################# if CODE_OPTIONS[:gs2] and CODE_OPTIONS[:gs2][:show_opt] eputs("Optimisation Summary:") optimisation_flags.each do |flag| eputs("------------------------- #{flag}: #{send(flag)}\n* #{rcp.variables_with_help[flag].gsub(/\n/, "\n\t").sub(/\A([^.]*.).*\Z/m, '\1')}") end #not_set = [:operator, :save_for_restart, :write_nl_flux, :write_final_fields, :write_final_moments].find_all do |diagnostic| #not (send(diagnostic) and send(diagnostic).fortran_true?) #end #if not_set.size > 0 #str = not_set.inject("") do |s, diagnostic| #s + "\n\t#{diagnostic} --- " + rcp.namelists[diagnostics_namelist][:variables][diagnostic][:description] rescue s #end #warning("The following useful diagnostics were not set:" + str) if str.length > 0 #end end end def optimisation_flags [ :opt_redist_persist, :opt_redist_persist_overlap, :opt_redist_nbk, :opt_redist_init, :intmom_sub, :intspec_sub, #:local_field_solve, :do_smart_update, :field_subgath, :field_option, :field_local_allreduce, :field_local_allreduce_sub, :minnrow, :opt_init_bc, :opt_source ] end # A hash which gives the actual numbers of gridpoints indexed by their corresponding letters in the layout string. def gridpoints gridpoints = {'l' => @ngauss, 'e' => @negrid, 's' => @nspec} if @grid_option == "single" gridpoints.absorb({'x'=>1, 'y'=>1}) else gridpoints.absorb({'x' => (@ntheta0 or (2.0 * (@nx - 1.0) / 3.0 + 1.0).floor), 'y' => (@naky or ((@ny - 1.0) / 3.0 + 1.0).floor)}) end return gridpoints end def cumulative_gridpoints c = 1 error("Please specify layout") unless @layout @layout.split(//).reverse.inject({}){|hash, let| c*=gridpoints[let]; hash[let] = c; hash} end # ep parallelisation def max_nprocs_no_x parallelisation = cumulative_gridpoints parallelisation[parallelisation.keys[parallelisation.keys.index('x') - 1]] end def diagnostics_namelist :gs2_diagnostics_knobs end # Run the ingen tool on the input file def ingen Dir.chdir(@directory) do ing = File.dirname(File.expand_path(@executable)) + '/ingen' success = system "#{ing} #@run_name.in" warning("Could not run ingen... make sure that ingen is in the same folder as @executable and can be run on the login nodes if you want this to work") unless success end end end end