gs2crmod 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.document +5 -0
  2. data/Gemfile +13 -0
  3. data/LICENSE.txt +20 -0
  4. data/README.md +4 -0
  5. data/README.rdoc +19 -0
  6. data/Rakefile +56 -0
  7. data/VERSION +1 -0
  8. data/ext/extconf.rb +9 -0
  9. data/ext/gs2crmod_ext.c +366 -0
  10. data/gs2crmod.gemspec +98 -0
  11. data/include/gs2crmod_ext.h +58 -0
  12. data/lib/gs2crmod/astrogk/astrogk.rb +201 -0
  13. data/lib/gs2crmod/astrogk/calculations.rb +57 -0
  14. data/lib/gs2crmod/astrogk/check_convergence.rb +7 -0
  15. data/lib/gs2crmod/astrogk/deleted_variables.rb +76 -0
  16. data/lib/gs2crmod/astrogk/graphs.rb +13 -0
  17. data/lib/gs2crmod/astrogk/gsl_data.rb +13 -0
  18. data/lib/gs2crmod/astrogk/gsl_tools.rb +182 -0
  19. data/lib/gs2crmod/astrogk/ingen.rb +18 -0
  20. data/lib/gs2crmod/astrogk/input_file_tools.rb +7 -0
  21. data/lib/gs2crmod/astrogk/namelist_tools.rb +14 -0
  22. data/lib/gs2crmod/astrogk/namelists.rb +2800 -0
  23. data/lib/gs2crmod/astrogk/properties.rb +17 -0
  24. data/lib/gs2crmod/astrogk/species_dependent_namelists.rb +228 -0
  25. data/lib/gs2crmod/astrogk/test_gs2.rb +231 -0
  26. data/lib/gs2crmod/astrogk.rb +200 -0
  27. data/lib/gs2crmod/calculations.rb +780 -0
  28. data/lib/gs2crmod/check_convergence.rb +179 -0
  29. data/lib/gs2crmod/deleted_variables.rb +916 -0
  30. data/lib/gs2crmod/graphs.rb +1899 -0
  31. data/lib/gs2crmod/graphs_rdoc.rb +556 -0
  32. data/lib/gs2crmod/gs2.rb +1143 -0
  33. data/lib/gs2crmod/gsl_data.rb +1181 -0
  34. data/lib/gs2crmod/gsl_data_3d.rb +705 -0
  35. data/lib/gs2crmod/gsl_tools.rb +187 -0
  36. data/lib/gs2crmod/ingen.rb +218 -0
  37. data/lib/gs2crmod/namelists.rb +5142 -0
  38. data/lib/gs2crmod/properties.rb +22 -0
  39. data/lib/gs2crmod/species_dependent_namelists.rb +228 -0
  40. data/lib/gs2crmod/test_gs2.rb +231 -0
  41. data/lib/gs2crmod.rb +2 -0
  42. data/lib/gs2crmod_extension.rb +1 -0
  43. data/test/helper.rb +18 -0
  44. data/test/test_gs2crmod.rb +7 -0
  45. metadata +176 -0
