gs2crmod 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+