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,187 @@
1
+ ###################################
2
+ # GS2 CodeRunner Module: GSL Tools
3
+ #
4
+ # Various useful methods for manipulating gsl data.
5
+ #
6
+ ###################################
7
+
8
+ module GSL
9
+ def self.cache
10
+ @cache ||= {}
11
+ @cache
12
+ end
13
+ end
14
+
15
+
16
+ class GSL::Vector
17
+ def pieces(no_pieces)
18
+ ans = []
19
+ piece_sizes = []
20
+
21
+ for i in 0...no_pieces
22
+ ans.push []; piece_sizes[i] = 0
23
+ end
24
+ for j in 0...size
25
+ piece_sizes[j % no_pieces] += 1
26
+ end
27
+ # p ans, piece_sizes
28
+ accum = 0
29
+ piece_sizes.each_with_index do |piece_size, piece|
30
+ ans[piece] = self.subvector(accum, piece_size)
31
+ accum += piece_size
32
+ end
33
+ return ans
34
+ end
35
+
36
+ def from_box_order
37
+ size = self.size
38
+ v1, v2 = self.subvector(0, (size+1)/2), self.subvector((size+1)/2, (size-1)/2)
39
+ return v2.connect(v1)
40
+ end
41
+ def to_box_order
42
+ size = self.size
43
+ v1, v2 = self.subvector(0, (size-1)/2), self.subvector((size-1)/2, (size+1)/2)
44
+ return v2.connect(v1)
45
+ end
46
+
47
+ end
48
+
49
+
50
+
51
+ class GSL::Matrix::Complex
52
+
53
+ def self.re_im(re, im)
54
+ raise "Shape of real and imaginary matrices must match" unless re.shape == im.shape
55
+ rows, cols = re.shape
56
+ mat = alloc(rows, cols)
57
+ for i in 0...rows
58
+ for j in 0...cols
59
+ mat[i,j] = GSL::Complex.alloc([re[i,j], im[i,j]])
60
+ end
61
+ end
62
+ return mat
63
+ end
64
+
65
+
66
+ def backward_cols_c2c(normalise = false)
67
+ gm = self.dup
68
+ rows, cols = gm.shape
69
+ table = GSL.cache[[:fft_table, :complex, rows]] ||= GSL::FFT::ComplexWavetable.alloc(rows)
70
+ work = GSL.cache[[:fft_work, :complex, rows]] ||= GSL::FFT::ComplexWorkspace.alloc(rows)
71
+ for i in 0...cols
72
+ vec = gm.col(i)
73
+ vec.backward!(table, work)
74
+ for j in 0...rows
75
+ gm[j,i] = vec[j]
76
+ end
77
+ end
78
+ gm = gm / rows if normalise
79
+ gm
80
+ end
81
+
82
+ def forward_cols_c2c
83
+ gm = self.dup
84
+ rows, cols = gm.shape
85
+ table = GSL.cache[[:fft_table, :complex, rows]] ||= GSL::FFT::ComplexWavetable.alloc(rows)
86
+ work = GSL.cache[[:fft_work, :complex, rows]] ||= GSL::FFT::ComplexWorkspace.alloc(rows)
87
+ for i in 0...cols
88
+ vec = gm.col(i)
89
+ vec.forward!(table, work)
90
+ for j in 0...rows
91
+ gm[j,i] = vec[j]
92
+ end
93
+ end
94
+ gm
95
+ end
96
+
97
+ def backward_rows_cc2r(normalise = false)
98
+ gm = self.dup
99
+ rows, cols = gm.shape
100
+ # if cols%2 == 0
101
+ # newcols = cols*2
102
+ # else
103
+ # newcols = cols*2 - 1
104
+ # end
105
+ was_even = rows.times.inject(true) do |bool, i|
106
+ bool and (gm[i, cols - 1].imag == 0.0)
107
+ end
108
+ # ep was_even
109
+
110
+ if was_even
111
+ newcols = cols * 2 - 2
112
+ else
113
+ newcols = cols * 2 - 1
114
+ end
115
+ gm_re = GSL::Matrix.alloc(rows, newcols)
116
+
117
+ table = GSL.cache[[:fft_table, :real, newcols]] ||= GSL::FFT::RealWavetable.alloc(newcols)
118
+ work = GSL.cache[[:fft_work, :real, newcols]] ||= GSL::FFT::RealWorkspace.alloc(newcols)
119
+ row = GSL::Vector::Complex.alloc(cols)
120
+ # p rows
121
+ for i in 0...rows
122
+ # p i
123
+ # row = gm.row(i)
124
+ (0...cols).each{|j| row[j] = gm[i,j]}
125
+ if was_even
126
+ vec = row.concat(row.subvector(1, row.size - 2).reverse.conjugate) if cols > 2
127
+ else
128
+ vec = row.concat(row.subvector(1, row.size - 1).reverse.conjugate) if cols > 1
129
+ end
130
+ vec.backward!(table, work)
131
+ for j in 0...newcols
132
+ gm_re[i,j] = vec[j].real
133
+ end
134
+ end
135
+ gm_re = gm_re / newcols.to_f if normalise
136
+ gm_re
137
+ end
138
+
139
+ end
140
+
141
+ class GSL::Matrix
142
+
143
+ def move_rows_from_box_order
144
+ rows, cols = self.shape
145
+ gm1, gm2 = self.view(0,0, (rows + 1)/2, cols), self.view((rows + 1)/2, 0, (rows - 1)/2, cols)
146
+ return gm2.vertcat(gm1)
147
+ end
148
+ def move_cols_from_box_order
149
+ rows, cols = self.shape
150
+ gm1, gm2 = self.view(0,0, rows, (cols + 1)/2), self.view(0, (cols + 1)/2, rows, (cols - 1)/2)
151
+ return gm2.horzcat(gm1)
152
+ end
153
+
154
+
155
+ def forward_rows_r2cc
156
+ gm = self.dup
157
+ rows, cols = gm.shape
158
+ if cols%2 == 0
159
+ newcols = (cols+2)/2
160
+ else
161
+ newcols = (cols+1)/2
162
+ end
163
+ gm_cc = GSL::Matrix::Complex.alloc(rows, newcols)
164
+
165
+ table = GSL.cache[[:fft_table, :real, cols]] ||= GSL::FFT::RealWavetable.alloc(cols)
166
+ work = GSL.cache[[:fft_work, :real, cols]] ||= GSL::FFT::RealWorkspace.alloc(cols)
167
+ row = GSL::Vector.alloc(cols)
168
+ for i in 0...rows
169
+ (0...cols).each{|j| row[j] = gm[i,j]}
170
+ # p i
171
+ # row = gm.get_row(i)
172
+ # vec_out = GSL::Vector::Complex.alloc(row.size)
173
+ # (0...row.size).each{|j| vec[j] = row[j]}
174
+ # if cols%2 == 0
175
+ # vec_out = vec.concat(vec.subvector(1, vec.size - 2).reverse.conjugate)
176
+ # else
177
+ # vec_out = vec.concat(vec.subvector(1, vec.size - 1).reverse.conjugate)
178
+ # end
179
+ view = row.forward(table, work).halfcomplex_to_complex
180
+ for j in 0...newcols
181
+ gm_cc[i,j] = view[j]
182
+ end
183
+ end
184
+ return gm_cc
185
+ end
186
+
187
+ end
@@ -0,0 +1,218 @@
1
+ class CodeRunner
2
+ class Gs2
3
+
4
+ MAX_NAME_SIZE = 310
5
+
6
+
7
+ def warning(message)
8
+ eputs "Warning: " + message; sleep 0.3
9
+ end
10
+
11
+ class InputFileError < StandardError
12
+ end
13
+
14
+ def error(message)
15
+ raise InputFileError.new("Error: " + message)
16
+ end
17
+
18
+ def test_failed(namelist, var, gs2_var, tst)
19
+ return <<EOF
20
+
21
+ ---------------------------
22
+ Test Failed
23
+ ---------------------------
24
+
25
+ Namelist: #{namelist}
26
+ Variable: #{var}
27
+ GS2 Name: #{gs2_var}
28
+ Value: #{send(var)}
29
+ Test: #{tst[:test]}
30
+ Explanation: #{tst[:explanation]}
31
+
32
+ ---------------------------
33
+ EOF
34
+
35
+ end
36
+
37
+
38
+ def namelist_test_failed(namelist, tst)
39
+ return <<EOF
40
+
41
+ ---------------------------
42
+ Test Failed
43
+ ---------------------------
44
+
45
+ Namelist: #{namelist}
46
+ Test: #{tst[:test]}
47
+ Explanation: #{tst[:explanation]}
48
+
49
+ ---------------------------
50
+ EOF
51
+
52
+ end
53
+
54
+ # Checks input parameters for inconsistencies and prints a report.
55
+
56
+ def run_namelist_tests(namelist, hash, enum = nil)
57
+ ext = enum ? "_#{enum}" : ""
58
+ hash[:must_pass].each do |tst|
59
+ error(namelist_test_failed(namelist, tst)) unless instance_eval(tst[:test])
60
+ end if hash[:must_pass]
61
+ hash[:should_pass].each do |tst|
62
+ warning(namelist_test_failed(namelist, tst)) unless instance_eval(tst[:test])
63
+ end if hash[:should_pass]
64
+ hash[:variables].each do |var, var_hash|
65
+ gs2_var = (var_hash[:gs2_name] or var)
66
+ cr_var = var+ext.to_sym
67
+ if send(cr_var) and (not var_hash[:should_include] or eval(var_hash[:should_include]))
68
+ var_hash[:must_pass].each do |tst|
69
+ error(test_failed(namelist, cr_var, gs2_var, tst)) unless send(cr_var).instance_eval(tst[:test])
70
+ end if var_hash[:must_pass]
71
+ var_hash[:should_pass].each do |tst|
72
+ warning(test_failed(namelist, cr_var, gs2_var, tst)) unless send(cr_var).instance_eval(tst[:test])
73
+ end if var_hash[:should_pass]
74
+ if (var_hash[:allowed_values] or var_hash[:text_options])
75
+ tst = {test: "#{(var_hash[:allowed_values] or var_hash[:text_options]).inspect}.include? self", explanation: "The variable must have one of these values"}
76
+ error(test_failed(namelist, cr_var, gs2_var, tst)) unless send(cr_var).instance_eval(tst[:test])
77
+ end
78
+
79
+ end
80
+ end
81
+ end
82
+
83
+
84
+ # Eventually, this will be a full port of the tool of the same name in the GS2 folder. At the moment it runs a limited set of tests for common errors in the input parameters (including type checking).
85
+
86
+ def ingen
87
+
88
+ # Sections
89
+
90
+ # Namelist Tests
91
+ # Grids
92
+ # Parallelisation
93
+ # Initialisation
94
+ # Diagnostics
95
+ # Misc
96
+
97
+ # Namelist Tests
98
+
99
+ rcp.namelists.each do |namelist, hash|
100
+ next if hash[:should_include].kind_of? String and not eval(hash[:should_include])
101
+ if en = hash[:enumerator]
102
+ #ep 'en', en, namelist
103
+ next unless send(en[:name])
104
+ send(en[:name]).times do |i|
105
+ run_namelist_tests(namelist, hash, i+1)
106
+ end
107
+ else
108
+ run_namelist_tests(namelist, hash)
109
+ end
110
+ end
111
+
112
+
113
+ # Grid Errors
114
+
115
+ # naky
116
+ warning("Setting naky when non-linear mode is on is not recommended.") if @naky and @nonlinear_mode == "on"
117
+
118
+ warning("You have set both ny and naky; naky will override ny.") if @ny and @naky
119
+
120
+ error("Boundary options should not be periodic with finite magnetic shear") if @boundary_option == "periodic" and ((@s_hat_input and @s_hat_input.abs > 1.0e-6) or (@shat and @shat.abs > 1.0e-6))
121
+
122
+ # delt
123
+
124
+ error("Please specify delt") unless @delt
125
+ error("delt <= 0") if @delt <= 0.0
126
+ warning("Nonlinear run with delt_minimum unspecified.") if @nonlinear_mode=="on" and not @delt_minimum
127
+
128
+ error("delt (#@delt) < delt_minimum") if @delt and @delt_minimum and @delt < @delt_minimum
129
+
130
+ # Parallelisation Errors
131
+
132
+
133
+ # Check whether we are parallelising over x
134
+ 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"
135
+
136
+
137
+ # Initialisation Errors
138
+
139
+ # Check if restart folder exists
140
+ if @restart_file and @restart_file =~ /^(?<folder>[^\/]+)\//
141
+ folder = $~[:folder]
142
+ warning("Folder #{folder}, specified in restart_file, not present. NetCDF save may fail") unless FileTest.exist?(folder)
143
+ end
144
+
145
+ error("Setting @restart_file as an empty string will result in hidden restart files.") if @restart_file == ""
146
+
147
+ error("ginit_option is 'many' but is_a_restart is false") if @ginit_option == "many" and not @is_a_restart
148
+
149
+ #Diagnostic errors
150
+ #
151
+ #Check whether useful diagnostics have been omitted.
152
+
153
+ not_set = [:write_verr, :save_for_restart, :write_nl_flux, :write_final_fields, :write_final_moments].find_all do |diagnostic|
154
+ not (send(diagnostic) and send(diagnostic).fortran_true?)
155
+ end
156
+
157
+ if not_set.size > 0
158
+ str = not_set.inject("") do |str, diagnostic|
159
+ str + "\n\t#{diagnostic} --- " + rcp.namelists[diagnostics_namelist][:variables][diagnostic][:description] rescue str
160
+ end
161
+ warning("The following useful diagnostics were not set:" + str) if str.length > 0
162
+ end
163
+
164
+ 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"
165
+
166
+ #{
167
+ #write_verr: "Velocity space diagnostics will not be output for this run"
168
+ #}.each do |var, warn|
169
+ #warning(v"#{var} not set or .false. --- " + warn) unless send(var) and send(var).fortran_true?
170
+ #end
171
+
172
+ warning("You will write out diagnostics less than 50 times") if @nstep/@nwrite < 50
173
+
174
+ #Miscellaneous errors.
175
+
176
+ 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
177
+
178
+ warning("You are submitting a nonlinear run with no dissipation.") if @nonlinear_mode == "on" and @hyper_option=="none" and @collision_model=="none"
179
+
180
+ 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}
181
+
182
+ warning("The system will abort with rapid timestep changes...") if !@abort_rapid_time_step_change or @abort_rapid_time_step_change.fortran_true?
183
+
184
+
185
+
186
+ end
187
+
188
+ # A hash which gives the actual numbers of gridpoints indexed by their corresponding letters in the layout string.
189
+
190
+ def gridpoints
191
+ gridpoints = {'l' => @ngauss, 'e' => @negrid, 's' => @nspec}
192
+ if @grid_option == "single"
193
+ gridpoints.absorb({'x'=>1, 'y'=>1})
194
+ else
195
+ gridpoints.absorb({'x' => (2.0 * (@nx - 1.0) / 3.0 + 1.0).floor, 'y' => (@naky or ((@ny - 1.0) / 3.0 + 1.0).floor)})
196
+ end
197
+ return gridpoints
198
+ end
199
+
200
+ def cumulative_gridpoints
201
+ c = 1
202
+ error("Please specify layout") unless @layout
203
+ @layout.split(//).reverse.inject({}){|hash, let| c*=gridpoints[let]; hash[let] = c; hash}
204
+ end
205
+ # ep parallelisation
206
+ def max_nprocs_no_x
207
+ parallelisation = cumulative_gridpoints
208
+ parallelisation[parallelisation.keys[parallelisation.keys.index('x') - 1]]
209
+ end
210
+
211
+
212
+ def diagnostics_namelist
213
+ :gs2_diagnostics_knobs
214
+ end
215
+ end
216
+ end
217
+
218
+