@@ -0,0 +1,17 @@
1
+ class CodeRunner
2
+ class Gs2::Astrogk
3
+
4
+
5
+ ######################################
6
+ # GS2 CodeRunner Module
7
+ #
8
+ # Calculated Properties
9
+ #
10
+ # These are methods which calculate
11
+ # miscellaneous properties of the run.
12
+ #
13
+ #####################################
14
+
15
+
16
+ end
17
+ end
@@ -0,0 +1,228 @@
1
+ {:species_parameters=>
2
+ {:description=>"SPECIES ",
3
+ :include_conditions=>"true",
4
+ :variables=>
5
+ {:z=>
6
+ {:help=>"Charge",
7
+ :include_conditions=>"true",
8
+ :description=>"Charge",
9
+ :tests=>["Tst::FLOAT"],
10
+ :autoscanned_defaults=>[],
11
+ :must_pass=>
12
+ [{:test=>"kind_of? Numeric",
13
+ :explanation=>
14
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."}]},
15
+ :mass=>
16
+ {:help=>"Mass",
17
+ :include_conditions=>"true",
18
+ :description=>"Mass",
19
+ :tests=>["Tst::FLOAT"],
20
+ :autoscanned_defaults=>[],
21
+ :must_pass=>
22
+ [{:test=>"kind_of? Numeric",
23
+ :explanation=>
24
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."}]},
25
+ :dens=>
26
+ {:help=>"Density\t",
27
+ :include_conditions=>"true",
28
+ :description=>"Density\t",
29
+ :tests=>["Tst::FLOAT"],
30
+ :autoscanned_defaults=>[],
31
+ :must_pass=>
32
+ [{:test=>"kind_of? Numeric",
33
+ :explanation=>
34
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."}]},
35
+ :temp=>
36
+ {:help=>"Temperature",
37
+ :include_conditions=>"true",
38
+ :description=>"Temperature",
39
+ :tests=>["Tst::FLOAT"],
40
+ :autoscanned_defaults=>[],
41
+ :must_pass=>
42
+ [{:test=>"kind_of? Numeric",
43
+ :explanation=>
44
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."}]},
45
+ :tprim=>
46
+ {:help=>"6.0 !-1/T (dT/drho)",
47
+ :include_conditions=>"true",
48
+ :description=>"6.0 !-1/T (dT/drho)",
49
+ :tests=>["Tst::FLOAT"],
50
+ :autoscanned_defaults=>[],
51
+ :must_pass=>
52
+ [{:test=>"kind_of? Numeric",
53
+ :explanation=>
54
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."}]},
55
+ :fprim=>
56
+ {:help=>"2.22 !-1/n (dn/drho)",
57
+ :include_conditions=>"true",
58
+ :description=>"2.22 !-1/n (dn/drho)",
59
+ :tests=>["Tst::FLOAT"],
60
+ :autoscanned_defaults=>[],
61
+ :must_pass=>
62
+ [{:test=>"kind_of? Numeric",
63
+ :explanation=>
64
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."}]},
65
+ :uprim=>
66
+ {:help=>"?",
67
+ :include_conditions=>"true",
68
+ :description=>"?",
69
+ :tests=>["Tst::FLOAT"],
70
+ :autoscanned_defaults=>[],
71
+ :must_pass=>
72
+ [{:test=>"kind_of? Numeric",
73
+ :explanation=>
74
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."}]},
75
+ :vnewk=>
76
+ {:help=>"1.e-2 !collisionality parameter",
77
+ :include_conditions=>"true",
78
+ :description=>"1.e-2 !collisionality parameter",
79
+ :tests=>["Tst::FLOAT"],
80
+ :autoscanned_defaults=>[],
81
+ :must_pass=>
82
+ [{:test=>"kind_of? Numeric",
83
+ :explanation=>
84
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."}]},
85
+ :type=>
86
+ {:help=>"'ion' Thermal ion species ",
87
+ :include_conditions=>"true",
88
+ :description=>"'ion' Thermal ion species ",
89
+ :tests=>["Tst::STRING"],
90
+ :autoscanned_defaults=>[],
91
+ :must_pass=>
92
+ [{:test=>"kind_of? String",
93
+ :explanation=>"This variable must be a string."}]},
94
+ :dens0=>
95
+ {:should_include=>"true",
96
+ :description=>nil,
97
+ :help=>nil,
98
+ :tests=>["Tst::FLOAT"],
99
+ :gs2_name=>:dens0,
100
+ :must_pass=>
101
+ {:test=>"kind_of? Numeric",
102
+ :explanation=>
103
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."},
104
+ :autoscanned_defaults=>[1.0]},
105
+ :u0=>
106
+ {:should_include=>"true",
107
+ :description=>nil,
108
+ :help=>nil,
109
+ :tests=>["Tst::FLOAT"],
110
+ :gs2_name=>:u0,
111
+ :must_pass=>
112
+ {:test=>"kind_of? Numeric",
113
+ :explanation=>
114
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."},
115
+ :autoscanned_defaults=>[1.0]},
116
+ :uprim2=>
117
+ {:should_include=>"true",
118
+ :description=>nil,
119
+ :help=>nil,
120
+ :tests=>["Tst::FLOAT"],
121
+ :gs2_name=>:uprim2,
122
+ :must_pass=>
123
+ {:test=>"kind_of? Numeric",
124
+ :explanation=>
125
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."},
126
+ :autoscanned_defaults=>[0.0]},
127
+ :nustar=>
128
+ {:should_include=>"true",
129
+ :description=>nil,
130
+ :help=>nil,
131
+ :tests=>["Tst::FLOAT"],
132
+ :gs2_name=>:nustar,
133
+ :must_pass=>
134
+ {:test=>"kind_of? Numeric",
135
+ :explanation=>
136
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."},
137
+ :autoscanned_defaults=>[-1.0]},
138
+ :nu=>
139
+ {:should_include=>"true",
140
+ :description=>nil,
141
+ :help=>nil,
142
+ :tests=>["Tst::FLOAT"],
143
+ :gs2_name=>:nu,
144
+ :must_pass=>
145
+ {:test=>"kind_of? Numeric",
146
+ :explanation=>
147
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."},
148
+ :autoscanned_defaults=>[-1.0]},
149
+ :nu_h=>
150
+ {:should_include=>"true",
151
+ :description=>nil,
152
+ :help=>nil,
153
+ :tests=>["Tst::FLOAT"],
154
+ :gs2_name=>:nu_h,
155
+ :must_pass=>
156
+ {:test=>"kind_of? Numeric",
157
+ :explanation=>
158
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."},
159
+ :autoscanned_defaults=>[0.0]},
160
+ :tperp0=>
161
+ {:should_include=>"true",
162
+ :description=>nil,
163
+ :help=>nil,
164
+ :tests=>["Tst::FLOAT"],
165
+ :gs2_name=>:tperp0,
166
+ :must_pass=>
167
+ {:test=>"kind_of? Numeric",
168
+ :explanation=>
169
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."},
170
+ :autoscanned_defaults=>[0.0]},
171
+ :tpar0=>
172
+ {:should_include=>"true",
173
+ :description=>nil,
174
+ :help=>nil,
175
+ :tests=>["Tst::FLOAT"],
176
+ :gs2_name=>:tpar0,
177
+ :must_pass=>
178
+ {:test=>"kind_of? Numeric",
179
+ :explanation=>
180
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."},
181
+ :autoscanned_defaults=>[0.0]}}},
182
+ :dist_fn_species_knobs=>
183
+ {:description=>"",
184
+ :include_conditions=>"true",
185
+ :variables=>
186
+ {:fexpr=>
187
+ {:help=>
188
+ "0.5 !Temporal implicitness parameter. Recommended value: 0.48",
189
+ :include_conditions=>"true",
190
+ :description=>
191
+ "0.5 !Temporal implicitness parameter. Recommended value: 0.48",
192
+ :tests=>["Tst::FLOAT"],
193
+ :autoscanned_defaults=>[],
194
+ :must_pass=>
195
+ [{:test=>"kind_of? Numeric",
196
+ :explanation=>
197
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."}]},
198
+ :fexpi=>
199
+ {:help=>nil,
200
+ :include_conditions=>"true",
201
+ :description=>nil,
202
+ :tests=>["Tst::FLOAT"],
203
+ :autoscanned_defaults=>[],
204
+ :must_pass=>
205
+ [{:test=>"kind_of? Numeric",
206
+ :explanation=>
207
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."}]},
208
+ :bakdif=>
209
+ {:help=>"0.0 !Spatial implicitness parameter. Recommended value: 0.05",
210
+ :include_conditions=>"true",
211
+ :description=>
212
+ "0.0 !Spatial implicitness parameter. Recommended value: 0.05",
213
+ :tests=>["Tst::FLOAT"],
214
+ :autoscanned_defaults=>[],
215
+ :must_pass=>
216
+ [{:test=>"kind_of? Numeric",
217
+ :explanation=>
218
+ "This variable must be a floating point number (an integer is also acceptable: it will be converted into a floating point number)."}]},
219
+ :bd_exp=>
220
+ {:should_include=>"true",
221
+ :description=>nil,
222
+ :help=>nil,
223
+ :tests=>["Tst::INT"],
224
+ :gs2_name=>:bd_exp,
225
+ :must_pass=>
226
+ {:test=>"kind_of? Integer",
227
+ :explanation=>"This variable must be an integer."},
228
+ :autoscanned_defaults=>["bd_exp_out"]}}}}
@@ -0,0 +1,231 @@
1
+ class CodeRunner
2
+ class Gs2::Astrogk
3
+
4
+ # See TestAstrogk
5
+
6
+ def self.test_gs2(*args)
7
+ TestAstrogk.test_gs2(*args)
8
+ end
9
+
10
+ # = Astrogk Test Suite
11
+ # This class is designed to run a set of functional tests to test the GS2 source. It is not a test suite for GS2crmod, the GS2 CodeRunner module. It takes all the input files from the folder <tt>test_cases</tt>, runs them and checks that they give the same output as the standard case. Only the NetCDF file from the standard case should be included, and should have the same name as the test case input file.
12
+
13
+ module TestAstrogk
14
+
15
+
16
+ # The folder where all the test files are stored.
17
+
18
+ TEST_FOLDER = Dir.pwd #File.dirname(__FILE__) + "../test_cases"
19
+
20
+
21
+ # Give the standardised name of the test_results folder, given the name of the test case input file
22
+
23
+ def self.results_folder(input_file)
24
+ 'test_results/' + input_file.sub(/\.in$/, '')
25
+ end
26
+
27
+ def self.test_case_folder(input_file)
28
+ TEST_FOLDER + '/' + input_file.sub(/\.in$/, '')
29
+ end
30
+
31
+ # The io object all test info is written to.
32
+
33
+ TEST_OUT = STDERR
34
+
35
+ # Run all the test cases. test_case_location should be the folder test_cases in the gs2 source.
36
+ #
37
+ # Options are
38
+ # * restart (default: true) Delete all results and start again.
39
+ # * submit (default: true) Submit any runs that haven't been submitted.
40
+ # * serial (default: true) Wait till one test run has finished before starting another
41
+
42
+ def self.test_gs2(test_case_location, options={})
43
+ Astrogk.send(:include, self)
44
+ test_case_location.sub!(/~/, ENV['HOME'])
45
+ TEST_FOLDER.gsub!(/^.*$/, test_case_location)
46
+ raise "The first argument should be the test_cases folder" unless File.basename(TEST_FOLDER) == "test_cases"
47
+ @tests_failed = {}
48
+
49
+
50
+ serial = true unless ["false", false].include? options[:serial]
51
+ restart = true unless ["false", false].include? options[:restart]
52
+ submit = true unless ["false", false].include? options[:submit]
53
+
54
+
55
+ @test_runner = CodeRunner.fetch_runner(Y: Dir.pwd, u: true)
56
+ @submitted_tests = @test_runner.runs.map{|run| run.run_name}
57
+ test_cases = Dir.entries(TEST_FOLDER).find_all do |entry|
58
+ # p entry
59
+ File.directory?(TEST_FOLDER + '/' + entry) and not entry =~ /^\./
60
+ end
61
+ # p test_cases
62
+
63
+ if restart
64
+ FileUtils.rm_r 'test_results' if FileTest.exist? 'test_results'
65
+ FileUtils.makedirs 'test_results'
66
+ end
67
+
68
+ # Submit the tests
69
+ if submit
70
+ test_cases.each do |test_case|
71
+ next if FileTest.exist? results_folder(test_case)
72
+ submit_run(test_case)
73
+ run_tests if serial
74
+ end
75
+ end
76
+ run_tests
77
+
78
+ if @tests_failed.size == 0
79
+ TEST_OUT.puts "All Tests Completed Successfully"
80
+ eputs "All Tests Completed Successfully" unless TEST_OUT == STDERR
81
+ else
82
+ eputs "Tests Were Failed"
83
+ @tests_failed.each do |name, hash|
84
+ sep = "----------------------------------------------"
85
+ TEST_OUT.puts '', sep, " Test Failed", sep
86
+ TEST_OUT.puts "Name: #{name}"
87
+ TEST_OUT.puts "Description: \n#{hash[:description]}", ''
88
+ TEST_OUT.puts "This test failed on these checks: #{hash[:checks_failed]}", ''
89
+ TEST_OUT.puts sep, ''
90
+ end
91
+ end
92
+
93
+ end
94
+
95
+ # Check to see which run has completed and run tests for those runs.
96
+
97
+ def self.run_tests
98
+ eputs "Waiting for runs to complete"
99
+ loop do
100
+ break if @submitted_tests.size ==0
101
+ @test_runner.update(false)
102
+ i = 0
103
+ loop do
104
+ tst = @submitted_tests[0]
105
+ run = @test_runner.runs.find{|run| run.run_name == tst}
106
+ if [:Complete, :Failed].include? run.status
107
+ run_checks run
108
+ @submitted_tests.delete(tst)
109
+ end
110
+ i += 1
111
+ break if i >= @submitted_tests.size
112
+ end
113
+ sleep 3
114
+ end
115
+ end
116
+
117
+
118
+ # Run the test case with the given input file.
119
+
120
+ def self.submit_run(test_case)
121
+
122
+ dir = results_folder(test_case)
123
+ input_text = File.read("#{test_case_folder(test_case)}/#{test_case}.in")
124
+
125
+ description = input_text.scan(Regexp.new("#{/^\s*!\s*description\s*=\s* /}(#{Regexp.quoted_string})")).flatten[0]
126
+ (eputs "----Rejecting '#{file}', no description provided or description is not in the correct format: description = \" description \"";return) unless description
127
+ run = Astrogk.new(@test_runner)
128
+
129
+ # This cryptic statement updates the run parameters from the input file
130
+ run.instance_eval(
131
+ Astrogk.defaults_file_text_from_input_file("#{test_case_folder(test_case)}/#{test_case}.in"))
132
+
133
+ run.run_name = test_case
134
+ run.instance_variable_set(:@dir_name, dir)
135
+ @test_runner.test_submission = true
136
+ @test_runner.submit(run)
137
+
138
+ other_files = Dir.entries(test_case_folder(test_case)).find_all do |f|
139
+ not (f =~ /\.in/ or f =~ /\.out\.nc/ or f =~ /\.svn/ or [".", ".."].include? f)
140
+ end
141
+ other_files.each do |f|
142
+ # p f
143
+ FileUtils.cp(test_case_folder(test_case)+'/'+f, results_folder(test_case)+'/'+f)
144
+ end
145
+
146
+ @test_runner.test_submission = false
147
+ @test_runner.submit(run)
148
+ @submitted_tests.push run.run_name
149
+
150
+
151
+ end
152
+
153
+ def self.run_checks(run)
154
+ checks_failed = []
155
+
156
+ input_text = File.read("#{test_case_folder(run.run_name)}/#{run.run_name}.in")
157
+ description = input_text.scan(Regexp.new("#{/^\s*!\s*description\s*=\s* /}(#{Regexp.quoted_string})")).flatten[0]
158
+ description.gsub!(/(.{25,45} |.{45})/){"#$1\n"} if description
159
+ if input_text =~ Regexp.new("#{/^\s*!\s*custom_checks\s*=\s* /}(#{Regexp.properly_nested("\\[", "\\]", false)})")
160
+ custom_checks = eval($1)
161
+ custom_checks.each{|check| checks_failed.push check unless run.run_check check}
162
+ else
163
+ checks_failed.push :standard unless run.run_check :standard
164
+ end
165
+ unless checks_failed.size == 0
166
+ @tests_failed[run.run_name] = {checks_failed: checks_failed, description: description}
167
+ end
168
+ end
169
+
170
+ # Relative error which differences cannot exceed in the standard case
171
+
172
+ TOLERANCE = 1.0e-10
173
+
174
+ # A list of variables that are allowed to be different in the standard test
175
+
176
+ EXCLUDED_VARIABLES = ['input_file']
177
+
178
+ # Check the results against standard cases using the checks described here. Any custom tests should be implemented here!
179
+
180
+ def run_check(check)
181
+ netcdf_standard_case = NumRu::NetCDF.open(TestAstrogk.test_case_folder(@run_name) + '/' + @run_name + '.out.nc')
182
+ Dir.chdir(@directory) do
183
+ case check
184
+ when :standard
185
+ netcdf = NumRu::NetCDF.open(@run_name + '.out.nc')
186
+ netcdf.vars.map{|v| v.name}.each do |v|
187
+ unless netcdf_standard_case.var(v)
188
+ TEST_OUT.puts "Warning: variable '#{v}' is missing from the test case netcdf output for '#@run_name'. Suggest updating the test case netcdf file. This is not a GS2 fault."
189
+ end
190
+ end
191
+ netcdf_standard_case.vars.map{|v| v.name}.each do |v|
192
+ next if EXCLUDED_VARIABLES.include? v
193
+ begin
194
+ unless netcdf.var(v)
195
+ TEST_OUT.puts "Error: Variable #{v} is missing from the netcdf output for #@run_name"
196
+ return false
197
+ end
198
+
199
+ narray = netcdf.var(v).get
200
+ standard_narray = netcdf_standard_case.var(v).get
201
+
202
+ if standard_narray.abs.max < TOLERANCE
203
+ if narray.abs.max < TOLERANCE
204
+ next
205
+ else
206
+ TEST_OUT.puts "Error: Variable '#{v}' has failed check in '#@run_name'"
207
+ return false
208
+ end
209
+ end
210
+
211
+
212
+ difference = narray - standard_narray
213
+ return false unless difference.abs.max / standard_narray.abs.max < TOLERANCE
214
+ # ep 'var', difference.abs.max
215
+ rescue => err
216
+ TEST_OUT.puts "Error: #{err}"
217
+ TEST_OUT.puts "Error: Variable '#{v}' has failed check in '#@run_name'"
218
+ return false
219
+ end
220
+ end
221
+ return true
222
+ end
223
+ end
224
+ end
225
+
226
+
227
+ end #module TestAstrogk
228
+
229
+ end
230
+ end
231
+
@@ -0,0 +1,200 @@
1
+ ##########################################
2
+ # = Code Runner GS2 Module
3
+ ##########################################
4
+ #
5
+ # Authors: Edmund Highcock
6
+ # Copyright: 2009 Edmund Highcock
7
+ #
8
+ # This is free software released under the GPL v3
9
+ #
10
+ # This module allows easy running of the plasma turbulence simulation code gs2 using Code Runner, by automatically organising, naming and submitting runs, and analysing the run data.
11
+ #
12
+ # See Code Runner documentation, or documentation for individual methods.
13
+ #
14
+ # Notes
15
+ #
16
+ # index variables, e.g. kx_index, ky_index etc always refer to the 1-based Fortran index, to keep correspondance with the gs2 indices. Element variables, e.g. kx_element, always refer to the 0-based C/ruby index
17
+ #
18
+ # raw NumRu::NetCDF grids are in Fortran row-major order. This means that when you access grids using the NetCDF function NetCDF#get, you must specify the indices in fortran order (but 0-based!). The NetCDF#get function then returns a C-like NArray with the indices in the opposite order. You can convert this to a Ruby Array using the method NArray#to_a (the indices will still be in the same order).
19
+
20
+
21
+ #
22
+
23
+
24
+
25
+ class CodeRunner
26
+
27
+
28
+ #CodeRunner.setup_run_class('g2') # Astrogk Inherits from GS2
29
+
30
+ # This is a customised subclass of CodeRunner::Run which allows CodeRunner to submit and analyse simulations from the gyrokinetic flux tube code AstroGK, which is principally used for simulating plasmas in magnetic confinement fusion.
31
+ #
32
+ # It performs two distinct roles: submitting simulations and analysing the data.
33
+ #
34
+ # = Submitting Simulations
35
+ #
36
+ # This principally involves generating the input file, which is a very nontrivial task. In order to do this, it maintains a complete record of every possible input parameter for AstroGK, as well as what datatype that parameter is, and sometimes what values it is allowed to take. This allows that not only to generate the input file, but to check that the input file makes sense. However, although generating the input file works beautifully, the set of sanity checks that it makes is not exhaustive: intelligent use is still required!
37
+ #
38
+ # In tandem with this, it maintains a whole set of tools for manipulating its database of input parameters. This includes updating their allowed values and also editing and accessing help for every input parameter.
39
+ #
40
+ # = Analysing Simulations
41
+ #
42
+ # The amount of analysis possible on AstroGK data is enormous, and CodeRunner hasn't got close to getting there. What it can do is:
43
+ #
44
+ # * Check if the run is complete by comparing the number of completed timesteps against nstep
45
+ # * Calculate growth rates for linear runs.
46
+ # * Check if non-linear runs have saturated and calculate fluxes for those runs.
47
+ # * Automatically plot a huge variety of different graphs, ranging from simple plots of heat flux versus time to three-dimensional plots of the spectrum and potential.
48
+
49
+
50
+ class Gs2::Astrogk < Gs2
51
+
52
+
53
+
54
+ def agk?
55
+ true
56
+ end
57
+
58
+ # Include the other files
59
+ @code_module_folder = folder = File.dirname(File.expand_path(__FILE__)) + '/astrogk' # i.e. the directory this file is in
60
+ setup_namelists(folder)
61
+ require folder + '/graphs.rb'
62
+ # require folder + '/namelist_tools.rb'
63
+ # require folder + '/input_file_tools.rb'
64
+ require folder + '/gsl_data.rb'
65
+ require folder + '/check_convergence.rb'
66
+ require folder + '/calculations.rb'
67
+ require folder + '/ingen.rb'
68
+ require folder + '/properties.rb'
69
+ require folder + '/test_gs2.rb'
70
+
71
+ NaN = GSL::NAN
72
+ # GSL::Neg
73
+
74
+
75
+
76
+
77
+
78
+ ################################################
79
+ # Quantities that are calculated or determined by CodeRunner
80
+ # after the simulation has ended, i.e. quantities
81
+ # that are not available from the AstroGK output files.
82
+ ################################################
83
+ # Get GS2 results and add any
84
+ # astrogk ones (currently empty)
85
+
86
+ @results = rcp.results + []
87
+
88
+ ###############################################
89
+ # Other useful information about the run
90
+ ###############################################
91
+
92
+ @astrogk_run_info = rcp.gs2_run_info + []
93
+
94
+ @run_info = @astrogk_run_info.dup
95
+
96
+
97
+
98
+ @naming_pars = rcp.naming_pars + []
99
+
100
+ @code_long = "AstroGK Astrophysical Gyrokinetic Code"
101
+
102
+ @excluded_sub_folders =[]
103
+
104
+ def run_namelist_backwards_compatibility
105
+ end
106
+ def set_nprocs
107
+
108
+ if (nprocs_in = @nprocs) =~ /^x/
109
+ max = max_nprocs_no_x
110
+ #Astrogk seems to not like you actually having naky * nspec * negrid processors.. reduce it
111
+ for i in 2...max
112
+ if max%i ==0
113
+ max = max / i
114
+ break
115
+ end
116
+ end
117
+ nodes = 0
118
+ @nprocs = "#{nodes}#{nprocs_in}"
119
+ loop do
120
+ nodes += 1
121
+ @nprocs = "#{nodes}#{nprocs_in}"
122
+ if actual_number_of_processors > max
123
+ nodes -= 1
124
+ @nprocs = "#{nodes}#{nprocs_in}"
125
+ break
126
+ end
127
+ end
128
+ end
129
+ end
130
+ def input_file_header
131
+ <<EOF
132
+ !==============================================================================
133
+ ! AstroGK INPUT FILE automatically generated by CodeRunner
134
+ !==============================================================================
135
+ !
136
+ ! AstroGK is a gyrokinetic flux tube initial value turbulence code
137
+ ! which can be used for fusion or astrophysical plasmas.
138
+ !
139
+ ! See http://gyrokinetics.sourceforge.net
140
+ !
141
+ ! CodeRunner is a framework for the automated running and analysis
142
+ ! of large simulations.
143
+ !
144
+ ! See http://coderunner.sourceforge.net
145
+ ! by CodeRunner version #{CodeRunner::CODE_RUNNER_VERSION.to_s}
146
+ !
147
+ !==============================================================================
148
+
149
+ EOF
150
+ end
151
+ def self.defaults_file_header
152
+ <<EOF1
153
+ ######################################################################
154
+ # Automatically generated defaults file for AstroGK CodeRunner module#
155
+ # #
156
+ # This defaults file specifies a set of defaults for AstroGK which are#
157
+ # used by CodeRunner to set up and run GS2 simulations. #
158
+ # #
159
+ # Created #{Time.now.to_s} #
160
+ # #
161
+ ######################################################################
162
+
163
+ @defaults_file_description = ""
164
+ EOF1
165
+ end
166
+
167
+ @source_code_subfolders = ['utils']
168
+
169
+ folder = File.dirname(File.expand_path(__FILE__)) # i.e. the directory this file is in
170
+
171
+ def self.transfer_gs2_docs
172
+ CodeRunner.setup_run_class('gs2')
173
+ p CodeRunner::Astrogk.ancestors
174
+ intersection = (CodeRunner::Gs2.rcp.namelists.keys&CodeRunner::Astrogk.rcp.namelists.keys)
175
+ gs2namelists=CodeRunner::Gs2.rcp.namelists
176
+ intersection.each do | namelist |
177
+ p namelist
178
+ gs2namelist=gs2namelists[namelist]
179
+ next unless gs2namelist
180
+ self.rcp.namelists[namelist][:variables].each do | varname, varhash |
181
+ p varname
182
+ if match = (gs2namelist[:variables][varname]) # or gs2namelist[:variables].find{|gs2varname,gs2varhash| gs2varhash[:code_name]==varhash[:code_name]}[1])
183
+ puts "Found corresponding variable #{varname}"
184
+ #p match
185
+ puts "Found help: #{match[:help]}"
186
+ varhash[:help] = match[:help] if match[:help]
187
+ varhash[:description] = match[:description]
188
+ save_namelists
189
+ end
190
+ end
191
+
192
+ end
193
+ end
194
+ end # class Astrogk
195
+ # For backwards compatibility
196
+ Astrogk = Gs2::Astrogk
197
+
198
+ end # class CodeRunner
199
+
200
+