gs2crmod 0.11.78 → 0.11.79
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.
- checksums.yaml +7 -0
- data/VERSION +1 -1
- data/ext/gs2crmod_ext.c +0 -399
- data/gs2crmod.gemspec +7 -5
- data/lib/gs2crmod/calculations.rb +4 -35
- data/lib/gs2crmod/graphs.rb +1 -1
- data/lib/gs2crmod/gs2.rb +0 -236
- data/lib/gs2crmod/gsl_data.rb +1305 -1304
- metadata +22 -40
data/lib/gs2crmod/gsl_data.rb
CHANGED
@@ -7,112 +7,112 @@
|
|
7
7
|
#
|
8
8
|
|
9
9
|
class NumRu::NetCDF
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
aliold :var
|
11
|
+
def var(*args)
|
12
|
+
if args[0].kind_of? Symbol
|
13
|
+
args[0] = args[0].to_s
|
14
|
+
end
|
15
|
+
return old_var(*args)
|
16
|
+
end
|
17
17
|
end
|
18
18
|
class CodeRunner
|
19
|
-
class Gs2
|
19
|
+
class Gs2
|
20
20
|
|
21
21
|
|
22
22
|
eval(File.read(File.dirname(__FILE__) + '/gsl_tools.rb'), GLOBAL_BINDING, File.dirname(__FILE__) + '/gsl_tools.rb')
|
23
23
|
|
24
24
|
# def gsl_vector(name, options={})
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
25
|
+
# if options[:t_index] or options[:frame_index] or not [:Failed, :Complete].include? status
|
26
|
+
# return get_gsl_vector(name, options)
|
27
|
+
# else
|
28
|
+
# return cache[[:gsl_vector, name, options]] ||= get_gsl_vector(name, options)
|
29
|
+
# end
|
30
30
|
# end
|
31
31
|
|
32
32
|
def netcdf_file
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
33
|
+
#if @runner.cache[:runs] and (open = @runner.cache[:runs].keys.find_all{|id| @runner.cache[:runs][id][:netcdf_file]}).size > 200
|
34
|
+
#ep "my id", id
|
35
|
+
if (open = @runner.run_list.keys.find_all{|id| @runner.run_list[id].cache[:netcdf_file]}).size > 200
|
36
|
+
open = open.sort_by{|id| @runner.run_list[id].cache[:netcdf_file_otime]}
|
37
|
+
@runner.run_list[open[0]].ncclose
|
38
|
+
end
|
39
|
+
|
40
|
+
if cache[:netcdf_file] and not [:Complete, :Failed].include? @status
|
41
|
+
ncclose
|
42
|
+
end
|
43
|
+
cache[:netcdf_file_otime] = Time.now.to_i
|
44
|
+
cache[:netcdf_file] ||= NumRu::NetCDF.open(netcdf_filename)
|
45
|
+
cache[:netcdf_file].sync
|
46
|
+
cache[:netcdf_file]
|
47
47
|
end
|
48
48
|
|
49
49
|
def netcdf_filename
|
50
|
-
|
50
|
+
@directory + '/' + @run_name + '.out.nc'
|
51
51
|
end
|
52
52
|
|
53
53
|
|
54
54
|
def ncclose
|
55
|
-
|
56
|
-
|
55
|
+
cache[:netcdf_file].close
|
56
|
+
cache.delete(:netcdf_file)
|
57
57
|
end
|
58
58
|
|
59
59
|
|
60
60
|
|
61
61
|
module FixNormOption
|
62
62
|
#class << self
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
63
|
+
def fix_norm_action(options)
|
64
|
+
case options[:set_norm_option]
|
65
|
+
when "t_over_m", "bd"
|
66
|
+
if ["t_over_m", "bd"].include? @norm_option
|
67
|
+
return :none
|
68
|
+
else
|
69
|
+
return :from_root_2
|
70
|
+
end
|
71
|
+
else
|
72
|
+
#eputs "else", norm_option
|
73
|
+
if ["t_over_m", "bd"].include? @norm_option
|
74
|
+
#eputs "norm old"
|
75
|
+
return :to_root_2
|
76
|
+
else
|
77
|
+
return :none
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def fix_heat_flux_norm(tensor, options={})
|
83
|
+
case fix_norm_action(options)
|
84
|
+
when :none
|
85
|
+
#eputs "none"
|
86
|
+
return tensor
|
87
|
+
when :to_root_2
|
88
|
+
eputs "to_root_2"
|
89
|
+
return tensor / 2.0**1.5
|
90
|
+
when :from_root_2
|
91
|
+
return tensor * 2.0**1.5
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Return tensor normalised according to options[:set_norm_option]
|
96
|
+
# (which may be "t_over_m", "bd" or "with_root_2", "mtk" etc)
|
97
|
+
# regardless of the original normalisation.
|
98
|
+
#
|
99
|
+
# <tt>power</tt> should be the power to which the reference thermal
|
100
|
+
# velocity is raised in the normalising quantity. For example,
|
101
|
+
# <tt>t</tt> is normalised to a / v_thr, so for times, power should
|
102
|
+
# be set equal to -1.
|
103
|
+
|
104
|
+
def fix_norm(tensor, power, options={})
|
105
|
+
case fix_norm_action(options)
|
106
|
+
when :none
|
107
|
+
#eputs "none"
|
108
|
+
return tensor
|
109
|
+
when :to_root_2
|
110
|
+
eputs "to_root_2"
|
111
|
+
return tensor / 2.0**(0.5 * power)
|
112
|
+
when :from_root_2
|
113
|
+
return tensor * 2.0**(0.5 * power)
|
114
|
+
end
|
115
|
+
end
|
116
116
|
|
117
117
|
#end # class << self
|
118
118
|
end # module FixNormOption
|
@@ -121,188 +121,188 @@ include FixNormOption
|
|
121
121
|
|
122
122
|
def gsl_vector(name, options={})
|
123
123
|
Dir.chdir(@directory) do
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
124
|
+
options[:t_index_window] ||= @scan_index_window
|
125
|
+
options.setup_time_window
|
126
|
+
if [:ky, :kx].include? name.to_sym
|
127
|
+
vec = fix_norm(
|
128
|
+
GSL::Vector.alloc(netcdf_file.var(name.to_s).get.to_a.sort),
|
129
|
+
-1, options
|
130
|
+
) # ky, ky are normalised to 1 / rho_i
|
131
|
+
if i = options[:interpolate_ + name.to_s.sub(/k/, '').to_sym]
|
132
|
+
if name.to_sym == :ky
|
133
|
+
s = (vec.size - 1)*i + 1
|
134
|
+
#return vec.connect(GSL::Vector.alloc((vec.size-1)*(i-1)) * 0.0)
|
135
|
+
return (0...s).map{|k| k.to_f * vec[1]}.to_gslv
|
136
|
+
else
|
137
|
+
size = vec.size
|
138
|
+
#vec = vec.to_box_order
|
139
|
+
raise "Hmmm, kx.size should be odd" unless size%2 == 1
|
140
|
+
s = (size-1)/2 * i
|
141
|
+
return (-s..s).to_a.map{|ii| ii.to_f * vec.to_box_order[1]}.to_gslv
|
142
|
+
#new_vec = GSL::Vector.alloc((s-1)*i + 1)
|
143
|
+
#new_vec *= 0.0
|
144
|
+
#for j in 0...((s-1)/2+1)
|
145
|
+
#new_vec[j] = vec[j]
|
146
|
+
#end
|
147
|
+
#for j in 0...((s-1)/2)
|
148
|
+
#new_vec[-j-1] = vec[-j-1]
|
149
|
+
#end
|
150
|
+
#return new_vec.from_box_order
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
else
|
155
|
+
return vec
|
156
|
+
end
|
157
|
+
elsif [:theta].include? name.to_sym
|
158
|
+
#ep options; gets
|
159
|
+
#vec = GSL::Vector.alloc(netcdf_file.var(name.to_s).get({'start' => [options[:thetamin]||0], 'end' => [options[:thetamax]||-1]}).to_a)
|
160
|
+
vec = GSL::Vector.alloc(netcdf_file.var(name.to_s).get.to_a)
|
161
|
+
if gryfx? and options[:periodic]
|
162
|
+
#vec = vec.connect([2.0*vec[-1] - vec[-2]].to_gslv)
|
163
|
+
vec = vec.connect([-vec[0]].to_gslv)
|
164
|
+
end
|
165
|
+
if ith = options[:interpolate_theta]
|
166
|
+
osize = vec.size
|
167
|
+
newsize = (osize-1)*ith+1
|
168
|
+
newvec = GSL::Vector.alloc(newsize)
|
169
|
+
newvec[newsize-1] = vec[osize-1]# * ith.to_f
|
170
|
+
for i in 0...(newsize-1)
|
171
|
+
im = i%ith
|
172
|
+
frac = im.to_f/ith.to_f
|
173
|
+
#iold = (i-im)/(new_shape[-1]-1)*(shape[-1]-1)
|
174
|
+
iold = (i-im)/ith
|
175
|
+
newvec[i] = (vec[iold] * (1.0-frac) + vec[iold+1] * frac)
|
176
|
+
end
|
177
|
+
vec = newvec
|
178
|
+
end
|
179
|
+
start = options[:thetamin]||0
|
180
|
+
endv = options[:thetamax]||vec.size-1
|
181
|
+
#ep ['options', options, 'vec.size', vec.size]
|
182
|
+
vec = vec.subvector(start, (endv-start+1)).dup
|
183
|
+
return vec
|
184
|
+
elsif name.to_sym == :t
|
185
|
+
#options.setup_time_window
|
186
|
+
t = GSL::Vector.alloc(netcdf_file.var(name.to_s).get('start' => [options[:begin_element]], 'end' => [options[:end_element]]).to_a)
|
187
|
+
t = t - t[0] if options[:sync_time]
|
188
|
+
return fix_norm(t, -1, options) # t is normalised to a/v_thi
|
189
|
+
end
|
190
|
+
options = eval(options) if options.class == String
|
191
|
+
if options[:saturated_time_average] or options[:sta]
|
192
|
+
raise "Not Saturated" unless @saturation_time_index
|
193
|
+
tmax = list(:t).keys.max
|
194
|
+
return ((@saturation_time_index..tmax).to_a.map do |t_index|
|
195
|
+
gsl_vector(name, options.dup.absorb({t_index: t_index, saturated_time_average: nil, sta: nil}))
|
196
|
+
end).sum / (list(:t).values.max - list(:t)[@saturation_time_index])
|
197
|
+
elsif options[:time_average] or options[:ta]
|
198
|
+
tmax = list(:t).keys.max
|
199
|
+
start_t = 2
|
200
|
+
return ((start_t..tmax).to_a.map do |t_index|
|
201
|
+
gsl_vector(name, options.dup.absorb({t_index: t_index, time_average: nil, ta: nil}))
|
202
|
+
end).sum / (list(:t).values.max - list(:t)[start_t])
|
203
|
+
end
|
204
|
+
if method = self.class.instance_methods.find{|meth| (name + '_gsl_vector').to_sym == meth}
|
205
|
+
options[:graphkit_name] = name
|
206
|
+
return send(method, options)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
raise "GSL Vector #{name} not found"
|
210
210
|
end
|
211
211
|
|
212
212
|
module GSLVectors
|
213
213
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
#
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
#
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
214
|
+
# The square of the potential summed over all wave numbers, indexed by time, normalised to (e/T)(rho_1/a).
|
215
|
+
|
216
|
+
def phi2tot_over_time_gsl_vector(options)
|
217
|
+
|
218
|
+
Dir.chdir(@directory) do #Necessary options: ky
|
219
|
+
#log 'about to open netcdf file'
|
220
|
+
#options.setup_time_window
|
221
|
+
phis = netcdf_file.var('phi2').get('start'=>[options[:begin_element]], 'end'=>[options[:end_element]] ).to_a
|
222
|
+
log 'about to allocate gsl vector'
|
223
|
+
vec = GSL::Vector.alloc(phis)
|
224
|
+
log 'finished'
|
225
|
+
return fix_norm(vec, 1, options)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
def apar2_over_time_gsl_vector(options)
|
229
|
+
|
230
|
+
Dir.chdir(@directory) do #Necessary options: ky
|
231
|
+
#log 'about to open netcdf file'
|
232
|
+
#options.setup_time_window
|
233
|
+
phis = netcdf_file.var('apar2').get('start'=>[options[:begin_element]], 'end'=>[options[:end_element]] ).to_a
|
234
|
+
log 'about to allocate gsl vector'
|
235
|
+
vec = GSL::Vector.alloc(phis)
|
236
|
+
log 'finished'
|
237
|
+
return fix_norm(vec, 1, options)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def transient_es_heat_flux_amplification_over_kx_gsl_vector(options)
|
242
|
+
options[:direction] = :kx
|
243
|
+
transient_es_heat_flux_amplification_over_kxy_gsl_vector(options)
|
244
|
+
end
|
245
|
+
|
246
|
+
def transient_es_heat_flux_amplification_over_ky_gsl_vector(options)
|
247
|
+
options[:direction] = :ky
|
248
|
+
transient_es_heat_flux_amplification_over_kxy_gsl_vector(options)
|
249
|
+
end
|
250
|
+
def transient_es_heat_flux_amplification_over_kxy_gsl_vector(options)
|
251
|
+
Dir.chdir(@directory) do # i.e. phi2_by_ky_vs_time or phi2_by_kx_vs_time
|
252
|
+
kxy = options[:direction].to_sym
|
253
|
+
|
254
|
+
# ep :growth_rate_at_ + kxy
|
255
|
+
p send(:transient_es_heat_flux_amplification_at_species_at_ + kxy)
|
256
|
+
return GSL::Vector.alloc(send(:transient_es_heat_flux_amplification_at_species_at_ + kxy)[options[:species_index]-1].values)
|
257
|
+
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def transient_amplification_over_kx_gsl_vector(options)
|
262
|
+
options[:direction] = :kx
|
263
|
+
transient_amplification_over_kxy_gsl_vector(options)
|
264
|
+
end
|
265
|
+
def transient_amplification_over_ky_gsl_vector(options)
|
266
|
+
options[:direction] = :ky
|
267
|
+
transient_amplification_over_kxy_gsl_vector(options)
|
268
|
+
end
|
269
|
+
def transient_amplification_over_kxy_gsl_vector(options)
|
270
|
+
Dir.chdir(@directory) do # i.e. phi2_by_ky_vs_time or phi2_by_kx_vs_time
|
271
|
+
kxy = options[:direction]
|
272
|
+
# ep :growth_rate_at_ + kxy
|
273
|
+
return GSL::Vector.alloc(send(:transient_amplification_at_ + kxy).values)
|
274
|
+
|
275
|
+
end
|
276
|
+
end
|
277
|
+
private :transient_amplification_over_kxy_gsl_vector
|
278
|
+
|
279
|
+
# The growth rate of the fluctuations, calculated from the potential, indexed by time and normalised to vth_1/a.
|
280
|
+
# :kx or :kx_index must be specified in options
|
281
|
+
#
|
282
|
+
def growth_rate_by_kx_over_time_gsl_vector(options)
|
283
|
+
options[:direction] = :kx
|
284
|
+
growth_rate_by_kxy_over_time_gsl_vector(options)
|
285
|
+
end
|
286
|
+
|
287
|
+
# The growth rate of the fluctuations, calculated from the potential, indexed by time and normalised to vth_1/a.
|
288
|
+
# :ky or :ky_index must be specified in options
|
289
|
+
|
290
|
+
def growth_rate_by_ky_over_time_gsl_vector(options)
|
291
|
+
options[:direction] = :ky
|
292
|
+
growth_rate_by_kxy_over_time_gsl_vector(options)
|
293
|
+
end
|
294
|
+
def growth_rate_by_kxy_over_time_gsl_vector(options)
|
295
|
+
# i.e. time_dependent_gr_by_ky_vs_time or phi2_by_kx_vs_time
|
296
|
+
|
297
|
+
kxy = options[:direction]
|
298
|
+
|
299
|
+
phi = gsl_vector("phi2_by_#{kxy}_over_time", options).log / 2.0
|
300
|
+
|
301
|
+
size = phi.size
|
302
|
+
dphi = phi.subvector(1, size - 1) - phi.subvector(0, size-1)
|
303
|
+
# NB dt already has norm fixed, dphi is dimensionless
|
304
|
+
return fix_norm(dphi/gsl_vector('dt'), 0, options)
|
305
|
+
end
|
306
306
|
|
307
307
|
# <MJL edits on 2013-09-19>
|
308
308
|
# The real frequency of the fluctuations, read from the .out file, indexed by time and normalised to vth_1/a.
|
@@ -357,115 +357,115 @@ module GSLVectors
|
|
357
357
|
# </MJL>
|
358
358
|
|
359
359
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
#
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
360
|
+
# The size of each time step, indexed by time, normalised to a/v_th1.
|
361
|
+
|
362
|
+
def dt_gsl_vector(options)
|
363
|
+
t = gsl_vector('t', options)
|
364
|
+
size = t.size
|
365
|
+
# NB t already has norm fixed
|
366
|
+
return t.subvector(1, size - 1) - t.subvector(0, size-1)
|
367
|
+
end
|
368
|
+
|
369
|
+
# The growth rate, calculated from the potential, indexed by kx. Only makes sense in linear calculations.
|
370
|
+
def growth_rate_over_kx_gsl_vector(options)
|
371
|
+
options[:direction] = :kx
|
372
|
+
growth_rate_over_kxy_gsl_vector(options)
|
373
|
+
end
|
374
|
+
# The growth rate, calculated from the potential, indexed by ky. Only makes sense in linear calculations.
|
375
|
+
def growth_rate_over_ky_gsl_vector(options)
|
376
|
+
options[:direction] = :ky
|
377
|
+
growth_rate_over_kxy_gsl_vector(options)
|
378
|
+
end
|
379
|
+
|
380
|
+
def growth_rate_over_kxy_gsl_vector(options)
|
381
|
+
Dir.chdir(@directory) do # i.e. phi2_by_ky_vs_time or phi2_by_kx_vs_time
|
382
|
+
kxy = options[:direction]
|
383
|
+
# ep :growth_rate_at_ + kxy
|
384
|
+
return GSL::Vector.alloc(send(:growth_rate_at_ + kxy).values)
|
385
|
+
|
386
|
+
end
|
387
|
+
end
|
388
|
+
private :growth_rate_over_kxy_gsl_vector
|
389
|
+
|
390
|
+
# The growth rate, calculated from the potential, indexed by kx. Only makes sense in linear calculations.
|
391
|
+
def growth_rate_over_kx_slice_gsl_vector(options)
|
392
|
+
Dir.chdir(@directory) do
|
393
|
+
slice_of_growth_rates = send(:growth_rate_at_ky_at_kx)[options[:ky]].values
|
394
|
+
raise "Something went wrong: slice of growth rates seems empty" if slice_of_growth_rates.nil?
|
395
|
+
return GSL::Vector.alloc(slice_of_growth_rates)
|
396
|
+
#return GSL::Vector.alloc(send(:growth_rate_at_ky_at_kx[ky]).values)
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
# The growth rate, calculated from the potential, indexed by ky. Only makes sense in linear calculations.
|
401
|
+
def growth_rate_over_ky_slice_gsl_vector(options)
|
402
|
+
Dir.chdir(@directory) do
|
403
|
+
slice_of_growth_rates = send(:growth_rate_at_ky_at_kx).values.map{|h| h[options[:kx]]}
|
404
|
+
raise "Something went wrong: slice of growth rates seems empty" if slice_of_growth_rates.nil?
|
405
|
+
return GSL::Vector.alloc(slice_of_growth_rates)
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
# Frequency, indexed over ky, taken direct from the gs2 output file
|
410
|
+
def frequency_over_ky_gsl_vector(options)
|
411
|
+
options.convert_to_index(self, :kx)
|
412
|
+
return GSL::Vector.alloc(gsl_vector('ky').to_a.map{|ky| frequency_at_ky_at_kx[ky].values[options[:kx_index]-1]})
|
413
|
+
end
|
414
|
+
|
415
|
+
def es_heat_by_kx_over_time_gsl_vector(options)
|
416
|
+
options[:direction] = :kx
|
417
|
+
es_heat_by_kxy_over_time_gsl_vector(options)
|
418
|
+
end
|
419
|
+
def es_heat_by_ky_over_time_gsl_vector(options)
|
420
|
+
options[:direction] = :ky
|
421
|
+
es_heat_by_kxy_over_time_gsl_vector(options)
|
422
|
+
end
|
423
|
+
|
424
|
+
def es_heat_by_kxy_over_time_gsl_vector(options)
|
425
|
+
Dir.chdir(@directory) do
|
426
|
+
kxy = options[:direction]
|
427
|
+
#kxy_index = kxy + :_index
|
428
|
+
options.convert_to_index(self, kxy)
|
429
|
+
raise "Please provide species_index " unless options[:species_index]
|
430
|
+
if kxy==:ky
|
431
|
+
lkx = list(:kx)
|
432
|
+
es_heat_av = (lkx.keys.map do |kx_index|
|
433
|
+
es_heat = netcdf_file.var('es_heat_by_k').get({'start' => [kx_index-1,options[:ky_index]-1,options[:species_index]-1, 0], 'end' => [kx_index-1,options[:ky_index]-1,options[:species_index]-1, -1]})
|
434
|
+
#ep phi.shape
|
435
|
+
es_heat.reshape(*es_heat.shape.values_at(3))
|
436
|
+
end).sum / lkx.size
|
437
|
+
return es_heat_av.to_gslv
|
438
|
+
else
|
439
|
+
lky = list(:ky)
|
440
|
+
es_heat_av = (lky.keys.map do |ky_index|
|
441
|
+
es_heat = netcdf_file.var('es_heat_by_k').get({'start' => [options[:kx_index]-1,ky_index-1,options[:species_index]-1, 0], 'end' => [options[:kx_index]-1,ky_index-1,options[:species_index]-1, -1]})
|
442
|
+
#ep phi.shape
|
443
|
+
es_heat.reshape(*es_heat.shape.values_at(3))
|
444
|
+
end).sum / lky.size
|
445
|
+
return es_heat_av.to_gslv
|
446
|
+
end
|
447
|
+
|
448
|
+
end
|
449
|
+
end
|
450
|
+
private :es_heat_by_kxy_over_time_gsl_vector
|
451
|
+
|
452
|
+
def es_heat_over_kx_gsl_vector(options)
|
453
|
+
options[:direction] = :kx
|
454
|
+
es_heat_over_kxy_gsl_vector(options)
|
455
|
+
end
|
456
|
+
def es_heat_over_ky_gsl_vector(options)
|
457
|
+
options[:direction] = :ky
|
458
|
+
es_heat_over_kxy_gsl_vector(options)
|
459
|
+
end
|
460
460
|
|
461
461
|
#This function will output the heat flux as a function of kx or ky.
|
462
462
|
#Default behaviour will be to average the heat flux over the time domain.
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
463
|
+
def es_heat_over_kxy_gsl_vector(options)
|
464
|
+
Dir.chdir(@directory) do
|
465
|
+
kxy = options[:direction]
|
466
|
+
raise "Please provide species_index " unless options[:species_index]
|
467
|
+
if kxy==:ky
|
468
|
+
es_heat = (netcdf_file.var('es_heat_by_k').get({'start' => [0,0,options[:species_index]-1, 0], 'end' => [-1,-1,options[:species_index]-1, -1]})) #index = [kx,ky,spec,t]
|
469
469
|
#Need to average over time and sum over kx
|
470
470
|
shape = es_heat.shape
|
471
471
|
es_heat_av = []; temp = [];
|
@@ -475,9 +475,9 @@ module GSLVectors
|
|
475
475
|
end
|
476
476
|
es_heat_av[iy] = temp.sum
|
477
477
|
end
|
478
|
-
|
479
|
-
|
480
|
-
|
478
|
+
return es_heat_av.to_gslv
|
479
|
+
else
|
480
|
+
es_heat = (netcdf_file.var('es_heat_by_k').get({'start' => [0,0,options[:species_index]-1, 0], 'end' => [-1,-1,options[:species_index]-1, -1]})) #index = [kx,ky,spec,t]
|
481
481
|
shape = es_heat.shape
|
482
482
|
es_heat_av = []; temp = [];
|
483
483
|
for ix in 0...shape[0]
|
@@ -486,543 +486,543 @@ module GSLVectors
|
|
486
486
|
end
|
487
487
|
es_heat_av[ix] = temp.sum
|
488
488
|
end
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
#
|
521
|
-
#
|
522
|
-
#
|
523
|
-
#
|
489
|
+
return es_heat_av.to_gslv.from_box_order
|
490
|
+
end
|
491
|
+
end
|
492
|
+
end
|
493
|
+
def phi2_by_kx_over_time_gsl_vector(options)
|
494
|
+
options[:direction] = :kx
|
495
|
+
phi2_by_kxy_over_time_gsl_vector(options)
|
496
|
+
end
|
497
|
+
def phi2_by_ky_over_time_gsl_vector(options)
|
498
|
+
options[:direction] = :ky
|
499
|
+
phi2_by_kxy_over_time_gsl_vector(options)
|
500
|
+
end
|
501
|
+
def phi2_by_kxy_over_time_gsl_vector(options)
|
502
|
+
Dir.chdir(@directory) do
|
503
|
+
# i.e. phi2_by_ky_vs_time or phi2_by_kx_vs_time
|
504
|
+
|
505
|
+
kxy = options[:direction]
|
506
|
+
if list(kxy).size == 1
|
507
|
+
return phi2tot_over_time_gsl_vector(options)
|
508
|
+
end
|
509
|
+
kxy_index = kxy + :_index
|
510
|
+
|
511
|
+
|
512
|
+
#Necessary options: :ky or :kx
|
513
|
+
#Optional options: :t_index_window
|
514
|
+
# eputs "got here"
|
515
|
+
#options[:begin_element], options[:end_element] = (options[:t_index_window] ? options[:t_index_window].map{|ind| ind -1} : [0, -1])
|
516
|
+
phi_t_array=nil
|
517
|
+
if @grid_option == "single"
|
518
|
+
phi_t_array = netcdf_file.var('phi2').get('start' => [options[:begin_element]], 'end' => [options[:end_element]]).to_a.flatten
|
519
|
+
else
|
520
|
+
# value = options[:ky]
|
521
|
+
# eputs value
|
522
|
+
# get_list_of(:ky)
|
523
|
+
# index = @ky_list.find{|index,val| (val-value).abs < Float::EPSILON}[0]
|
524
524
|
# ep options
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
#
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
#
|
548
|
-
#
|
549
|
-
#
|
550
|
-
#
|
551
|
-
|
552
|
-
#
|
553
|
-
|
554
|
-
#
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
#
|
572
|
-
#
|
573
|
-
#
|
574
|
-
#
|
575
|
-
|
576
|
-
#
|
577
|
-
|
578
|
-
#
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
#
|
596
|
-
#
|
597
|
-
#
|
598
|
-
#
|
599
|
-
|
600
|
-
#
|
601
|
-
|
602
|
-
#
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
#
|
628
|
-
#
|
629
|
-
#
|
630
|
-
#
|
631
|
-
#
|
632
|
-
# #
|
633
|
-
# #
|
634
|
-
|
635
|
-
|
636
|
-
|
525
|
+
options.convert_to_index(self, kxy)
|
526
|
+
#ep options
|
527
|
+
phi_t_array = netcdf_file.var("phi2_by_#{kxy}").get('start' => [options[kxy_index] - 1, options[:begin_element]], 'end' => [options[kxy_index] - 1, options[:end_element]]).to_a.flatten
|
528
|
+
# eputs 'phi_t_array.size', phi_t_array.size
|
529
|
+
end
|
530
|
+
return GSL::Vector.alloc(phi_t_array)
|
531
|
+
|
532
|
+
end
|
533
|
+
end
|
534
|
+
private :phi2_by_kxy_over_time_gsl_vector
|
535
|
+
|
536
|
+
|
537
|
+
def phi2_by_mode_over_time_gsl_vector(options)
|
538
|
+
Dir.chdir(@directory) do #Necessary options: :ky and :kx
|
539
|
+
#Optional options: :t_index_window
|
540
|
+
# eputs "got here"
|
541
|
+
#options[:begin_element], options[:end_element] = (options[:t_index_window] ? options[:t_index_window].map{|ind| ind -1} : [0, -1])
|
542
|
+
options.setup_time_window
|
543
|
+
phi_t_array=nil
|
544
|
+
if @grid_option == "single"
|
545
|
+
phi_t_array = netcdf_file.var('phi2').get('start' => [options[:begin_element]], 'end' => [options[:end_element]]).to_a.flatten
|
546
|
+
else
|
547
|
+
# value = options[:ky]
|
548
|
+
# eputs value
|
549
|
+
# get_list_of(:ky)
|
550
|
+
# index = @ky_list.find{|index,val| (val-value).abs < Float::EPSILON}[0]
|
551
|
+
options.convert_to_index(self, :kx, :ky)
|
552
|
+
# p options
|
553
|
+
phi_t_array = netcdf_file.var("phi2_by_mode").get('start' => [options[:kx_index] - 1, options[:ky_index] - 1, options[:begin_element]], 'end' => [options[:kx_index] - 1, options[:ky_index] - 1, options[:end_element]]).to_a.flatten
|
554
|
+
# eputs 'phi_t_array.size', phi_t_array.size
|
555
|
+
end
|
556
|
+
return GSL::Vector.alloc(phi_t_array)
|
557
|
+
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
561
|
+
def tpar2_by_mode_over_time_gsl_vector(options)
|
562
|
+
Dir.chdir(@directory) do #Necessary options: :ky and :kx
|
563
|
+
#Optional options: :t_index_window
|
564
|
+
# eputs "got here"
|
565
|
+
#options[:begin_element], options[:end_element] = (options[:t_index_window] ? options[:t_index_window].map{|ind| ind -1} : [0, -1])
|
566
|
+
options.setup_time_window
|
567
|
+
tpar_t_array=nil
|
568
|
+
if @grid_option == "single"
|
569
|
+
tpar_t_array = netcdf_file.var('tpar2').get('start' => [options[:begin_element]], 'end' => [options[:end_element]]).to_a.flatten
|
570
|
+
else
|
571
|
+
# value = options[:ky]
|
572
|
+
# eputs value
|
573
|
+
# get_list_of(:ky)
|
574
|
+
# index = @ky_list.find{|index,val| (val-value).abs < Float::EPSILON}[0]
|
575
|
+
options.convert_to_index(self, :kx, :ky, :species)
|
576
|
+
# p options
|
577
|
+
tpar_t_array = netcdf_file.var("tpar2_by_mode").get('start' => [options[:kx_index] - 1, options[:ky_index] - 1, options[:species_index] - 1, options[:begin_element]], 'end' => [options[:kx_index] - 1, options[:ky_index] - 1, options[:species_index] - 1, options[:end_element]]).to_a.flatten
|
578
|
+
# eputs 'tpar_t_array.size', tpar_t_array.size
|
579
|
+
end
|
580
|
+
return GSL::Vector.alloc(tpar_t_array)
|
581
|
+
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
def tperp2_by_mode_over_time_gsl_vector(options)
|
586
|
+
Dir.chdir(@directory) do #Necessary options: :ky and :kx
|
587
|
+
#Optional options: :t_index_window
|
588
|
+
# eputs "got here"
|
589
|
+
#options[:begin_element], options[:end_element] = (options[:t_index_window] ? options[:t_index_window].map{|ind| ind -1} : [0, -1])
|
590
|
+
options.setup_time_window
|
591
|
+
tperp_t_array=nil
|
592
|
+
if @grid_option == "single"
|
593
|
+
tperp_t_array = netcdf_file.var('tperp2').get('start' => [options[:begin_element]], 'end' => [options[:end_element]]).to_a.flatten
|
594
|
+
else
|
595
|
+
# value = options[:ky]
|
596
|
+
# eputs value
|
597
|
+
# get_list_of(:ky)
|
598
|
+
# index = @ky_list.find{|index,val| (val-value).abs < Float::EPSILON}[0]
|
599
|
+
options.convert_to_index(self, :kx, :ky, :species)
|
600
|
+
# p options
|
601
|
+
tperp_t_array = netcdf_file.var("tperp2_by_mode").get('start' => [options[:kx_index] - 1, options[:ky_index] - 1, options[:species_index] - 1, options[:begin_element]], 'end' => [options[:kx_index] - 1, options[:ky_index] - 1, options[:species_index] - 1, options[:end_element]]).to_a.flatten
|
602
|
+
# eputs 'tperp_t_array.size', tperp_t_array.size
|
603
|
+
end
|
604
|
+
return GSL::Vector.alloc(tperp_t_array)
|
605
|
+
|
606
|
+
end
|
607
|
+
end
|
608
|
+
|
609
|
+
def phi0_by_kx_by_ky_over_time_gsl_vector(options)
|
610
|
+
Dir.chdir(@directory) do
|
611
|
+
options.convert_to_index(self, :kx, :ky)
|
612
|
+
phi0_array = netcdf_file.var('phi0').get.to_a.map{|arr| arr[options[:kx_index] - 1][options[:ky_index] - 1][options[:ri]]}
|
613
|
+
return GSL::Vector.alloc(phi0_array)
|
614
|
+
|
615
|
+
end
|
616
|
+
end
|
617
|
+
|
618
|
+
def linked_kx_elements_gsl_vector(options)
|
619
|
+
Dir.chdir(@directory) do
|
620
|
+
return GSL::Vector.alloc([0]) if @grid_option == "single" or agk?
|
621
|
+
if agk? or (@s_hat_input or @shat).abs < 1.0e-5
|
622
|
+
#p 'op1', options
|
623
|
+
options.convert_to_index(self, :ky, :kx)
|
624
|
+
#p 'op2', options
|
625
|
+
#eputs "No Magnetic Shear"
|
626
|
+
|
627
|
+
# begin
|
628
|
+
# options.convert_to_index(:kx)
|
629
|
+
# rescue
|
630
|
+
# raise "Must specify kx or kx_index if no magnetics shear"
|
631
|
+
# end
|
632
|
+
# # theta0 = (options[:theta0] || 0)
|
633
|
+
# # theta0 += jump(options) if @g_exb
|
634
|
+
|
635
|
+
#theta0 = (options[:kx_index])
|
636
|
+
#if @g_exb and @g_exb.abs > 0.0
|
637
637
|
#theta0 += jump(options)
|
638
638
|
#theta0 = theta0%((list(:kx).size-1)/2) if list(:kx).size > 1
|
639
639
|
#end
|
640
640
|
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
#
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
#
|
654
|
-
#
|
655
|
-
|
656
|
-
#
|
657
|
-
#
|
658
|
-
|
659
|
-
|
660
|
-
#
|
661
|
-
#
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
641
|
+
return GSL::Vector.alloc([options[:kx_index] - 1])
|
642
|
+
end
|
643
|
+
|
644
|
+
options.convert_to_index(self, :ky, :kx)
|
645
|
+
nkx = netcdf_file.var('kx').dims[0].length
|
646
|
+
# p nkx
|
647
|
+
stride = @jtwist * (options[:ky_index] -1 )
|
648
|
+
#stride = 3
|
649
|
+
nlinks = [(nkx / stride).floor, 1].max
|
650
|
+
theta0 = options[:kx_index] % @jtwist #(options[:theta0] || 0)
|
651
|
+
#log 'stride', stride, 'nlinks', nlinks, 'theta0', theta0
|
652
|
+
#if @g_exb and @jtwist > 1 #and options[:t_index]
|
653
|
+
# kx_shift = list(:ky)[options[:ky_index]] * @g_exb
|
654
|
+
# p list(:t)[options[:t_index]], options[:t_index], kx_shift
|
655
|
+
|
656
|
+
# kx_shift *= list(:t)[(options[:t_index] or list(:t).keys.max)]
|
657
|
+
# jump = (kx_shift / list(:kx)[2]).round
|
658
|
+
#theta0 += (@jtwist - jump(options) % @jtwist) % @jtwist
|
659
|
+
|
660
|
+
# else
|
661
|
+
# jump = 0
|
662
|
+
#end
|
663
|
+
#ep 'stride', stride, 'nlinks', nlinks, 'theta0', theta0
|
664
|
+
#ep GSL::Vector.indgen(nlinks / 2, nkx + theta0 - nlinks / 2 * stride, stride).connect(GSL::Vector.indgen(nlinks / 2, theta0, stride)).reverse if nlinks > 1
|
665
|
+
#return [7,5,3,1,34].to_gslv
|
666
|
+
return GSL::Vector.alloc([theta0 % jtwist]) if nlinks ==1
|
667
|
+
return GSL::Vector.indgen(nlinks / 2, nkx + theta0 - nlinks / 2 * stride, stride).connect(GSL::Vector.indgen(nlinks / 2, theta0, stride)).reverse
|
668
|
+
|
669
|
+
end
|
670
|
+
end
|
671
|
+
|
672
|
+
def spectrum_over_kpar_gsl_vector(options)
|
673
|
+
Dir.chdir(@directory) do
|
674
674
|
# , /kpar_spectrum/
|
675
|
-
|
676
|
-
|
677
|
-
|
675
|
+
#ep 'zero?', (@s_hat_input||@shat)==0.0
|
676
|
+
unless agk? or (@s_hat_input||@shat||0.0).abs<1.0e-5
|
677
|
+
phi = gsl_vector_complex('phi_along_field_line', options)
|
678
678
|
phi = phi.subvector(0,phi.size-1)
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
679
|
+
#i = 0
|
680
|
+
#phi = phi.collect{|re,im|
|
681
|
+
#i+=1; GSL::Complex.alloc(Math.sin(0.1*i), Math.cos(0.1*i))+
|
682
|
+
#GSL::Complex.alloc(Math.sin(0.4*i), Math.cos(0.4*i))
|
683
|
+
|
684
|
+
#}
|
685
|
+
##GraphKit.quick_create([phi.square]).gnuplot
|
686
|
+
phi_k = phi.forward
|
687
|
+
phi_kr = phi_k.square
|
688
|
+
case phi_kr.size%2
|
689
|
+
when 0
|
690
|
+
spec = phi_kr.subvector((phi_kr.size+2)/2, (phi_kr.size-2)/2).connect(phi_kr.subvector(0, (phi_kr.size+2)/2))
|
691
|
+
when 1
|
692
|
+
spec = phi_kr.subvector((phi_kr.size + 1)/2, (phi_kr.size-1)/2).connect(phi_kr.subvector(0, (phi_kr.size+1)/2))
|
693
|
+
end
|
694
|
+
##spec = phi_kr
|
695
|
+
#ep 'spec.class', spec.class
|
696
|
+
return spec
|
697
|
+
else
|
698
|
+
|
699
|
+
gm = gsl_matrix('spectrum_over_ky_over_kpar', options)
|
700
|
+
vec = GSL::Vector.alloc(gm.shape[1])
|
701
|
+
vec.set_all(0.0)
|
702
|
+
for ky_element in 0...gm.shape[0]
|
703
|
+
vec+= gm.row(ky_element)
|
704
|
+
end
|
705
|
+
vec = vec/gm.shape[0]
|
706
|
+
return vec
|
707
|
+
end
|
708
|
+
end
|
709
|
+
end
|
710
|
+
def kpar_gsl_vector(options)
|
711
|
+
|
712
|
+
Dir.chdir(@directory) do
|
713
|
+
if agk? or (@s_hat_input||@shat).abs < 1.0e-5
|
714
|
+
dk = 1
|
715
|
+
phi = list(:theta).values
|
716
|
+
else
|
717
|
+
kxe = gsl_vector('linked_kx_elements', options)
|
718
|
+
dk = 1.0/kxe.size
|
719
|
+
phi = gsl_vector_complex('phi_along_field_line', options)
|
720
|
+
end
|
721
|
+
case phi.size%2
|
722
|
+
when 0
|
723
|
+
kpar = GSL::Vector.indgen(phi.size-1, -((phi.size-3)/2))*dk
|
724
|
+
when 1
|
725
|
+
kpar = GSL::Vector.indgen(phi.size-1, -((phi.size-2)/2))*dk
|
726
|
+
end
|
727
727
|
#ep 'kpar', kpar, 'phi.size', phi.size
|
728
728
|
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
#
|
749
|
-
|
750
|
-
#
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
#
|
778
|
-
#
|
779
|
-
#
|
780
|
-
|
781
|
-
#
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
#
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
#
|
801
|
-
#
|
802
|
-
#
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
#
|
808
|
-
|
809
|
-
|
810
|
-
#
|
811
|
-
#
|
812
|
-
#
|
813
|
-
#
|
814
|
-
#
|
815
|
-
#
|
816
|
-
#
|
817
|
-
#
|
818
|
-
#
|
819
|
-
|
820
|
-
|
821
|
-
#
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
#
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
#
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
729
|
+
#ep 'kpar.class', kpar.class
|
730
|
+
return kpar
|
731
|
+
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
735
|
+
def phi_along_field_line_gsl_vector(options)
|
736
|
+
Dir.chdir(@directory) do
|
737
|
+
complex_phi_vector= gsl_vector_complex('phi_along_field_line', options)
|
738
|
+
case options[:imrc]
|
739
|
+
when :im
|
740
|
+
phi_vector = complex_phi_vector.imag
|
741
|
+
when :mag
|
742
|
+
_mag = true
|
743
|
+
phi_vector = complex_phi_vector.abs2
|
744
|
+
when :corr
|
745
|
+
thetas = gsl_vector('theta_along_field_line', options)
|
746
|
+
min = thetas.abs.to_a.index(thetas.abs.min)
|
747
|
+
at_0 = complex_phi_vector[min]
|
748
|
+
# ep at_0.class
|
749
|
+
phi_vector = (complex_phi_vector * (at_0 / at_0.mag).conj).real
|
750
|
+
# gsl_complex('correcting_phase', options)).real
|
751
|
+
when :real
|
752
|
+
phi_vector = complex_phi_vector.real
|
753
|
+
else
|
754
|
+
raise CRError.new("options[:imrc] was: #{options[:irmc]}")
|
755
|
+
end
|
756
|
+
phi_vector *= -1.0 if options[:flip]
|
757
|
+
(phi_vector /= phi_vector.abs.max; phi_vector *= (options[:height] || 1.0)) if options[:norm]
|
758
|
+
phi_vector = phi_vector.reverse if options[:rev]
|
759
|
+
return phi_vector
|
760
|
+
|
761
|
+
end
|
762
|
+
end
|
763
|
+
|
764
|
+
def theta_along_field_line_gsl_vector(options)
|
765
|
+
Dir.chdir(@directory) do
|
766
|
+
case @grid_option
|
767
|
+
when "single", "range"
|
768
|
+
theta_vector = gsl_vector(:theta)
|
769
|
+
when "box"
|
770
|
+
#eputs "Start theta_along_field_line"
|
771
|
+
|
772
|
+
kx_elements = gsl_vector('linked_kx_elements', options).to_a
|
773
|
+
#if @grid_option == "range"
|
774
|
+
#kx_elements = kx_elements.to_gslv.from_box_order.to_a
|
775
|
+
#end
|
776
|
+
ep 'kx_elements', kx_elements.to_a
|
777
|
+
# ep list(:kx).keys.max
|
778
|
+
# ep kx_elements[0], list(:kx)[(kx_elements[0] + 1).to_i]
|
779
|
+
# ep kx_elements[-1], list(:kx)[(kx_elements[-1] + 1).to_i]
|
780
|
+
thetas = gsl_vector(:theta)
|
781
|
+
# ep thetas
|
782
|
+
#eputs "End theta_along_field_line"
|
783
|
+
return thetas if agk? or (@s_hat_input or @shat).abs < 1.0e-5
|
784
|
+
if gryfx?
|
785
|
+
theta_list = ((1..kx_elements.size).to_a.map do |i|
|
786
|
+
thetas * i
|
787
|
+
end)
|
788
|
+
thetas = theta_list.inject{|o,n| o.connect(n)}
|
789
|
+
thetas -= Math::PI*(kx_elements.size-1)
|
790
|
+
return thetas
|
791
|
+
|
792
|
+
end
|
793
|
+
theta_list = (kx_elements.map do |element|
|
794
|
+
|
795
|
+
kx = list(:kx)[(element + 1).to_i]
|
796
|
+
# ep element
|
797
|
+
#ep 'kx', kx, 'shat', (@s_hat_input or @shat), 'ky', list(:ky)[options[:ky_index]]
|
798
|
+
thetas - 1.0 / (@s_hat_input or @shat) / list(:ky)[options[:ky_index]] * kx
|
799
|
+
end).inject{|old, new| old.connect(new)}
|
800
|
+
# thetas = gsl_vector(:theta) - 1.0 / @shat / list(:ky)[options[:ky_index]] * list(:kx)[(kx_elements[0] + 1).to_i] #- Math::PI*(kx_elements.size - 1)
|
801
|
+
# get_list_of(:ky, :t)
|
802
|
+
# if @g_exb #and options[:t_index]
|
803
|
+
|
804
|
+
if options[:moving]
|
805
|
+
theta_list = theta_list - Math::PI * 2.0 * (jump(options) / @jtwist)
|
806
|
+
else
|
807
|
+
# ep 'jump % jtwist is!!', jump(options) % @jtwist
|
808
|
+
theta_list = theta_list - Math::PI * 2.0 / @nx.to_f * ((jump(options) % @jtwist).to_f / @jtwist.to_f)
|
809
|
+
end
|
810
|
+
# jump = 0
|
811
|
+
# end
|
812
|
+
# theta_list = thetas.dup #gsl_vector(:theta) - Math::PI*kx_elements.size
|
813
|
+
# (kx_elements.size - 1).times do
|
814
|
+
# thetas = thetas + Math::PI * 2.0
|
815
|
+
# theta_list = theta_list.connect(thetas)
|
816
|
+
# end
|
817
|
+
# pp theta_list.to_a.values_at(0, theta_list.size - 1)
|
818
|
+
# pp theta_list.to_a.max
|
819
|
+
theta_vector = theta_list
|
820
|
+
end
|
821
|
+
# theta_vector = theta_vector.reverse if options[:rev]
|
822
|
+
theta_vector *= (@shat) if options[:z]
|
823
|
+
return theta_vector
|
824
|
+
|
825
|
+
end
|
826
|
+
end
|
827
|
+
|
828
|
+
def phi_for_eab_movie_gsl_vector(options)
|
829
|
+
Dir.chdir(@directory) do #options required are x_index, y_index and tm_index (Time)
|
830
|
+
mvf_name = @run_name + '.movie.nc'
|
831
|
+
raise CRError.new("cannot find file #{mvf_name}") unless FileTest.exist? mvf_name
|
832
|
+
ncf = NumRu::NetCDF.open(mvf_name)
|
833
|
+
# p ncf.var('phi_by_xmode').get.to_a[0][0][0]
|
834
|
+
return GSL::Vector.alloc(ncf.var('phi_by_xmode').get.to_a[options[:tm_index] - 1].map{|xy_arr| xy_arr[options[:x_index] - 1][options[:y_index] - 1]})
|
835
|
+
|
836
|
+
end
|
837
|
+
end
|
838
|
+
|
839
|
+
def hflux_tot_over_time_gsl_vector(options)
|
840
|
+
Dir.chdir(@directory) do
|
841
|
+
options.setup_time_window
|
842
|
+
narr = netcdf_file.var('hflux_tot').get('start' => [options[:begin_element]], 'end' => [options[:end_element]])
|
843
|
+
#eputs 'Got narr'
|
844
|
+
#ep 'hflux_tot', hflux
|
845
|
+
#eputs "fixing norm"
|
846
|
+
return fix_heat_flux_norm(GSL::Vector.alloc(narr.to_a), options)
|
847
|
+
end
|
848
|
+
end
|
849
|
+
alias :hflux_tot_gsl_vector :hflux_tot_over_time_gsl_vector
|
850
|
+
def es_heat_flux_over_time_gsl_vector(options)
|
851
|
+
Dir.chdir(@directory) do
|
852
|
+
|
853
|
+
options.setup_time_window
|
854
|
+
return GSL::Vector.alloc(netcdf_file.var('es_heat_flux').get('start' => [options[:species_index].to_i - 1, options[:begin_element]], 'end' => [options[:species_index].to_i - 1, options[:end_element]]).to_a.flatten)
|
855
|
+
end
|
856
|
+
end
|
857
|
+
def es_heat_par_over_time_gsl_vector(options)
|
858
|
+
Dir.chdir(@directory) do
|
859
|
+
|
860
|
+
options.setup_time_window
|
861
|
+
return GSL::Vector.alloc(netcdf_file.var('es_heat_par').get('start' => [options[:species_index].to_i - 1, options[:begin_element]], 'end' => [options[:species_index].to_i - 1, options[:end_element]]).to_a.flatten)
|
862
|
+
end
|
863
|
+
end
|
864
|
+
alias :es_heat_par_gsl_vector :es_heat_par_over_time_gsl_vector
|
865
|
+
def es_heat_perp_over_time_gsl_vector(options)
|
866
|
+
Dir.chdir(@directory) do
|
867
|
+
|
868
|
+
options.setup_time_window
|
869
|
+
return GSL::Vector.alloc(netcdf_file.var('es_heat_perp').get('start' => [options[:species_index].to_i - 1, options[:begin_element]], 'end' => [options[:species_index].to_i - 1, options[:end_element]]).to_a.flatten)
|
870
|
+
end
|
871
|
+
end
|
872
|
+
alias :es_heat_perp_gsl_vector :es_heat_perp_over_time_gsl_vector
|
873
|
+
def es_heat_flux_over_time_gsl_vector(options)
|
874
|
+
Dir.chdir(@directory) do
|
875
|
+
|
876
|
+
options.setup_time_window
|
877
|
+
return GSL::Vector.alloc(netcdf_file.var('es_heat_flux').get('start' => [options[:species_index].to_i - 1, options[:begin_element]], 'end' => [options[:species_index].to_i - 1, options[:end_element]]).to_a.flatten)
|
878
|
+
end
|
879
|
+
end
|
880
|
+
def es_mom_flux_over_time_gsl_vector(options)
|
881
|
+
Dir.chdir(@directory) do
|
882
|
+
|
883
|
+
options.setup_time_window
|
884
|
+
return GSL::Vector.alloc(netcdf_file.var('es_mom_flux').get('start' => [options[:species_index].to_i - 1, options[:begin_element]], 'end' => [options[:species_index].to_i - 1, options[:end_element]]).to_a.flatten)
|
885
|
+
end
|
886
|
+
end
|
887
|
+
# Velocity space diagnostics: fraction of dist func in higher
|
888
|
+
# pitch angle harmonics
|
889
|
+
def lpc_pitch_angle_gsl_vector(options)
|
890
|
+
raise "Velocity space lpc diagnostics not found" unless FileTest.exist? "#@directory/#@run_name.lpc"
|
891
|
+
lpc = GSL::Vector.filescan("#@directory/#@run_name.lpc")
|
892
|
+
return lpc[1]
|
893
|
+
end
|
894
|
+
# Velocity space diagnostics: fraction of dist func in higher
|
895
|
+
# energy harmonics
|
896
|
+
def lpc_energy_gsl_vector(options)
|
897
|
+
raise "Velocity space lpc diagnostics not found" unless FileTest.exist? "#@directory/#@run_name.lpc"
|
898
|
+
lpc = GSL::Vector.filescan("#@directory/#@run_name.lpc")
|
899
|
+
return lpc[2]
|
900
|
+
end
|
901
|
+
# Velocity space diagnostics: integral error due to
|
902
|
+
# pitch angle resolution
|
903
|
+
def vres_pitch_angle_gsl_vector(options)
|
904
|
+
raise "Velocity space vres diagnostics not found" unless FileTest.exist? "#@directory/#@run_name.vres"
|
905
|
+
vres = GSL::Vector.filescan("#@directory/#@run_name.vres")
|
906
|
+
return vres[1]
|
907
|
+
end
|
908
|
+
# Velocity space diagnostics: integral error due to
|
909
|
+
# energy resolution
|
910
|
+
def vres_energy_gsl_vector(options)
|
911
|
+
raise "Velocity space vres diagnostics not found" unless FileTest.exist? "#@directory/#@run_name.vres"
|
912
|
+
vres = GSL::Vector.filescan("#@directory/#@run_name.vres")
|
913
|
+
return vres[2]
|
914
|
+
end
|
915
|
+
def par_mom_flux_over_time_gsl_vector(options)
|
916
|
+
Dir.chdir(@directory) do
|
917
|
+
|
918
|
+
options.setup_time_window
|
919
|
+
# This is a hack... one day some one will put it in the NetCDF file (haha).
|
920
|
+
momlines = `grep parmom #@run_name.out`
|
921
|
+
mom = []
|
922
|
+
momlines.scan(Regexp.new("#{LongRegexen::FLOAT.to_s}$")) do
|
923
|
+
mom.push $~[:float].to_f
|
924
|
+
end
|
925
|
+
options[:end_element] = (mom.size + options[:end_element]) if options[:end_element] < 0
|
926
|
+
# p options
|
927
|
+
return GSL::Vector.alloc(mom).subvector(options[:begin_element], options[:end_element] - options[:begin_element] + 1)
|
928
|
+
end
|
929
|
+
end
|
930
|
+
|
931
|
+
def perp_mom_flux_over_time_gsl_vector(options)
|
932
|
+
|
933
|
+
Dir.chdir(@directory) do
|
934
|
+
options.setup_time_window
|
935
|
+
# This is a hack... one day some one will put it in the NetCDF file (haha).
|
936
|
+
momlines = `grep perpmom #@run_name.out`
|
937
|
+
mom = []
|
938
|
+
momlines.scan(Regexp.new("#{LongRegexen::FLOAT.to_s}$")) do
|
939
|
+
mom.push $~[:float].to_f
|
940
|
+
end
|
941
|
+
options[:end_element] = (mom.size + options[:end_element]) if options[:end_element] < 0
|
942
|
+
# p options
|
943
|
+
return GSL::Vector.alloc(mom).subvector(options[:begin_element], options[:end_element] - options[:begin_element] + 1)
|
944
|
+
end
|
945
|
+
end
|
946
|
+
|
947
|
+
def scan_parameter_value_gsl_vector(options)
|
948
|
+
return GSL::Vector.alloc(netcdf_file.var('scan_parameter_value').get.to_a)
|
949
|
+
end
|
950
|
+
def spectrum_over_kx_gsl_vector(options)
|
951
|
+
options[:direction] = :kx
|
952
|
+
spectrum_over_kxy_gsl_vector(options)
|
953
|
+
end
|
954
|
+
|
955
|
+
def spectrum_over_kx_avg_gsl_vector(options)
|
956
|
+
options[:direction] = :kx
|
957
|
+
spectrum_over_kxy_avg_gsl_vector(options)
|
958
|
+
end
|
959
|
+
def spectrum_over_ky_gsl_vector(options)
|
960
|
+
options[:direction] = :ky
|
961
|
+
spectrum_over_kxy_gsl_vector(options)
|
962
|
+
end
|
963
|
+
def spectrum_over_ky_avg_gsl_vector(options)
|
964
|
+
options[:direction] = :ky
|
965
|
+
spectrum_over_kxy_avg_gsl_vector(options)
|
966
|
+
end
|
967
|
+
def spectrum_over_kxy_gsl_vector(options)
|
968
|
+
Dir.chdir(@directory) do
|
969
|
+
# i.e. spectrum_over_ky or spectrum_over_kx
|
970
|
+
kxy = options[:direction]
|
971
|
+
# eputs options[:t_index]
|
972
|
+
raise "Spectrum makes no sense for single modes" if @grid_option == "single"
|
973
|
+
|
974
|
+
options.convert_to_index(:t) if options[:t] or options[:t_element]
|
975
|
+
# eputs options[:t_index]
|
976
|
+
|
977
|
+
options[:t_index] ||= list(:t).keys.max
|
978
|
+
# eputs options[:t_index]
|
979
|
+
phi_array = netcdf_file.var("phi2_by_#{kxy}").get('start' => [0, options[:t_index] - 1], 'end' => [-1, options[:t_index] - 1]).to_a.flatten
|
980
|
+
v = GSL::Vector.alloc(phi_array)
|
981
|
+
v = v.from_box_order if kxy == :kx
|
982
|
+
v = v.mul(gsl_vector(kxy).square) unless options[:phi2_only]
|
983
|
+
return v
|
984
|
+
end
|
985
|
+
end
|
986
986
|
|
987
987
|
#spectrum averaged in time
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
988
|
+
def spectrum_over_kxy_avg_gsl_vector(options)
|
989
|
+
Dir.chdir(@directory) do
|
990
|
+
# i.e. spectrum_over_ky or spectrum_over_kx
|
991
|
+
kxy = options[:direction]
|
992
|
+
raise "Spectrum makes no sense for single modes" if @grid_option == "single"
|
993
993
|
|
994
|
-
|
994
|
+
phi_array = netcdf_file.var("phi2_by_#{kxy}").get('start' => [0, 0], 'end' => [-1, -1]) #index = [kx or ky, t]
|
995
995
|
|
996
996
|
shape = phi_array.shape
|
997
997
|
phi_av = [];
|
998
|
-
#average over time for each kx or ky individually
|
998
|
+
#average over time for each kx or ky individually
|
999
999
|
for i in 0...shape[0]
|
1000
1000
|
phi_av[i] = phi_array[i,0..-1].sum / shape[1]
|
1001
1001
|
end
|
1002
1002
|
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1003
|
+
v = GSL::Vector.alloc(phi_av)
|
1004
|
+
v = v.from_box_order if kxy == :kx
|
1005
|
+
v = v.mul(gsl_vector(kxy).square) unless options[:phi2_only]
|
1006
|
+
return v
|
1007
|
+
end
|
1008
|
+
end
|
1009
|
+
|
1010
|
+
def x_gsl_vector(options)
|
1011
|
+
raise "options nakx and interpolate_x are incompatible" if options[:nakx] and options[:interpolate_x]
|
1012
|
+
kx = gsl_vector(:kx, options)
|
1013
|
+
lx = 2*Math::PI/kx.to_box_order[1]
|
1014
|
+
#ep 'lx', lx
|
1015
|
+
nx = options[:nakx]||kx.size
|
1016
|
+
GSL::Vector.indgen(nx, 0, lx/nx)
|
1017
|
+
end
|
1018
|
+
def y_gsl_vector(options)
|
1019
|
+
raise "options naky and interpolate_y are incompatible" if options[:naky] and options[:interpolate_y]
|
1020
|
+
ky = gsl_vector(:ky, options)
|
1021
|
+
ly = 2*Math::PI/ky[1]
|
1022
|
+
ny = options[:naky]||ky.size
|
1023
|
+
ysize = ny*2-2+ny%2
|
1024
|
+
GSL::Vector.indgen(ysize, 0, ly/ysize)
|
1025
|
+
end
|
1026
1026
|
|
1027
1027
|
#This function reads in the 'grho' variable from the netcdf file.
|
1028
1028
|
def grho_gsl_vector(options)
|
@@ -1030,17 +1030,17 @@ module GSLVectors
|
|
1030
1030
|
return grho
|
1031
1031
|
end
|
1032
1032
|
|
1033
|
-
#This function returns the zonal flow velocity as a function of x (the radial coordinate).
|
1034
|
-
#This is v_ZF = kxfac*IFT(i k_x phi_imag), where kxfac = (qinp/rhoc)*grho(rhoc).
|
1035
|
-
|
1036
|
-
|
1033
|
+
#This function returns the zonal flow velocity as a function of x (the radial coordinate).
|
1034
|
+
#This is v_ZF = kxfac*IFT(i k_x phi_imag), where kxfac = (qinp/rhoc)*grho(rhoc).
|
1035
|
+
def zonal_flow_velocity_over_x_gsl_vector(options)
|
1036
|
+
Dir.chdir(@directory) do
|
1037
1037
|
raise CRFatal.new("Need to specify a theta_index.") unless options[:theta_index]
|
1038
1038
|
raise CRFatal.new("Need either qinp or pk and epsl specified in order to calculate kxfac.
|
1039
1039
|
If using numerical equil use the option :kxfac to override calculation.") unless @qinp or (@pk and @epsl or options[:kxfac])
|
1040
|
-
|
1040
|
+
phi = gsl_vector_complex('phi_zonal', options)
|
1041
1041
|
|
1042
1042
|
kx = gsl_vector(:kx).to_box_order
|
1043
|
-
|
1043
|
+
_x = gsl_vector(:x)
|
1044
1044
|
grho = gsl_vector('grho')[options[:theta_index]]
|
1045
1045
|
if @qinp
|
1046
1046
|
kxfac = (@qinp/@rhoc)*grho
|
@@ -1049,415 +1049,416 @@ module GSLVectors
|
|
1049
1049
|
elsif options[:kxfac]
|
1050
1050
|
kxfac = options[:kxfac]
|
1051
1051
|
else
|
1052
|
-
raise 'Error: Need qinp or pk and epsl to calculate kxfac'
|
1052
|
+
raise 'Error: Need qinp or pk and epsl to calculate kxfac'
|
1053
1053
|
end
|
1054
1054
|
|
1055
1055
|
vec_zf_vel = GSL::Vector.alloc(kx.size)
|
1056
1056
|
#Take imaginary part since i k_x will lead to imaginary part being real
|
1057
1057
|
vec_zf_vel = kxfac*(phi*kx).backward.imag
|
1058
1058
|
return vec_zf_vel
|
1059
|
-
|
1060
|
-
|
1059
|
+
end
|
1060
|
+
end
|
1061
1061
|
|
1062
|
-
#This function returns the mean flow velocity as a function of x (the radial coordinate).
|
1063
|
-
#This is v_g_exb = (x - x(centre))*g_exb. The x-x(centre) ensures that the flow is zero
|
1062
|
+
#This function returns the mean flow velocity as a function of x (the radial coordinate).
|
1063
|
+
#This is v_g_exb = (x - x(centre))*g_exb. The x-x(centre) ensures that the flow is zero
|
1064
1064
|
#at the middle of the box.
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1065
|
+
def mean_flow_velocity_over_x_gsl_vector(options)
|
1066
|
+
Dir.chdir(@directory) do
|
1067
|
+
raise CRFatal.new("Need to have g_exb > 0 to have a mean flow.") unless @g_exb
|
1068
1068
|
x = gsl_vector(:x)
|
1069
1069
|
|
1070
1070
|
vec_exb_vel = GSL::Vector.alloc(x.size)
|
1071
1071
|
#Take imaginary part since i k_x will lead to imaginary part being real
|
1072
1072
|
vec_exb_vel = (x - x[x.size/2])*@g_exb
|
1073
1073
|
return vec_exb_vel
|
1074
|
-
|
1075
|
-
|
1074
|
+
end
|
1075
|
+
end
|
1076
1076
|
|
1077
|
-
|
1078
|
-
|
1077
|
+
def zonal_spectrum_gsl_vector(options)
|
1078
|
+
Dir.chdir(@directory) do
|
1079
1079
|
gmzf = gsl_matrix('spectrum_over_ky_over_kx',options)
|
1080
1080
|
veczf = GSL::Vector.alloc(gmzf.shape[1])
|
1081
1081
|
gmzf.shape[1].times{|i| veczf[i] = gmzf[0,i]}
|
1082
1082
|
return veczf
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
end
|
1083
|
+
end
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
end # module GSLVectors
|
1087
1087
|
include GSLVectors
|
1088
1088
|
|
1089
1089
|
def gsl_vector_complex(name, options={})
|
1090
|
-
|
1090
|
+
options = eval(options) if options.class == String
|
1091
1091
|
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1092
|
+
if method = self.class.instance_methods.find{|meth| (name + '_gsl_vector_complex').to_sym == meth}
|
1093
|
+
options[:graphkit_name] = name
|
1094
|
+
return send(method, options)
|
1095
|
+
end
|
1096
1096
|
end
|
1097
1097
|
|
1098
1098
|
module GSLVectorComplexes
|
1099
1099
|
|
1100
|
-
|
1101
|
-
|
1102
|
-
#
|
1103
|
-
#
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
#This function returns a complex GSL vector of the zonal (ky=0) component of phi/phi_t at a given theta index
|
1100
|
+
def phi_along_field_line_gsl_vector_complex(options)
|
1101
|
+
Dir.chdir(@directory) do
|
1102
|
+
# eputs options[:ky]
|
1103
|
+
# eputs Dir.pwd
|
1104
|
+
#eputs "Start phi_along_field_line"
|
1105
|
+
options.convert_to_index(self, :ky)
|
1106
|
+
if options[:t_index] or options[:t]
|
1107
|
+
#extra option required is t_index
|
1108
|
+
raise CRFatal.new("write_phi_over_time is not enabled so this function won't work") unless @write_phi_over_time
|
1109
|
+
|
1110
|
+
options.convert_to_index(self, :t)
|
1111
|
+
case @grid_option
|
1112
|
+
when "single"
|
1113
|
+
temp = GSL::Vector.alloc(netcdf_file.var('phi_t').get({'start' => [0,0,0,0, options[:t_index] - 1], 'end' => [-1,-1,0,0, options[:t_index] - 1]}).to_a[0][0][0].flatten)
|
1114
|
+
when "range"
|
1115
|
+
a = netcdf_file.var('phi_t').get({'start' => [0, 0, options[:kx_index]-1, options[:ky_index] - 1, options[:t_index] - 1], 'end' => [-1, -1, options[:kx_index]-1, options[:ky_index] - 1, options[:t_index]-1]})
|
1116
|
+
#temp = GSL::Vector.alloc(a.to_a[0].values_at(*kx_elements).flatten)
|
1117
|
+
temp = GSL::Vector.alloc(a.to_a[0][0].flatten)
|
1118
|
+
when "box"
|
1119
|
+
options.convert_to_index(self, :ky, :kx)
|
1120
|
+
kx_elements = gsl_vector('linked_kx_elements', options).to_a
|
1121
|
+
# pp kx_elements
|
1122
|
+
a = netcdf_file.var('phi_t').get({
|
1123
|
+
'start' => [0,0,0,options[:ky_index] - 1, options[:t_index] - 1],
|
1124
|
+
'end' => [-1,-1,-1, options[:ky_index] - 1, options[:t_index] - 1]
|
1125
|
+
}).to_a[0][0].values_at(*kx_elements).flatten
|
1126
|
+
# pp a.index(nil)
|
1127
|
+
# temp = GSL::Vector.alloc(netcdf_file.var('phi').get.to_a[options[:ky_index] - 1 ].values_at(*kx_elements).flatten)
|
1128
|
+
#ep a
|
1129
|
+
temp = GSL::Vector.alloc(a)
|
1130
|
+
end
|
1131
|
+
|
1132
|
+
#eputs "End phi_along_field_line"
|
1133
|
+
return GSL::Vector::Complex.alloc(temp.subvector_with_stride(0, 2), temp.subvector_with_stride(1, 2))
|
1134
|
+
else
|
1135
|
+
case @grid_option
|
1136
|
+
when "single"
|
1137
|
+
temp = GSL::Vector.alloc(netcdf_file.var('phi').get({'start' => [0,0, 0, 0], 'end' => [-1,-1,0,0]}).to_a.flatten)
|
1138
|
+
when "range"
|
1139
|
+
a = netcdf_file.var('phi').get({'start' => [0, 0, 0, options[:ky_index] - 1], 'end' => [-1, -1, -1, options[:ky_index] - 1]})
|
1140
|
+
#temp = GSL::Vector.alloc(a.to_a[0].values_at(*kx_elements).flatten)
|
1141
|
+
temp = GSL::Vector.alloc(a.to_a[0][0].flatten)
|
1142
|
+
when "box"
|
1143
|
+
ep 'kx_elements', kx_elements = gsl_vector('linked_kx_elements', options).to_a
|
1144
|
+
a = netcdf_file.var('phi').get({'start' => [0, 0, 0, options[:ky_index] - 1], 'end' => [-1, -1, -1, options[:ky_index] - 1]})
|
1145
|
+
temp = GSL::Vector.alloc(a.to_a[0].values_at(*kx_elements).flatten)
|
1146
|
+
else
|
1147
|
+
raise "invalid grid option"
|
1148
|
+
end
|
1149
|
+
|
1150
|
+
vector = GSL::Vector::Complex.alloc(temp.subvector_with_stride(0, 2), temp.subvector_with_stride(1, 2))
|
1151
|
+
#ep 'vector', vector.real
|
1152
|
+
return vector
|
1153
|
+
end
|
1154
|
+
end
|
1155
|
+
# eputs data; gets
|
1156
|
+
end
|
1157
|
+
|
1158
|
+
#This function returns a complex GSL vector of the zonal (ky=0) component of phi/phi_t at a given theta index
|
1159
1159
|
#and time index if write_phi_over_time was enabled during the simulation
|
1160
|
-
|
1160
|
+
def phi_zonal_gsl_vector_complex(options)
|
1161
1161
|
Dir.chdir(@directory) do
|
1162
1162
|
if options[:t_index] or options[:t]
|
1163
1163
|
#extra option required is t_index
|
1164
1164
|
raise CRFatal.new("write_phi_over_time is not enabled so this function won't work") unless @write_phi_over_time
|
1165
|
-
|
1165
|
+
|
1166
1166
|
options.convert_to_index(self, :t)
|
1167
1167
|
a = netcdf_file.var('phi_t').get({
|
1168
|
-
'start' => [0,options[:theta_index],0,0, options[:t_index] - 1],
|
1168
|
+
'start' => [0,options[:theta_index],0,0, options[:t_index] - 1],
|
1169
1169
|
'end' => [-1,options[:theta_index],-1,0, options[:t_index] - 1]
|
1170
1170
|
})
|
1171
1171
|
vector = GSL::Vector::Complex.alloc(GSL::Vector.alloc(a[0,0,0..-1,0,0]), GSL::Vector.alloc(a[1,0,0..-1,0,0]))
|
1172
1172
|
return vector
|
1173
1173
|
else
|
1174
1174
|
a = netcdf_file.var('phi').get({
|
1175
|
-
'start' => [0, options[:theta_index], 0, 0],
|
1175
|
+
'start' => [0, options[:theta_index], 0, 0],
|
1176
1176
|
'end' => [-1, options[:theta_index], -1, 0]
|
1177
1177
|
})
|
1178
1178
|
vector = GSL::Vector::Complex.alloc(GSL::Vector.alloc(a[0,0,0..-1,0]), GSL::Vector.alloc(a[1,0,0..-1,0]))
|
1179
1179
|
return vector
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1180
|
+
end
|
1181
|
+
end
|
1182
|
+
end
|
1183
1183
|
|
1184
|
-
end
|
1184
|
+
end
|
1185
1185
|
include GSLVectorComplexes
|
1186
1186
|
|
1187
1187
|
def gsl_matrix(name, options={})
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1188
|
+
options = eval(options) if options.class == String
|
1189
|
+
if options[:saturated_time_average] or options[:sta]
|
1190
|
+
raise "Not Saturated" unless @saturation_time_index
|
1191
|
+
tmax = list(:t).keys.max
|
1192
|
+
return ((@saturation_time_index..tmax).to_a.map do |t_index|
|
1193
|
+
gsl_matrix(name, options.dup.absorb({t_index: t_index, saturated_time_average: nil, sta: nil}))
|
1194
|
+
end).sum / (list(:t).values.max - list(:t)[@saturation_time_index])
|
1195
|
+
end
|
1196
|
+
if method = self.class.instance_methods.find{|meth| (name + '_gsl_matrix').to_sym == meth}
|
1197
|
+
options[:graphkit_name] = name
|
1198
|
+
return send(method, options)
|
1199
|
+
end
|
1200
1200
|
end
|
1201
1201
|
|
1202
1202
|
module GSLMatrices
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
#
|
1228
|
-
|
1229
|
-
#
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
#
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
#
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1203
|
+
def growth_rate_over_ky_over_kx_gsl_matrix(options)
|
1204
|
+
if @growth_rate_at_ky_at_kx.nil?
|
1205
|
+
raise("The CodeRunner variable growth_rate_at_ky_at_kx does not seem to have been calculated for this run. This may result when the environment variable GS2_CALCULATE_ALL is not set when the run was analyzed. Try setting GS2_CALCULATE_ALL and then re-analyze the run using, e.g. from the command line,\n $ coderunner rc 'cgrf\' -j #{@id}")
|
1206
|
+
end
|
1207
|
+
array = @growth_rate_at_ky_at_kx.values.map{|h| h.values}
|
1208
|
+
return GSL::Matrix.alloc(array.flatten, array.size, array[0].size)
|
1209
|
+
end
|
1210
|
+
def transient_amplification_over_ky_over_kx_gsl_matrix(options)
|
1211
|
+
array = @transient_amplification_at_ky_at_kx.values.map{|h| h.values}
|
1212
|
+
return GSL::Matrix.alloc(array.flatten, array.size, array[0].size)
|
1213
|
+
end
|
1214
|
+
def es_heat_flux_over_ky_over_kx_gsl_matrix(options)
|
1215
|
+
Dir.chdir(@directory) do
|
1216
|
+
raise "Heat flux spectrum makes no sense for single modes" if @grid_option == "single"
|
1217
|
+
options.convert_to_index(:t) if options[:t] or options[:t_element]
|
1218
|
+
options[:t_index] ||= list(:t).keys.max
|
1219
|
+
#es_heat_by_k index order (in Fortran) is kx, ky, t
|
1220
|
+
es_heat_narray = netcdf_file.var("es_heat_by_k").get('start' => [0, 0, 0, options[:t_index] - 1], 'end' => [-1, -1, 0, options[:t_index] - 1])
|
1221
|
+
es_heat_narray.reshape!(*es_heat_narray.shape.slice(0..1))
|
1222
|
+
|
1223
|
+
gm = es_heat_narray.to_gm.move_cols_from_box_order
|
1224
|
+
if options[:limit]
|
1225
|
+
for i in 0...gm.shape[0]
|
1226
|
+
for j in 0...gm.shape[1]
|
1227
|
+
# j+= extra if
|
1228
|
+
gm[i, j] = [[gm[i,j], (options[:limit][0] or gm[i,j])].max, (options[:limit][1] or gm[i,j])].min
|
1229
|
+
# mat[i, j+extra] = gm[i,-j] unless j==0
|
1230
|
+
end
|
1231
|
+
end
|
1232
|
+
end
|
1233
|
+
return gm
|
1234
|
+
end
|
1235
|
+
end
|
1236
|
+
def spectrum_over_ky_over_kx_gsl_matrix(options)
|
1237
|
+
Dir.chdir(@directory) do
|
1238
|
+
raise "Spectrum makes no sense for single modes" if @grid_option == "single"
|
1239
|
+
options.convert_to_index(:t) if options[:t] or options[:t_element]
|
1240
|
+
options[:t_index] ||= list(:t).keys.max
|
1241
|
+
#phi2_by_mode index order (in Fortran) is kx, ky, t
|
1242
|
+
phi_narray = netcdf_file.var("phi2_by_mode").get('start' => [0, 0, options[:t_index] - 1], 'end' => [-1, -1, options[:t_index] - 1])
|
1243
|
+
phi_narray.reshape!(*phi_narray.shape.slice(0..1))
|
1244
|
+
|
1245
|
+
gm = phi_narray.to_gm.move_cols_from_box_order
|
1246
|
+
if options[:times_kx4] or options[:times_kx2]
|
1247
|
+
# puts 'normalising'
|
1248
|
+
vals = list(:kx).values.sort
|
1249
|
+
for i in 0...gm.shape[0]
|
1250
|
+
for j in 0...gm.shape[1]
|
1251
|
+
# p vals[j]
|
1252
|
+
gm[i,j] = gm[i,j] * (vals[j])**4 if options[:times_kx4]
|
1253
|
+
gm[i,j] = gm[i,j] * (vals[j])**2 if options[:times_kx2]
|
1254
|
+
end
|
1255
|
+
end
|
1256
|
+
end
|
1257
|
+
if options[:no_zonal]
|
1258
|
+
|
1259
|
+
for i in 0...gm.shape[1]
|
1260
|
+
gm[0,i] = 0.0
|
1261
|
+
end
|
1262
|
+
end
|
1263
|
+
if options[:log]
|
1264
|
+
gm = gm.log
|
1265
|
+
end
|
1266
|
+
|
1267
|
+
return gm
|
1268
|
+
end
|
1269
|
+
end
|
1270
|
+
def spectrum_over_ky_over_kpar_gsl_matrix(options)
|
1271
|
+
Dir.chdir(@directory) do
|
1272
|
+
|
1273
|
+
#:re, :theta, :kx, :ky
|
1274
|
+
lkx = list(:kx)
|
1275
|
+
|
1276
|
+
if options[:t_index] or options[:t]
|
1277
|
+
#extra option required is t_index
|
1278
|
+
raise CRFatal.new("write_phi_over_time is not enabled so this function won't work") unless @write_phi_over_time
|
1279
|
+
options.convert_to_index(self, :t)
|
1280
|
+
end
|
1281
|
+
phi_av = (lkx.keys.map do |kx_index|
|
1282
|
+
if options[:t_index]
|
1283
|
+
phi = netcdf_file.var('phi_t').get({'start' => [0,0,kx_index-1,0, options[:t_index] - 1], 'end' => [-1,-2,kx_index-1,-1, options[:t_index] - 1]})
|
1284
|
+
else
|
1285
|
+
phi = netcdf_file.var('phi').get({'start' => [0, 0, kx_index - 1, 0], 'end' => [-1, -2, kx_index-1, -1]})
|
1286
|
+
end
|
1287
|
+
#ep phi.shape
|
1288
|
+
phi.reshape(*phi.shape.values_at(0,1,3))
|
1289
|
+
end).sum / lkx.size
|
1290
|
+
|
1291
|
+
phi_t = phi_av.to_a #.map{|arr| arr.transpose}.transpose.map{|a| a.transpose}
|
1292
|
+
#ep 'phi_t', phi_t.size, phi_t[0].size, phi_t[0][0].size
|
1293
|
+
gvky = gsl_vector('ky')
|
1294
|
+
gm = GSL::Matrix.alloc(gvky.size, gsl_vector('theta').size-1)
|
1295
|
+
for ky_element in 0...gm.shape[0]
|
1296
|
+
#p phi_t[ky_element].transpose[0]
|
1297
|
+
spectrum = GSL::Vector::Complex.alloc(phi_t[ky_element]).forward.square
|
1298
|
+
if options[:no_kpar0]
|
1299
|
+
spectrum[0]=0.0
|
1300
|
+
end
|
1301
1301
|
#ep spectrum.size
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1302
|
+
spectrum = spectrum.from_box_order
|
1303
|
+
#ep spectrum.shape
|
1304
|
+
spectrum = spectrum*gvky[ky_element]**2 unless options[:phi2_only]
|
1305
1305
|
#ep gm.size
|
1306
1306
|
#ep spectrum.size
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1307
|
+
gm.set_row(ky_element, spectrum)
|
1308
|
+
end
|
1309
|
+
if options[:no_zonal]
|
1310
|
+
gm.row(0).set_all(0.0)
|
1311
|
+
end
|
1312
|
+
if options[:log]
|
1313
|
+
gm = gm.log
|
1314
|
+
end
|
1315
|
+
|
1316
|
+
return gm
|
1317
|
+
end
|
1318
|
+
end
|
1319
|
+
|
1320
|
+
def phi0_over_x_over_y_gsl_matrix(options)
|
1321
|
+
Dir.chdir(@directory) do
|
1322
|
+
|
1323
|
+
#options.convert_to_index(:t) if options[:t] or options[:t_element]
|
1324
|
+
options.convert_to_index(self, :t) if options[:t] or options[:t_element]
|
1325
|
+
options[:t_index] ||= list(:t).keys.max
|
1326
|
+
phi_re_narray = netcdf_file.var("phi0").get('start' => [0, 0, 0, options[:t_index] - 1], 'end' => [0, -1, -1, options[:t_index] - 1])
|
1327
|
+
phi_re_narray.reshape!(*phi_re_narray.shape.slice(1..2))
|
1328
|
+
# The narray has index order ky, kx, but we want kx, ky for historical reasons, hence the transpose.
|
1329
|
+
gm_re = phi_re_narray.to_gm
|
1330
|
+
phi_im_narray = netcdf_file.var("phi0").get('start' => [1, 0, 0, options[:t_index] - 1], 'end' => [1, -1, -1, options[:t_index] - 1])
|
1331
|
+
phi_im_narray.reshape!(*phi_im_narray.shape.slice(1..2))
|
1332
|
+
# The narray has index order ky, kx, but we want kx, ky for historical imasons, hence the transpose.
|
1333
|
+
gm_im = phi_im_narray.to_gm
|
1334
|
+
gm = GSL::Matrix::Complex.re_im(gm_re, gm_im)
|
1335
|
+
|
1336
|
+
ntheta0_temp = gm.shape[1]
|
1337
|
+
naky_temp = gm.shape[0]
|
1338
|
+
|
1339
|
+
|
1340
|
+
|
1341
|
+
# Due to a strange GS2 convention, non zonal modes must be divided by 2:
|
1342
|
+
for i in 1...naky_temp
|
1343
|
+
for j in 0...ntheta0_temp
|
1344
|
+
gm[i,j] = gm[i,j]/2.0
|
1345
|
+
end
|
1346
|
+
end
|
1347
|
+
|
1348
|
+
if options[:no_zonal]
|
1349
|
+
for i in 0...gm.shape[1]
|
1350
|
+
gm[0,i] = GSL::Complex.alloc([0,0])
|
1351
|
+
end
|
1352
|
+
end
|
1353
|
+
if xres = (options[:xres] or options[:x_resolution])
|
1354
|
+
if xres < nx
|
1355
|
+
puts "Warning: xres should be at least nx. Using nx instead of the xres you specified."
|
1356
|
+
xres = nx
|
1357
|
+
end
|
1358
|
+
else
|
1359
|
+
xres = nx
|
1360
|
+
end
|
1361
|
+
if yres = (options[:yres] or options[:y_resolution])
|
1362
|
+
if yres < ny
|
1363
|
+
puts "Warning: yres should be at least ny. Using ny instead of the yres you specified."
|
1364
|
+
yres = ny
|
1365
|
+
end
|
1366
|
+
else
|
1367
|
+
yres = ny
|
1368
|
+
end
|
1369
|
+
|
1370
|
+
# Next, pad with 0's:
|
1371
|
+
padded = GSL::Matrix::Complex.calloc(yres, xres)
|
1372
|
+
# Zonal modes first:
|
1373
|
+
for ix in 0...((ntheta0_temp+1)/2)
|
1374
|
+
padded[0, ix] = gm[0, ix]
|
1375
|
+
end
|
1376
|
+
for ix in ((ntheta0_temp+1)/2)...ntheta0_temp
|
1377
|
+
padded[0, ix+xres-ntheta0_temp] = gm[0, ix]
|
1378
|
+
end
|
1379
|
+
# Now include the non-zonal modes in the padded matrix mat:
|
1380
|
+
for iy in 1...naky_temp
|
1381
|
+
for ix in 0...((ntheta0_temp + 1)/2)
|
1382
|
+
padded[iy, ix] = gm[iy, ix]
|
1383
|
+
end
|
1384
|
+
for ix in ((ntheta0_temp+1)/2)...ntheta0_temp
|
1385
|
+
padded[iy, ix+xres-ntheta0_temp] = gm[iy, ix]
|
1386
|
+
end
|
1387
|
+
padded[yres-iy, 0] = gm[iy,0].conj
|
1388
|
+
for ix in 1...xres
|
1389
|
+
padded[yres-iy, ix] = padded[iy, xres-ix].conj
|
1390
|
+
end
|
1391
|
+
end
|
1392
|
+
gm = padded
|
1393
|
+
|
1394
|
+
gm = gm.backward_cols_c2c(false).backward_rows_c2c(false)
|
1395
|
+
# At this point, gm should be purely real (within machine precision), but let's check to be sure:
|
1396
|
+
should_be_zero = gm.imag.abs.max
|
1397
|
+
if should_be_zero > 1.0e-10
|
1398
|
+
puts "should_be_zero = #{should_be_zero}"
|
1399
|
+
raise "Something went wrong - reconstructed phi is not purely real."
|
1400
|
+
end
|
1401
|
+
|
1402
|
+
gm = gm.real
|
1403
|
+
|
1404
|
+
if options[:limit]
|
1405
|
+
for i in 0...gm.shape[0]
|
1406
|
+
for j in 0...gm.shape[1]
|
1407
|
+
gm[i, j] = [[gm[i,j], options[:limit][0]].max, options[:limit][1]].min
|
1408
|
+
end
|
1409
|
+
end
|
1410
|
+
end
|
1411
|
+
|
1412
|
+
return gm
|
1413
|
+
end
|
1414
|
+
end
|
1414
1415
|
end
|
1415
1416
|
|
1416
1417
|
include GSLMatrices
|
1417
1418
|
|
1418
1419
|
def kx_shift(options)
|
1419
|
-
#
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1420
|
+
# ep options
|
1421
|
+
return 0 unless @g_exb and @g_exb.abs > 0.0
|
1422
|
+
#p options
|
1423
|
+
return - list(:ky)[options[:ky_index]] * list(:t)[(options[:t_index] or list(:t).keys.max)] * @g_exb
|
1423
1424
|
end
|
1424
1425
|
|
1425
1426
|
def jump(options)
|
1426
|
-
#
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1427
|
+
# ep 'kx_shift', kx_shift(options)
|
1428
|
+
jump = ((kx_shift(options) / list(:kx)[2]).round)
|
1429
|
+
case options[:t_index]
|
1430
|
+
when 1
|
1431
|
+
return jump
|
1432
|
+
else
|
1433
|
+
if @g_exb and @g_exb.abs > 0
|
1434
|
+
return jump + 1
|
1435
|
+
else
|
1436
|
+
return 0
|
1437
|
+
end
|
1438
|
+
end
|
1438
1439
|
end
|
1439
1440
|
|
1440
1441
|
# This function is used in the presence of perpendicular flow shear. It returns the (Eulerian) GS2
|
1441
|
-
# kx_index as a function of the Lagrangian kx, which is the kx_index of the mode in a shearing
|
1442
|
+
# kx_index as a function of the Lagrangian kx, which is the kx_index of the mode in a shearing
|
1442
1443
|
# coordinate system, I.e. if you give it an Lagrangian kx (which is the same as the Eulerian
|
1443
1444
|
# kx at t=0) it will tell you where it has now got to. It may have left the box, in which case
|
1444
1445
|
# this function will return an error.
|
1445
1446
|
#
|
1446
1447
|
# A given Lagrangian kx moves through the GS2 box, and thus for such a kx the response matrix varies
|
1447
|
-
# in time. This is done because the effect of flow shear can be reduced by a shearing coordinate
|
1448
|
+
# in time. This is done because the effect of flow shear can be reduced by a shearing coordinate
|
1448
1449
|
# transformation to become merely a time varying kx.
|
1449
1450
|
#
|
1450
1451
|
# At each timestep, phi(ikx_indexed(it)) is set equal to phi(ikx_indexed(it - jump(iky))
|
1451
|
-
# kx_indexed is defined in the following way.
|
1452
|
+
# kx_indexed is defined in the following way.
|
1452
1453
|
# do it=itmin(1), ntheta0
|
1453
|
-
#
|
1454
|
-
#
|
1455
|
-
#
|
1456
|
-
#
|
1457
|
-
#
|
1458
|
-
#
|
1454
|
+
# ikx_indexed (it+1-itmin(1)) = it
|
1455
|
+
# end do
|
1456
|
+
#
|
1457
|
+
# do it=1,itmin(1)-1
|
1458
|
+
# ikx_indexed (ntheta0 - itmin(1) + 1 + it)= it
|
1459
|
+
# end do
|
1459
1460
|
#
|
1460
|
-
# In other words, what this means is that akx(ikx_indexed(0)) is the minimum kx,
|
1461
|
+
# In other words, what this means is that akx(ikx_indexed(0)) is the minimum kx,
|
1461
1462
|
# and that akx(ikx_indexed(ntheta0)) gives the maximum kx, kx_indexed moves the
|
1462
1463
|
# kxs out of box order.
|
1463
1464
|
#
|
@@ -1465,103 +1466,103 @@ end
|
|
1465
1466
|
# so the Lagrangian mode has moved to a lower kx. So get the Eulerian index, one
|
1466
1467
|
# starts with the Lagrangian index, and adds jump (which is negative!). This, however,
|
1467
1468
|
# must be done with indexes that are in the physical (not box) order. So this function
|
1468
|
-
# first moves the indexes out of box order, then adds jump, then moves them back
|
1469
|
+
# first moves the indexes out of box order, then adds jump, then moves them back
|
1469
1470
|
# into box order so that the index returned will give the correct kx from the GS2
|
1470
1471
|
# array.
|
1471
1472
|
|
1472
1473
|
def eulerian_kx_index(options)
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1474
|
+
#eputs "Start eulerian_kx_index"
|
1475
|
+
lagrangian_kx_index = options[:kx_index]
|
1476
|
+
phys = physical_kx_index(lagrangian_kx_index)
|
1477
|
+
#ep 'jump', jump(options)
|
1478
|
+
index = phys + jump(options)
|
1479
|
+
raise ArgumentError.new("Lagrangian kx out of range") if index <= 0
|
1480
|
+
box= box_kx_index(index)
|
1481
|
+
#eputs "End eulerian_kx_index"
|
1482
|
+
return box
|
1482
1483
|
end
|
1483
1484
|
|
1484
1485
|
def kx_indexed
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1486
|
+
return cache[:kx_indexed] if cache[:kx_indexed]
|
1487
|
+
#kx = cache[:kx_array] ||= gsl_vector('kx').to_a
|
1488
|
+
#kxphys = kx.from_box_order
|
1489
|
+
#min_index = kx.min_index + 1
|
1490
|
+
#cache[:kx_indexed] ||= kx.size.times.inject({}) do |hash, kx_element|
|
1491
|
+
#hash[kx_element + 1] = kxphs
|
1492
|
+
kx = gsl_vector('kx')
|
1493
|
+
size = kx.size
|
1494
|
+
box = GSL::Vector::Int.indgen(size) + 1
|
1495
|
+
zero_element = kx.abs.min_index
|
1496
|
+
phys = box.subvector(zero_element, size-zero_element).connect(box.subvector(0, zero_element))
|
1497
|
+
cache[:kx_indexed] = [phys.to_a, box.to_a].transpose.inject({}){|hash, (physi, boxi)| hash[physi] = boxi; hash}
|
1497
1498
|
end
|
1498
1499
|
|
1499
1500
|
def box_kx_index(physical_kx_index)
|
1500
1501
|
|
1501
|
-
|
1502
|
+
return kx_indexed[physical_kx_index]
|
1502
1503
|
end
|
1503
1504
|
|
1504
1505
|
def physical_kx_index(box_kx_index)
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1506
|
+
return kx_indexed.key(box_kx_index)
|
1507
|
+
#kx = cache[:kx_gslv] ||= gsl_vector('kx')
|
1508
|
+
#return kx.from_box_order.to_a.index(kx[box_kx_index-1]) + 1
|
1509
|
+
#kx = cache[:kx_gslv] ||= gsl_vector('kx')
|
1510
|
+
#index_of_min_kx = cache[:index_of_min_kx] ||= kx.min_index + 1 # kx.min_index returns a 0-based index
|
1511
|
+
#if box_kx_index < index_of_min_kx
|
1512
|
+
#box_kx_index + (1 + kx.size - index_of_min_kx)
|
1513
|
+
#else
|
1514
|
+
#box_kx_index - (index_of_min_kx - 1)
|
1515
|
+
#end
|
1515
1516
|
end
|
1516
1517
|
|
1517
1518
|
|
1518
|
-
|
1519
|
+
|
1519
1520
|
|
1520
1521
|
def gsl_complex(name, options={})
|
1521
|
-
|
1522
|
-
#
|
1523
|
-
|
1524
|
-
#
|
1525
|
-
|
1526
|
-
|
1527
|
-
#
|
1528
|
-
#
|
1529
|
-
# #
|
1530
|
-
#
|
1531
|
-
#
|
1532
|
-
#
|
1533
|
-
#
|
1534
|
-
#
|
1535
|
-
#
|
1536
|
-
#
|
1537
|
-
#
|
1538
|
-
#
|
1539
|
-
#
|
1540
|
-
#
|
1541
|
-
#
|
1542
|
-
#
|
1543
|
-
# #
|
1544
|
-
# #
|
1545
|
-
#
|
1546
|
-
# #
|
1547
|
-
#
|
1548
|
-
#
|
1549
|
-
#
|
1550
|
-
#
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
|
1557
|
-
end
|
1522
|
+
options = eval(options) if options.class == String
|
1523
|
+
# p @directory
|
1524
|
+
Dir.chdir(@directory) do
|
1525
|
+
# eputs Dir.pwd
|
1526
|
+
case name
|
1527
|
+
when /correcting_phase/
|
1528
|
+
# options.convert_to_index(self, :ky)
|
1529
|
+
# theta0 = (options[:theta0] or 0)
|
1530
|
+
# # p 'options[:ky_index]', options[:ky_index]
|
1531
|
+
# phase_array = NumRu::NetCDF.open("#@directory/#@run_name.out.nc").var('phase').get({"start" => [0, options[:ky_index] - 1, theta0], 'end' => [1, options[:ky_index] - 1, theta0] }).to_a.flatten
|
1532
|
+
# p 'phase_array', phase_array
|
1533
|
+
# thetaelement0 = (list(:theta).key(0.0) - 1).to_i
|
1534
|
+
# p 'list(:theta)[thetaelement0 + 1]', list(:theta)[thetaelement0 + 1]
|
1535
|
+
# p 'thetaelement0', thetaelement0
|
1536
|
+
# p 'theta0 - jump(options)', theta0 - jump(options) % @jtwist
|
1537
|
+
# p 'list(:kx)[2] * (theta0 - jump(options)%@jtwist)', list(:kx)[2] * (theta0 - jump(options)%@jtwist)
|
1538
|
+
# kx_element = list(:kx).key(list(:kx)[2] * (theta0 - jump(options)%@jtwist)) - 1
|
1539
|
+
# at_0 = NumRu::NetCDF.open("#@directory/#@run_name.out.nc").var('phi').get({"start" => [0, thetaelement0, kx_element, options[:ky_index] - 1], 'end' => [1, thetaelement0, kx_element, options[:ky_index] - 1] }).to_a.flatten
|
1540
|
+
# p 'at_0', at_0
|
1541
|
+
# at_0 = GSL::Complex.alloc(at_0)
|
1542
|
+
# p 'at_0', at_0
|
1543
|
+
# return (at_0 / at_0.mag).conj
|
1544
|
+
# # pp 'theta0', theta0
|
1545
|
+
# # pp phase_array[5][theta0]
|
1546
|
+
# return GSL::Complex.alloc(phase_array)
|
1547
|
+
# # new_options = options.dup
|
1548
|
+
# new_options[:imrc] = :real
|
1549
|
+
# thetas = gsl_vector('theta_along_field_line', new_options)
|
1550
|
+
# at_0 = gsl_vector_complex('phi_along_field_line', new_options)[.to_a.index(0.0)]
|
1551
|
+
# p at_0
|
1552
|
+
exit
|
1553
|
+
else
|
1554
|
+
raise CRError.new("Unknown gsl_complex requested: #{name}")
|
1555
|
+
end
|
1556
|
+
# eputs data; gets
|
1557
|
+
end
|
1558
|
+
end
|
1558
1559
|
|
1559
1560
|
# def gsl_matrix(name, options={})
|
1560
|
-
#
|
1561
|
-
#
|
1562
|
-
#
|
1563
|
-
#
|
1564
|
-
#
|
1561
|
+
# if options[:t_index] or options[:frame_index]
|
1562
|
+
# return get_gsl_matrix(name, options)
|
1563
|
+
# else
|
1564
|
+
# return cache[[:gsl_vector, name, options]] ||= get_gsl_matrix(name, options)
|
1565
|
+
# end
|
1565
1566
|
# end
|
1566
1567
|
|
1567
1568
|
|