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.
- data/.document +5 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +20 -0
- data/README.md +4 -0
- data/README.rdoc +19 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/ext/extconf.rb +9 -0
- data/ext/gs2crmod_ext.c +366 -0
- data/gs2crmod.gemspec +98 -0
- data/include/gs2crmod_ext.h +58 -0
- data/lib/gs2crmod/astrogk/astrogk.rb +201 -0
- data/lib/gs2crmod/astrogk/calculations.rb +57 -0
- data/lib/gs2crmod/astrogk/check_convergence.rb +7 -0
- data/lib/gs2crmod/astrogk/deleted_variables.rb +76 -0
- data/lib/gs2crmod/astrogk/graphs.rb +13 -0
- data/lib/gs2crmod/astrogk/gsl_data.rb +13 -0
- data/lib/gs2crmod/astrogk/gsl_tools.rb +182 -0
- data/lib/gs2crmod/astrogk/ingen.rb +18 -0
- data/lib/gs2crmod/astrogk/input_file_tools.rb +7 -0
- data/lib/gs2crmod/astrogk/namelist_tools.rb +14 -0
- data/lib/gs2crmod/astrogk/namelists.rb +2800 -0
- data/lib/gs2crmod/astrogk/properties.rb +17 -0
- data/lib/gs2crmod/astrogk/species_dependent_namelists.rb +228 -0
- data/lib/gs2crmod/astrogk/test_gs2.rb +231 -0
- data/lib/gs2crmod/astrogk.rb +200 -0
- data/lib/gs2crmod/calculations.rb +780 -0
- data/lib/gs2crmod/check_convergence.rb +179 -0
- data/lib/gs2crmod/deleted_variables.rb +916 -0
- data/lib/gs2crmod/graphs.rb +1899 -0
- data/lib/gs2crmod/graphs_rdoc.rb +556 -0
- data/lib/gs2crmod/gs2.rb +1143 -0
- data/lib/gs2crmod/gsl_data.rb +1181 -0
- data/lib/gs2crmod/gsl_data_3d.rb +705 -0
- data/lib/gs2crmod/gsl_tools.rb +187 -0
- data/lib/gs2crmod/ingen.rb +218 -0
- data/lib/gs2crmod/namelists.rb +5142 -0
- data/lib/gs2crmod/properties.rb +22 -0
- data/lib/gs2crmod/species_dependent_namelists.rb +228 -0
- data/lib/gs2crmod/test_gs2.rb +231 -0
- data/lib/gs2crmod.rb +2 -0
- data/lib/gs2crmod_extension.rb +1 -0
- data/test/helper.rb +18 -0
- data/test/test_gs2crmod.rb +7 -0
- 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
|
+
|